@coder/pixel-storybook 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -0
  3. package/dist/api.d.ts +56 -0
  4. package/dist/api.js +238 -0
  5. package/dist/bin.d.ts +2 -0
  6. package/dist/bin.js +102 -0
  7. package/dist/checkDifferences.d.ts +63 -0
  8. package/dist/checkDifferences.js +67 -0
  9. package/dist/compare/compare.d.ts +5 -0
  10. package/dist/compare/compare.js +80 -0
  11. package/dist/compare/pixelmatch.d.ts +7 -0
  12. package/dist/compare/pixelmatch.js +46 -0
  13. package/dist/compare/utils.d.ts +2 -0
  14. package/dist/compare/utils.js +18 -0
  15. package/dist/compare/worker.d.ts +1 -0
  16. package/dist/compare/worker.js +6 -0
  17. package/dist/concurrency.d.ts +19 -0
  18. package/dist/concurrency.js +61 -0
  19. package/dist/config.d.ts +3795 -0
  20. package/dist/config.js +472 -0
  21. package/dist/configHelper.d.ts +2 -0
  22. package/dist/configHelper.js +34 -0
  23. package/dist/constants.d.ts +2 -0
  24. package/dist/constants.js +2 -0
  25. package/dist/crawler/storybook.d.ts +51 -0
  26. package/dist/crawler/storybook.js +317 -0
  27. package/dist/crawler/utils.d.ts +6 -0
  28. package/dist/crawler/utils.js +20 -0
  29. package/dist/createShots.d.ts +30 -0
  30. package/dist/createShots.js +54 -0
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +1 -0
  33. package/dist/log.d.ts +26 -0
  34. package/dist/log.js +99 -0
  35. package/dist/runner.d.ts +4 -0
  36. package/dist/runner.js +186 -0
  37. package/dist/schemas.d.ts +174 -0
  38. package/dist/schemas.js +73 -0
  39. package/dist/shard.d.ts +3 -0
  40. package/dist/shard.js +17 -0
  41. package/dist/shots/shots.d.ts +3 -0
  42. package/dist/shots/shots.js +196 -0
  43. package/dist/shots/utils.d.ts +33 -0
  44. package/dist/shots/utils.js +177 -0
  45. package/dist/types.d.ts +12 -0
  46. package/dist/types.js +1 -0
  47. package/dist/upload.d.ts +10 -0
  48. package/dist/upload.js +32 -0
  49. package/dist/uploadStorybook.d.ts +2 -0
  50. package/dist/uploadStorybook.js +56 -0
  51. package/dist/utils.d.ts +50 -0
  52. package/dist/utils.js +194 -0
  53. package/package.json +64 -0
package/dist/config.js ADDED
@@ -0,0 +1,472 @@
1
+ import { existsSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import * as z from 'zod';
4
+ import { defaultShotConcurrency } from './concurrency.js';
5
+ import { loadProjectConfigFile, loadTSProjectConfigFile, } from './configHelper.js';
6
+ import { log } from './log.js';
7
+ import { BrowserSchema, MaskSchema, ShotModeSchema } from './schemas.js';
8
+ const StorybookShotsSchema = z.object({
9
+ /**
10
+ * URL of the Storybook instance or local folder
11
+ * @default 'storybook-static'
12
+ */
13
+ storybookUrl: z.string(),
14
+ /**
15
+ * Define areas for all stories where differences will be ignored
16
+ */
17
+ mask: z.array(MaskSchema).optional(),
18
+ /**
19
+ * Define custom breakpoints for all Storybook shots as width in pixels
20
+ * @default []
21
+ * @example
22
+ * [ 320, 768, 1280 ]
23
+ */
24
+ breakpoints: z.array(z.number()).optional(),
25
+ /**
26
+ * Target specific element on page with a selector
27
+ */
28
+ elementLocator: z.string().optional(),
29
+ /**
30
+ * Wait for a specific selector before taking a screenshot
31
+ * @example '[data-storyloaded]'
32
+ */
33
+ waitForSelector: z.string().optional(),
34
+ });
35
+ const StoryLikeSchema = z.object({
36
+ shotMode: ShotModeSchema,
37
+ id: z.string().optional(),
38
+ kind: z.string().optional(),
39
+ story: z.string().optional(),
40
+ shotName: z.string().optional(),
41
+ parameters: z.record(z.unknown()).optional(),
42
+ filePathBaseline: z.string().optional(),
43
+ filePathCurrent: z.string().optional(),
44
+ filePathDifference: z.string().optional(),
45
+ });
46
+ const ShotItem = z.object({
47
+ shotMode: ShotModeSchema,
48
+ id: z.string(),
49
+ shotName: z.string(),
50
+ url: z.string(),
51
+ filePathBaseline: z.string(),
52
+ filePathCurrent: z.string(),
53
+ filePathDifference: z.string(),
54
+ browserConfig: z.custom().optional(),
55
+ threshold: z.number(),
56
+ waitBeforeScreenshot: z.number().optional(),
57
+ stabilizeBeforeScreenshot: z.boolean().optional(),
58
+ importPath: z.string().optional(),
59
+ mask: z.array(MaskSchema).optional(),
60
+ viewport: z
61
+ .object({
62
+ width: z.number(),
63
+ height: z.number().optional(),
64
+ })
65
+ .optional(),
66
+ breakpoint: z.number().optional(),
67
+ breakpointGroup: z.string().optional(),
68
+ elementLocator: z.string().optional(),
69
+ waitForSelector: z.string().optional(),
70
+ });
71
+ const TimeoutsSchema = z.object({
72
+ /**
73
+ * Timeout for fetching stories
74
+ * @default 30_000
75
+ */
76
+ fetchStories: z.number().default(30_000),
77
+ /**
78
+ * Timeout for loading the state of the page
79
+ * @default 30_000
80
+ */
81
+ loadState: z.number().default(30_000),
82
+ /**
83
+ * Timeout for waiting for network requests to finish
84
+ * @default 30_000
85
+ */
86
+ networkRequests: z.number().default(30_000),
87
+ });
88
+ const BaseConfigSchema = z.object({
89
+ /**
90
+ * Browser to use: chromium, firefox, or webkit
91
+ * @default 'chromium'
92
+ */
93
+ browser: z
94
+ .union([BrowserSchema, z.array(BrowserSchema).default(['chromium'])])
95
+ .default('chromium'),
96
+ /**
97
+ * Enable Storybook mode
98
+ */
99
+ storybookShots: StorybookShotsSchema.optional(),
100
+ /**
101
+ * Path to the current image folder
102
+ * @default '.lostpixel/current/'
103
+ */
104
+ imagePathCurrent: z.string().default('.lostpixel/current/'),
105
+ /**
106
+ * Define custom breakpoints for all tests as width in pixels
107
+ * @default []
108
+ * @example
109
+ * [ 320, 768, 1280 ]
110
+ */
111
+ breakpoints: z.array(z.number()).optional(),
112
+ /**
113
+ * Number of concurrent shots to take. Auto-scales with the number of CPUs
114
+ * available to the process by default (floor `10`, ceiling `32`). Set to
115
+ * `0` to opt back into the auto default from an explicit config.
116
+ * @default auto
117
+ */
118
+ shotConcurrency: z
119
+ .number()
120
+ .nonnegative()
121
+ .default(() => defaultShotConcurrency())
122
+ .transform((value) => (value === 0 ? defaultShotConcurrency() : value)),
123
+ /**
124
+ * Timeouts for various stages of the test
125
+ */
126
+ timeouts: TimeoutsSchema.default({
127
+ fetchStories: 30_000,
128
+ loadState: 30_000,
129
+ networkRequests: 30_000,
130
+ }),
131
+ /**
132
+ * Maximum time to wait before taking a screenshot. When
133
+ * `stabilizeBeforeScreenshot` is `true` (the default), this is the cap on
134
+ * the adaptive stability wait. When `false`, this is the fixed sleep.
135
+ * @default 1_000
136
+ */
137
+ waitBeforeScreenshot: z.number().default(1000),
138
+ /**
139
+ * When `true`, the wait before taking a screenshot is adaptive: lost-pixel
140
+ * waits for web fonts, pending images, one committed frame, and a quiet
141
+ * DOM, bounded above by `waitBeforeScreenshot`. When `false`, falls back
142
+ * to a fixed sleep of `waitBeforeScreenshot` milliseconds.
143
+ * @default true
144
+ */
145
+ stabilizeBeforeScreenshot: z.boolean().default(true),
146
+ /**
147
+ * Time to wait for the first network request to start
148
+ * @default 200
149
+ */
150
+ waitForFirstRequest: z.number().default(200),
151
+ /**
152
+ * Time to wait for the last network request to start
153
+ * @default 1_000
154
+ */
155
+ waitForLastRequest: z.number().default(1000),
156
+ /**
157
+ * Threshold for the difference between the baseline and current image
158
+ *
159
+ * Values between 0 and 1 are interpreted as percentage of the image size
160
+ *
161
+ * Values greater or equal to 1 are interpreted as pixel count.
162
+ * @default 0
163
+ */
164
+ threshold: z.number().default(0),
165
+ /**
166
+ * How often to retry a shot for a stable result
167
+ * @default 0
168
+ */
169
+ flakynessRetries: z.number().default(0),
170
+ /**
171
+ * Time to wait between flakyness retries
172
+ * @default 2_000
173
+ */
174
+ waitBetweenFlakynessRetries: z.number().default(2000),
175
+ /**
176
+ * Global shot filter
177
+ */
178
+ filterShot: z
179
+ .function()
180
+ .args(StoryLikeSchema)
181
+ .returns(z.boolean())
182
+ .optional(),
183
+ /**
184
+ * Shot and file name generator for images
185
+ */
186
+ shotNameGenerator: z
187
+ .function()
188
+ .args(StoryLikeSchema)
189
+ .returns(z.string())
190
+ .optional(),
191
+ /**
192
+ * Configure browser context options
193
+ */
194
+ configureBrowser: z
195
+ .function()
196
+ .args(StoryLikeSchema)
197
+ .returns(z.custom())
198
+ .optional(),
199
+ /**
200
+ * Configure page before screenshot
201
+ */
202
+ beforeScreenshot: z
203
+ .function()
204
+ .args(z.custom(), StoryLikeSchema)
205
+ .returns(z.promise(z.void()))
206
+ .optional(),
207
+ /**
208
+ * Perform actions after screenshot was taken
209
+ */
210
+ afterScreenshot: z
211
+ .function()
212
+ .args(z.custom(), StoryLikeSchema)
213
+ .returns(z.promise(z.void()))
214
+ .optional(),
215
+ /**
216
+ * Launch options for the browser
217
+ */
218
+ browserLaunchOptions: z
219
+ .object({
220
+ chromium: z.custom().optional(),
221
+ firefox: z.custom().optional(),
222
+ webkit: z.custom().optional(),
223
+ })
224
+ .optional(),
225
+ });
226
+ export const PlatformModeConfigSchema = BaseConfigSchema.extend({
227
+ /**
228
+ * URL of the Lost Pixel API endpoint
229
+ * @default 'https://api.lost-pixel.com'
230
+ */
231
+ lostPixelPlatform: z.string().default('https://api.lost-pixel.com'),
232
+ /**
233
+ * API key for the Lost Pixel platform
234
+ */
235
+ apiKey: z.string(),
236
+ /**
237
+ * Project ID
238
+ */
239
+ lostPixelProjectId: z.string(),
240
+ /**
241
+ * CI build ID
242
+ */
243
+ ciBuildId: z
244
+ .string({
245
+ required_error: 'Required (can be set via `CI_BUILD_ID` env variable)',
246
+ })
247
+ // @ts-expect-error If not set, it will be caught during config validation
248
+ .default(process.env.CI_BUILD_ID),
249
+ /**
250
+ * CI build number
251
+ */
252
+ ciBuildNumber: z
253
+ .string({
254
+ required_error: 'Required (can be set via `CI_BUILD_NUMBER` env variable)',
255
+ })
256
+ // @ts-expect-error If not set, it will be caught during config validation
257
+ .default(process.env.CI_BUILD_NUMBER),
258
+ /**
259
+ * Git repository name (e.g. 'lost-pixel/lost-pixel-storybook')
260
+ */
261
+ repository: z
262
+ .string({
263
+ required_error: 'Required (can be set via `REPOSITORY` env variable)',
264
+ })
265
+ // @ts-expect-error If not set, it will be caught during config validation
266
+ .default(process.env.REPOSITORY),
267
+ /**
268
+ * Git branch name (e.g. 'main')
269
+ */
270
+ commitRefName: z
271
+ .string({
272
+ required_error: 'Required (can be set via `COMMIT_REF_NAME` env variable)',
273
+ })
274
+ // @ts-expect-error If not set, it will be caught during config validation
275
+ .default(process.env.COMMIT_REF_NAME),
276
+ /**
277
+ * Git commit SHA (e.g. 'b9b8b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9')
278
+ */
279
+ commitHash: z
280
+ .string({
281
+ required_error: 'Required (can be set via `COMMIT_HASH` env variable)',
282
+ })
283
+ // @ts-expect-error If not set, it will be caught during config validation
284
+ .default(process.env.COMMIT_HASH),
285
+ /**
286
+ * File path to event.json file
287
+ */
288
+ eventFilePath: z.string().optional(),
289
+ /**
290
+ * Whether to set the GitHub status check on process start or not
291
+ *
292
+ * Setting this option to `true` makes only sense if the repository settings have pending status checks disabled
293
+ * @default false
294
+ */
295
+ setPendingStatusCheck: z.boolean().default(false),
296
+ /**
297
+ * Skip taking screenshots and only upload existing images to the platform.
298
+ *
299
+ * When enabled, lost-pixel reads `.png` files from `imagePathCurrent`
300
+ * instead of launching a browser. Useful when screenshots are produced
301
+ * by an external process.
302
+ * @default false
303
+ */
304
+ uploadOnly: z.boolean().default(false),
305
+ });
306
+ export const GenerateOnlyModeConfigSchema = BaseConfigSchema.extend({
307
+ /**
308
+ * Run in local mode
309
+ * @deprecated Defaults to running in generateOnly mode
310
+ */
311
+ generateOnly: z.boolean().optional(),
312
+ /**
313
+ * Skip taking screenshots and only upload them to the platform.
314
+ */
315
+ uploadOnly: z.boolean().optional(),
316
+ /**
317
+ * Flag that decides if process should exit if a difference is found
318
+ */
319
+ failOnDifference: z.boolean().optional(),
320
+ /**
321
+ * Path to the baseline image folder
322
+ * @default '.lostpixel/baseline/'
323
+ */
324
+ imagePathBaseline: z.string().default('.lostpixel/baseline/'),
325
+ /**
326
+ * Path to the difference image folder
327
+ * @default '.lostpixel/difference/'
328
+ */
329
+ imagePathDifference: z.string().default('.lostpixel/difference/'),
330
+ /**
331
+ * Number of concurrent screenshots to compare
332
+ * @default 10
333
+ */
334
+ compareConcurrency: z.number().default(10),
335
+ /**
336
+ * Which comparison engine to use for diffing images
337
+ * @default 'pixelmatch'
338
+ */
339
+ compareEngine: z.enum(['pixelmatch', 'odiff']).default('pixelmatch'),
340
+ /**
341
+ * Filter stories to take screenshots of and run comparisons on (existing shots remain untouched)
342
+ */
343
+ filterItemsToCheck: z
344
+ .function()
345
+ .args(ShotItem)
346
+ .returns(z.boolean())
347
+ .optional(),
348
+ });
349
+ export const ConfigSchema = z.union([
350
+ PlatformModeConfigSchema,
351
+ GenerateOnlyModeConfigSchema,
352
+ ]);
353
+ // use partial() specifically for the inferred type
354
+ export const FlexibleConfigSchema = z.union([
355
+ PlatformModeConfigSchema.extend({
356
+ timeouts: TimeoutsSchema.partial(),
357
+ }).partial(),
358
+ GenerateOnlyModeConfigSchema.extend({
359
+ timeouts: TimeoutsSchema.partial(),
360
+ }).partial(),
361
+ ]);
362
+ export let config;
363
+ export const isPlatformModeConfig = (userConfig) => ('apiKey' in userConfig && typeof userConfig.apiKey === 'string') ||
364
+ ('lostPixelProjectId' in userConfig &&
365
+ typeof userConfig.lostPixelProjectId === 'string');
366
+ const printConfigErrors = (error) => {
367
+ for (const issue of error.issues) {
368
+ log.process('error', 'config', [
369
+ 'Configuration error:',
370
+ ` - Path: ${issue.path.join('.')}`,
371
+ ` - Message: ${issue.message}`,
372
+ ].join('\n'));
373
+ }
374
+ };
375
+ export const parseConfig = (userConfig) => {
376
+ if (isPlatformModeConfig(userConfig)) {
377
+ const platformCheck = PlatformModeConfigSchema.safeParse(userConfig);
378
+ if (platformCheck.success) {
379
+ return platformCheck.data;
380
+ }
381
+ printConfigErrors(platformCheck.error);
382
+ }
383
+ else {
384
+ const generateOnlyCheck = GenerateOnlyModeConfigSchema.safeParse(userConfig);
385
+ if (generateOnlyCheck.success) {
386
+ return generateOnlyCheck.data;
387
+ }
388
+ printConfigErrors(generateOnlyCheck.error);
389
+ }
390
+ throw new Error('Configuration error');
391
+ };
392
+ const configDirBase = process.env.LOST_PIXEL_CONFIG_DIR ?? process.cwd();
393
+ const configFileNameBase = path.join(path.isAbsolute(configDirBase) ? '' : process.cwd(), configDirBase, 'lostpixel.config');
394
+ const loadProjectConfig = async () => {
395
+ log.process('info', 'config', 'Loading project config ...');
396
+ log.process('info', 'config', 'Current working directory:', process.cwd());
397
+ if (process.env.LOST_PIXEL_CONFIG_DIR) {
398
+ log.process('info', 'config', 'Defined config directory:', process.env.LOST_PIXEL_CONFIG_DIR);
399
+ }
400
+ const configExtensions = ['ts', 'js', 'cjs', 'mjs'];
401
+ const configExtensionsString = configExtensions.join('|');
402
+ log.process('info', 'config', 'Looking for config file:', `${configFileNameBase}.(${configExtensionsString})`);
403
+ const configFiles = configExtensions
404
+ .map((ext) => `${configFileNameBase}.${ext}`)
405
+ .filter((file) => existsSync(file));
406
+ if (configFiles.length === 0) {
407
+ log.process('error', 'config', `Couldn't find project config file 'lostpixel.config.(${configExtensionsString})'`);
408
+ process.exit(1);
409
+ }
410
+ if (configFiles.length > 1) {
411
+ log.process('info', 'config', '✅ Found multiple config files, taking:', configFiles[0]);
412
+ }
413
+ else {
414
+ log.process('info', 'config', '✅ Found config file:', configFiles[0]);
415
+ }
416
+ const configFile = configFiles[0];
417
+ try {
418
+ const imported = (await loadProjectConfigFile(configFile));
419
+ return imported;
420
+ }
421
+ catch {
422
+ log.process('error', 'config', 'Loading config using ESBuild failed, using fallback option');
423
+ try {
424
+ if (existsSync(`${configFileNameBase}.js`)) {
425
+ const projectConfig = (await import(`${configFileNameBase}.js`));
426
+ const resolved = projectConfig?.default ?? projectConfig;
427
+ log.process('info', 'config', '✅ Successfully loaded configuration from:', `${configFileNameBase}.js`);
428
+ return resolved;
429
+ }
430
+ if (existsSync(`${configFileNameBase}.ts`)) {
431
+ const imported = (await loadTSProjectConfigFile(configFile));
432
+ log.process('info', 'config', '✅ Successfully loaded configuration from:', `${configFileNameBase}.ts`);
433
+ return imported;
434
+ }
435
+ log.process('error', 'config', "Couldn't find project config file 'lostpixel.config.js'");
436
+ process.exit(1);
437
+ }
438
+ catch (error) {
439
+ log.process('error', 'config', `Failed to load config file: ${configFile}`);
440
+ log.process('error', 'config', error);
441
+ process.exit(1);
442
+ }
443
+ }
444
+ };
445
+ export const configure = async ({ customProjectConfig, localDebugMode, }) => {
446
+ if (customProjectConfig) {
447
+ config = parseConfig(customProjectConfig);
448
+ return;
449
+ }
450
+ let loadedProjectConfig = await loadProjectConfig();
451
+ if (localDebugMode) {
452
+ let localDebugConfig = loadedProjectConfig;
453
+ if (isPlatformModeConfig(loadedProjectConfig)) {
454
+ localDebugConfig = {
455
+ ...loadedProjectConfig,
456
+ generateOnly: true,
457
+ // @ts-expect-error Force it into generateOnly mode by dropping the platform specific properties
458
+ lostPixelProjectId: undefined,
459
+ // @ts-expect-error Force it into generateOnly mode by dropping the platform specific properties
460
+ apiKey: undefined,
461
+ };
462
+ }
463
+ loadedProjectConfig = localDebugConfig;
464
+ }
465
+ // Default to Storybook mode if no mode is defined
466
+ if (!loadedProjectConfig.storybookShots) {
467
+ loadedProjectConfig.storybookShots = {
468
+ storybookUrl: 'storybook-static',
469
+ };
470
+ }
471
+ config = parseConfig(loadedProjectConfig);
472
+ };
@@ -0,0 +1,2 @@
1
+ export declare const loadProjectConfigFile: (configFilepath: string) => Promise<unknown>;
2
+ export declare const loadTSProjectConfigFile: (configFilepath: string) => Promise<unknown>;
@@ -0,0 +1,34 @@
1
+ import { log } from './log.js';
2
+ export const loadProjectConfigFile = async (configFilepath) => {
3
+ try {
4
+ const mod = (await import(configFilepath));
5
+ return mod?.default ?? mod?.config ?? mod;
6
+ }
7
+ catch (error) {
8
+ log.process('error', 'config', error);
9
+ throw error;
10
+ }
11
+ };
12
+ let unregisterTsx;
13
+ const setupTsx = async () => {
14
+ if (unregisterTsx) {
15
+ return;
16
+ }
17
+ try {
18
+ const tsx = await import('tsx/esm/api');
19
+ unregisterTsx = tsx.register();
20
+ }
21
+ catch (error) {
22
+ // @ts-expect-error Error type definition is missing 'code'
23
+ if (['ERR_MODULE_NOT_FOUND', 'MODULE_NOT_FOUND'].includes(error.code)) {
24
+ log.process('error', 'config', `Please install "tsx" to use a TypeScript configuration file`);
25
+ process.exit(1);
26
+ }
27
+ process.exit(1);
28
+ }
29
+ };
30
+ export const loadTSProjectConfigFile = async (configFilepath) => {
31
+ await setupTsx();
32
+ const imported = (await import(configFilepath));
33
+ return imported?.default ?? imported?.config;
34
+ };
@@ -0,0 +1,2 @@
1
+ export declare const notSupported = "not supported";
2
+ export declare const MEDIA_UPLOAD_CONCURRENCY = 10;
@@ -0,0 +1,2 @@
1
+ export const notSupported = 'not supported';
2
+ export const MEDIA_UPLOAD_CONCURRENCY = 10;
@@ -0,0 +1,51 @@
1
+ import type { BrowserContext, BrowserType } from 'playwright-core';
2
+ import type { Mask, ShotItem } from '../types.js';
3
+ type ExtraShots = {
4
+ name?: string;
5
+ args?: Record<string, unknown>;
6
+ prefix?: string;
7
+ suffix?: string;
8
+ };
9
+ export type StoryParameters = {
10
+ lostpixel?: {
11
+ disable?: boolean;
12
+ threshold?: number;
13
+ waitBeforeScreenshot?: number;
14
+ stabilizeBeforeScreenshot?: boolean;
15
+ mask?: Mask[];
16
+ breakpoints?: number[];
17
+ args?: Record<string, unknown>;
18
+ extraShots?: ExtraShots[];
19
+ elementLocator?: string;
20
+ };
21
+ viewport?: {
22
+ width?: number;
23
+ height?: number;
24
+ };
25
+ fileName?: string;
26
+ };
27
+ export type Story = {
28
+ id: string;
29
+ kind: string;
30
+ story: string;
31
+ name?: string;
32
+ title?: string;
33
+ importPath?: string;
34
+ parameters?: StoryParameters & {
35
+ storyshots?: {
36
+ disable?: boolean;
37
+ };
38
+ };
39
+ };
40
+ type CrawlerResult = {
41
+ stories: Story[] | undefined;
42
+ };
43
+ export declare const getStoryBookUrl: (url: string) => string;
44
+ export declare const getIframeUrl: (url: string) => string;
45
+ export declare const collectStoriesViaWindowApi: (context: BrowserContext, url: string, isIframeUrl?: boolean) => Promise<CrawlerResult>;
46
+ export declare const collectStoriesViaStoriesJson: (context: BrowserContext, url: string) => Promise<{
47
+ stories: Story[];
48
+ }>;
49
+ export declare const collectStories: (url: string) => Promise<CrawlerResult>;
50
+ export declare const generateStorybookShotItems: (baseUrl: string, stories: Story[], mask?: Mask[], modeBreakpoints?: number[], browser?: BrowserType) => ShotItem[];
51
+ export {};