@applitools/eyes-storybook 3.57.2 → 3.58.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.
- package/CHANGELOG.md +55 -0
- package/dist/index.d.ts +209 -2
- package/package.json +5 -5
- package/src/cli.js +9 -0
- package/src/configParams.js +8 -8
- package/src/defaultConfig.js +3 -0
- package/src/eyesStorybook.js +11 -0
- package/src/filterStories.js +10 -1
- package/src/generateConfig.js +9 -0
- package/src/index.ts +308 -31
- package/src/utils/config-validator.js +25 -20
- package/src/yargsOptions.js +21 -0
- package/dist/getStoryByIndex.js +0 -138
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,60 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.58.0](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.57.2...js/eyes-storybook@3.58.0) (2025-08-21)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* enhance storybook tsdocs and types | AD-10816 ([#3180](https://github.com/Applitools-Dev/sdk/issues/3180)) ([df2c28d](https://github.com/Applitools-Dev/sdk/commit/df2c28d7f3d661596d0f8d6f9389593527bddc71))
|
|
9
|
+
* storybook sharding | AD-10879 ([#3176](https://github.com/Applitools-Dev/sdk/issues/3176)) ([73e5f3f](https://github.com/Applitools-Dev/sdk/commit/73e5f3fce69044696a2457deb82f576542a2589e))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* configuration parameters and documentation | AD-10816 ([#3181](https://github.com/Applitools-Dev/sdk/issues/3181)) ([fded470](https://github.com/Applitools-Dev/sdk/commit/fded4705d7fea0c1b523dceec5f1128c68c1d76d))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Code Refactoring
|
|
18
|
+
|
|
19
|
+
* remove dist folder from eyes-sb ([#3182](https://github.com/Applitools-Dev/sdk/issues/3182)) ([a2696b9](https://github.com/Applitools-Dev/sdk/commit/a2696b969bbc7b686d6ebe03d45b9400e27f65ff))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Dependencies
|
|
23
|
+
|
|
24
|
+
* @applitools/dom-snapshot bumped to 4.13.3
|
|
25
|
+
|
|
26
|
+
* @applitools/socket bumped to 1.3.3
|
|
27
|
+
#### Bug Fixes
|
|
28
|
+
|
|
29
|
+
* tunnel uncaught error | FLD-3356 ([#3128](https://github.com/Applitools-Dev/sdk/issues/3128)) ([ed5fb8a](https://github.com/Applitools-Dev/sdk/commit/ed5fb8aad596ec0d8b45a89077a7765c24ae8a8e))
|
|
30
|
+
* @applitools/driver bumped to 1.23.3
|
|
31
|
+
#### Bug Fixes
|
|
32
|
+
|
|
33
|
+
* make orientation more robust | FLD-3470 ([#3166](https://github.com/Applitools-Dev/sdk/issues/3166)) ([3745427](https://github.com/Applitools-Dev/sdk/commit/37454279234b085dc9a159077b3f278cdccc203a))
|
|
34
|
+
* @applitools/spec-driver-webdriver bumped to 1.4.3
|
|
35
|
+
|
|
36
|
+
* @applitools/spec-driver-selenium bumped to 1.7.3
|
|
37
|
+
|
|
38
|
+
* @applitools/spec-driver-puppeteer bumped to 1.6.3
|
|
39
|
+
|
|
40
|
+
* @applitools/screenshoter bumped to 3.12.3
|
|
41
|
+
|
|
42
|
+
* @applitools/nml-client bumped to 1.11.3
|
|
43
|
+
|
|
44
|
+
* @applitools/tunnel-client bumped to 1.10.4
|
|
45
|
+
#### Bug Fixes
|
|
46
|
+
|
|
47
|
+
* tunnel uncaught error | FLD-3356 ([#3128](https://github.com/Applitools-Dev/sdk/issues/3128)) ([ed5fb8a](https://github.com/Applitools-Dev/sdk/commit/ed5fb8aad596ec0d8b45a89077a7765c24ae8a8e))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
* @applitools/ec-client bumped to 1.12.4
|
|
52
|
+
|
|
53
|
+
* @applitools/core bumped to 4.44.4
|
|
54
|
+
|
|
55
|
+
* @applitools/eyes bumped to 1.36.2
|
|
56
|
+
|
|
57
|
+
|
|
3
58
|
## [3.57.2](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.57.1...js/eyes-storybook@3.57.2) (2025-08-12)
|
|
4
59
|
|
|
5
60
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,39 +1,246 @@
|
|
|
1
1
|
import type { ConfigurationPlain, DesktopBrowserInfo, ChromeEmulationInfo, IOSDeviceInfo, IOSMultiDeviceInfo } from '@applitools/eyes';
|
|
2
|
+
type irrelevantToStorybook = 'waitBeforeScreenshots' | 'agentId' | 'captureStatusBar' | 'concurrentSessions' | 'connectionTimeout' | 'debugScreenshots' | 'defaultMatchSettings' | 'disableNMLUrlCache' | 'forceFullPageScreenshot' | 'hideCaret' | 'hideScrollbars' | 'hostApp' | 'hostAppInfo' | 'hostOS' | 'hostOSInfo' | 'ignoreBaseline' | 'ignoreCaret' | 'latestCommitInfo' | 'isDisabled' | 'matchTimeout' | 'mobileOptions' | 'removeSession' | 'rotation' | 'scaleRatio' | 'scrollRootElement' | 'sessionType' | 'stitchMode' | 'stitchOverlap' | 'viewportSize';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
+
* Configuration options for Applitools Eyes Storybook integration.
|
|
5
|
+
*
|
|
6
|
+
* This configuration can be specified in three ways:
|
|
7
|
+
* - Command line arguments
|
|
8
|
+
* - Environment variables (uppercase with APPLITOOLS_ prefix)
|
|
9
|
+
* - applitools.config.js file (CommonJS module export)
|
|
10
|
+
*
|
|
11
|
+
* Environment variables override applitools.config.js values.
|
|
12
|
+
*
|
|
13
|
+
* @see https://applitools.com/tutorials/sdks/storybook/config
|
|
4
14
|
*/
|
|
5
|
-
export type ApplitoolsConfig = Omit<ConfigurationPlain, '
|
|
15
|
+
export type ApplitoolsConfig = Omit<ConfigurationPlain, irrelevantToStorybook | 'waitBeforeCapture'> & {
|
|
16
|
+
/**
|
|
17
|
+
* URL for Storybook instance.
|
|
18
|
+
* @example 'http://localhost:9001'
|
|
19
|
+
*/
|
|
6
20
|
storybookUrl?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Port to run Storybook on.
|
|
23
|
+
* @default 9000
|
|
24
|
+
*/
|
|
7
25
|
storybookPort?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Host to run Storybook on.
|
|
28
|
+
* @default 'localhost'
|
|
29
|
+
*/
|
|
8
30
|
storybookHost?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Path to Storybook's config folder.
|
|
33
|
+
* @default '.storybook'
|
|
34
|
+
*/
|
|
9
35
|
storybookConfigDir?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Path to Storybook's static files folder.
|
|
38
|
+
*/
|
|
10
39
|
storybookStaticDir?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Whether to display Storybook output in console.
|
|
42
|
+
*/
|
|
11
43
|
showStorybookOutput?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Set to true if running the SDK in Docker to resolve potential issues.
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
12
48
|
runInDocker?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Predicate function, string, or regex specifying which stories should be visually tested.
|
|
51
|
+
* Visual baselines will be created only for specified components.
|
|
52
|
+
* Function receives object with name, kind, storyTitle, and parameters properties.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // Exclude stories with names starting with [SKIP]
|
|
56
|
+
* ({name, kind, storyTitle, parameters}) => !/^\\[SKIP\\]/.test(name)
|
|
57
|
+
*
|
|
58
|
+
* @default true (includes all stories)
|
|
59
|
+
*/
|
|
13
60
|
include?: ((story: {
|
|
14
61
|
name: string;
|
|
15
62
|
kind: string;
|
|
16
63
|
storyTitle?: string;
|
|
17
64
|
parameters?: any;
|
|
18
65
|
}) => boolean) | string | RegExp;
|
|
66
|
+
/**
|
|
67
|
+
* Specifies additional variations for all or some stories (e.g., RTL).
|
|
68
|
+
*/
|
|
19
69
|
variations?: Record<string, any>;
|
|
70
|
+
/**
|
|
71
|
+
* Time in milliseconds that Eyes-Storybook waits for Storybook to load.
|
|
72
|
+
* For Storybook versions 2 and 3, this is also the acknowledgment time.
|
|
73
|
+
* Recommended to use small values (e.g., 3000) for versions 2-3.
|
|
74
|
+
*
|
|
75
|
+
* @default 60000
|
|
76
|
+
*/
|
|
20
77
|
readStoriesTimeout?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Low-level options to send to puppeteer.launch().
|
|
80
|
+
* Use with great care.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* { args: ['--no-sandbox'], headless: false, devtools: true }
|
|
84
|
+
*/
|
|
21
85
|
puppeteerOptions?: Record<string, any>;
|
|
86
|
+
/**
|
|
87
|
+
* Options to send to page.setExtraHTTPHeaders().
|
|
88
|
+
* @see https://pptr.dev/api/puppeteer.page.setextrahttpheaders
|
|
89
|
+
*/
|
|
22
90
|
puppeteerExtraHTTPHeaders?: Record<string, string>;
|
|
91
|
+
/**
|
|
92
|
+
* When to consider navigation finished.
|
|
93
|
+
* @default 'load'
|
|
94
|
+
*/
|
|
23
95
|
navigationWaitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
|
|
96
|
+
/**
|
|
97
|
+
* Cache all requests from browser for faster performance.
|
|
98
|
+
* @default false
|
|
99
|
+
*/
|
|
24
100
|
browserCacheRequests?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Array of browser configurations for screenshot generation.
|
|
103
|
+
* Defines size and browser type for generated screenshots.
|
|
104
|
+
*
|
|
105
|
+
* @default [{ width: 1024, height: 768, name: 'chrome' }]
|
|
106
|
+
*/
|
|
25
107
|
browser?: (DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)[];
|
|
108
|
+
/**
|
|
109
|
+
* Name for the environment in which the application under test is running.
|
|
110
|
+
*/
|
|
26
111
|
envName?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Maximum number of tests that can run concurrently.
|
|
114
|
+
* Default value is the allowed amount for free accounts.
|
|
115
|
+
* For paid accounts, set to your account quota.
|
|
116
|
+
*
|
|
117
|
+
* @default 5
|
|
118
|
+
*/
|
|
27
119
|
testConcurrency?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Whether to display logs of the Eyes-Storybook plugin.
|
|
122
|
+
* @default false
|
|
123
|
+
*/
|
|
28
124
|
showLogs?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* If tests failed or have visual differences, close with non-zero exit code.
|
|
127
|
+
* @default true
|
|
128
|
+
*/
|
|
29
129
|
exitcode?: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Array of regions to ignore when comparing checkpoint with baseline screenshot.
|
|
132
|
+
*/
|
|
30
133
|
ignoreRegions?: any[];
|
|
134
|
+
/**
|
|
135
|
+
* Array of regions to consider as floating when comparing checkpoint with baseline.
|
|
136
|
+
*/
|
|
31
137
|
floatingRegions?: any[];
|
|
138
|
+
/**
|
|
139
|
+
* Array of regions to consider as match level Layout when comparing screenshots.
|
|
140
|
+
*/
|
|
32
141
|
layoutRegions?: any[];
|
|
142
|
+
/**
|
|
143
|
+
* Array of regions to consider as match level Strict when comparing screenshots.
|
|
144
|
+
*/
|
|
33
145
|
strictRegions?: any[];
|
|
146
|
+
/**
|
|
147
|
+
* Array of regions to consider as match level Content when comparing screenshots.
|
|
148
|
+
*/
|
|
34
149
|
contentRegions?: any[];
|
|
150
|
+
/**
|
|
151
|
+
* Array of regions to validate accessibility according to configured accessibilityValidation.
|
|
152
|
+
*/
|
|
35
153
|
accessibilityRegions?: any[];
|
|
154
|
+
/**
|
|
155
|
+
* Directory path for JSON results file.
|
|
156
|
+
* If set, creates eyes.json file with test results.
|
|
157
|
+
*/
|
|
36
158
|
jsonFilePath?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Directory path for TAP results file.
|
|
161
|
+
* If set, creates eyes.tap file with test results.
|
|
162
|
+
*/
|
|
37
163
|
tapFilePath?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Directory path for XUnit XML results file.
|
|
166
|
+
* If set, creates eyes.xml file with test results.
|
|
167
|
+
*/
|
|
38
168
|
xmlFilePath?: string;
|
|
169
|
+
/**
|
|
170
|
+
* Selector, function, or timeout to wait before capturing.
|
|
171
|
+
*
|
|
172
|
+
* * number: Milliseconds to wait before capturing.
|
|
173
|
+
* * string: CSS selector to wait for before capturing.
|
|
174
|
+
* * function: Predicate or async function to wait for before capturing.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* waitBeforeCapture: '#container.ready',
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* waitBeforeCapture: () => document.querySelector('#container.ready') !== null,
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* waitBeforeCapture: 3_000
|
|
184
|
+
*
|
|
185
|
+
* @see https://applitools.com/tutorials/sdks/storybook/component-config#waitBeforeCapture
|
|
186
|
+
*/
|
|
187
|
+
waitBeforeCapture?: number | string | (() => boolean | Promise<boolean>);
|
|
188
|
+
/**
|
|
189
|
+
* Unique identifier for the batch of tests - set to the same value if you want to group tests together.
|
|
190
|
+
*/
|
|
191
|
+
batchId?: string;
|
|
192
|
+
/**
|
|
193
|
+
* Name for the batch of tests - will appear in the Eyes dashboard.
|
|
194
|
+
*/
|
|
195
|
+
batchName?: string;
|
|
196
|
+
/**
|
|
197
|
+
* Sequence name for the batch of tests - will appear in the Eyes dashboard (in the 'insights' page and in the batch details).
|
|
198
|
+
*/
|
|
199
|
+
batchSequenceName?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Name for the baseline branch - use it if you want to compare with a specific branch that is different from the current branch.
|
|
202
|
+
*
|
|
203
|
+
* @see for more information and recommendations regarding baseline branches, see the [documentation](https://applitools.com/tutorials/concepts/best-practices/branching).
|
|
204
|
+
*/
|
|
205
|
+
baselineBranchName?: string;
|
|
206
|
+
/**
|
|
207
|
+
* Dry run - if true, no actual visual testing will be performed.
|
|
208
|
+
* @default false
|
|
209
|
+
*/
|
|
210
|
+
isDisabled?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Whether to ignore the baseline when comparing with the checkpoint (will make all checkpoints `new`)
|
|
213
|
+
* @default false
|
|
214
|
+
*/
|
|
215
|
+
ignoreBaseline?: boolean;
|
|
216
|
+
/**
|
|
217
|
+
* Settings for accessibility validation.
|
|
218
|
+
*/
|
|
219
|
+
accessibilitySettings?: {
|
|
220
|
+
/**
|
|
221
|
+
* Level of accessibility validation to perform.
|
|
222
|
+
*/
|
|
223
|
+
level?: 'AA' | 'AAA';
|
|
224
|
+
/**
|
|
225
|
+
* Array of specific accessibility guidelines to check.
|
|
226
|
+
*/
|
|
227
|
+
guidelinesVersion?: "WCAG_2_0" | "WCAG_2_1";
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* Whether to notify when the test is complete (requires to turn on notifications in the Applitools dashboard).
|
|
231
|
+
* @see https://applitools.com/tutorials/integrations/chat-&-notifications/email
|
|
232
|
+
*/
|
|
233
|
+
notifyOnCompletion?: boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Whether to show browser logs in the test results.
|
|
236
|
+
* @default false
|
|
237
|
+
*/
|
|
238
|
+
showBrowserLogs?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* A string formatted as `<ShardIndex>/<TotalShards>` to enable test sharding (running tests in parallel).
|
|
241
|
+
* @default undefined
|
|
242
|
+
*/
|
|
243
|
+
shard?: string;
|
|
39
244
|
};
|
|
245
|
+
export type configKeys = keyof ApplitoolsConfig;
|
|
246
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-storybook",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.58.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"applitools",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"up:framework": "cd test/fixtures/storybook-versions/${APPLITOOLS_FRAMEWORK_VERSION} && npm ci"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@applitools/core": "4.44.
|
|
62
|
-
"@applitools/driver": "1.23.
|
|
63
|
-
"@applitools/eyes": "1.36.
|
|
61
|
+
"@applitools/core": "4.44.4",
|
|
62
|
+
"@applitools/driver": "1.23.3",
|
|
63
|
+
"@applitools/eyes": "1.36.2",
|
|
64
64
|
"@applitools/functional-commons": "1.6.0",
|
|
65
65
|
"@applitools/logger": "2.2.2",
|
|
66
66
|
"@applitools/monitoring-commons": "1.0.19",
|
|
67
|
-
"@applitools/spec-driver-puppeteer": "1.6.
|
|
67
|
+
"@applitools/spec-driver-puppeteer": "1.6.3",
|
|
68
68
|
"@applitools/ufg-client": "1.17.2",
|
|
69
69
|
"@applitools/utils": "1.11.1",
|
|
70
70
|
"@inquirer/prompts": "7.0.1",
|
package/src/cli.js
CHANGED
|
@@ -32,6 +32,15 @@ const {performance, timeItAsync} = makeTiming();
|
|
|
32
32
|
|
|
33
33
|
console.log(`Using @applitools/eyes-storybook version ${VERSION}.\n`);
|
|
34
34
|
const config = generateConfig({argv, defaultConfig, externalConfigParams});
|
|
35
|
+
|
|
36
|
+
if (config.shard) {
|
|
37
|
+
console.log(`Running with shard: ${config.shard.current}/${config.shard.total}`);
|
|
38
|
+
// Log concurrency and shard configuration to console
|
|
39
|
+
if (config.testConcurrency && config.testConcurrency !== 5) {
|
|
40
|
+
console.log(`this shard has concurrency of ${config.testConcurrency} parallel tests`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
const logger = makeLogger({level: config.showLogs ? 'info' : 'silent', label: 'eyes'});
|
|
36
45
|
await validateAndPopulateConfig({
|
|
37
46
|
config,
|
package/src/configParams.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @type {Partial<(
|
|
6
|
+
* import('./index').configKeys
|
|
7
|
+
* | 'concurrency'
|
|
8
|
+
* )[]>}
|
|
9
|
+
*/
|
|
3
10
|
const configParams = [
|
|
4
11
|
'appName',
|
|
5
12
|
'testName',
|
|
6
13
|
'displayName',
|
|
7
14
|
'browser',
|
|
8
|
-
'url',
|
|
9
15
|
'apiKey',
|
|
10
16
|
'showLogs',
|
|
11
17
|
'batch',
|
|
12
18
|
'batchId',
|
|
13
19
|
'batchName',
|
|
14
20
|
'batchSequenceName',
|
|
15
|
-
'batchSequence',
|
|
16
21
|
'properties',
|
|
17
22
|
'baselineBranchName',
|
|
18
|
-
'baselineBranch',
|
|
19
23
|
'baselineEnvName',
|
|
20
|
-
'baselineName',
|
|
21
24
|
'envName',
|
|
22
|
-
'ignoreCaret',
|
|
23
25
|
'isDisabled',
|
|
24
26
|
'matchLevel',
|
|
25
27
|
'parentBranchName',
|
|
26
|
-
'parentBranch',
|
|
27
28
|
'branchName',
|
|
28
|
-
'branch',
|
|
29
29
|
'proxy',
|
|
30
30
|
'autProxy',
|
|
31
31
|
'saveDiffs',
|
|
@@ -41,9 +41,9 @@ const configParams = [
|
|
|
41
41
|
'ignoreDisplacements',
|
|
42
42
|
'accessibilitySettings',
|
|
43
43
|
'notifyOnCompletion',
|
|
44
|
-
'batchNotify',
|
|
45
44
|
'dontCloseBatches',
|
|
46
45
|
'showBrowserLogs',
|
|
46
|
+
'shard',
|
|
47
47
|
];
|
|
48
48
|
|
|
49
49
|
module.exports = {configParams};
|
package/src/defaultConfig.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
@@ -23,4 +24,6 @@ module.exports = {
|
|
|
23
24
|
browserRequestsTimeout: undefined,
|
|
24
25
|
browserHeadersOverride: undefined,
|
|
25
26
|
browserCacheRequests: undefined,
|
|
27
|
+
showBrowserLogs: undefined,
|
|
28
|
+
shard: undefined,
|
|
26
29
|
};
|
package/src/eyesStorybook.js
CHANGED
|
@@ -138,6 +138,17 @@ async function eyesStorybook({
|
|
|
138
138
|
const stories = await getStoriesWithSpinner();
|
|
139
139
|
|
|
140
140
|
const filteredStories = filterStories({stories, config});
|
|
141
|
+
|
|
142
|
+
// Log filtering and sharding results
|
|
143
|
+
logger.log(`${stories.length} total stories found`);
|
|
144
|
+
if (config.shard) {
|
|
145
|
+
logger.log(
|
|
146
|
+
`${filteredStories.length} stories after filtering and sharding (shard ${config.shard.current}/${config.shard.total})`,
|
|
147
|
+
);
|
|
148
|
+
} else {
|
|
149
|
+
logger.log(`${filteredStories.length} stories after filtering`);
|
|
150
|
+
}
|
|
151
|
+
|
|
141
152
|
const storiesIncludingVariations = addVariationStories({
|
|
142
153
|
stories: filteredStories,
|
|
143
154
|
config,
|
package/src/filterStories.js
CHANGED
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
const getStoryTitle = require('./getStoryTitle');
|
|
3
3
|
|
|
4
4
|
function filterStories({stories, config}) {
|
|
5
|
-
|
|
5
|
+
// Apply existing filters first
|
|
6
|
+
let filteredStories = stories.filter(story => filterStory(story, config));
|
|
7
|
+
|
|
8
|
+
// Apply sharding after other filters
|
|
9
|
+
if (config.shard) {
|
|
10
|
+
const {current, total} = config.shard;
|
|
11
|
+
filteredStories = filteredStories.filter((_story, index) => index % total === current - 1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return filteredStories;
|
|
6
15
|
}
|
|
7
16
|
|
|
8
17
|
function filterStory(story, config) {
|
package/src/generateConfig.js
CHANGED
|
@@ -55,6 +55,15 @@ function generateConfig({argv = {}, defaultConfig = {}, externalConfigParams = [
|
|
|
55
55
|
result.viewportSize = result.viewportSize ? result.viewportSize : {width: 1024, height: 600};
|
|
56
56
|
|
|
57
57
|
result.saveNewTests = result.saveNewTests === undefined ? true : result.saveNewTests;
|
|
58
|
+
|
|
59
|
+
// Auto-enable dontCloseBatches when sharding is used (unless explicitly set by user)
|
|
60
|
+
if (result.shard && result.dontCloseBatches === undefined) {
|
|
61
|
+
result.dontCloseBatches = true;
|
|
62
|
+
console.log(
|
|
63
|
+
'Auto-enabling dontCloseBatches due to sharding configuration - please make sure to close batches manually ( https://applitools.com/tutorials/concepts/best-practices/batching#manually-close-the-shared-batch ).',
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
result.keepBatchOpen = result.dontCloseBatches;
|
|
59
68
|
result.fully = result.fully === undefined ? true : false;
|
|
60
69
|
|
package/src/index.ts
CHANGED
|
@@ -1,35 +1,312 @@
|
|
|
1
|
-
import type {ConfigurationPlain, DesktopBrowserInfo, ChromeEmulationInfo, IOSDeviceInfo, IOSMultiDeviceInfo} from '@applitools/eyes'
|
|
1
|
+
import type { ConfigurationPlain, DesktopBrowserInfo, ChromeEmulationInfo, IOSDeviceInfo, IOSMultiDeviceInfo } from '@applitools/eyes';
|
|
2
|
+
|
|
3
|
+
type irrelevantToStorybook = 'waitBeforeScreenshots'
|
|
4
|
+
| 'agentId'
|
|
5
|
+
| 'captureStatusBar'
|
|
6
|
+
| 'concurrentSessions'
|
|
7
|
+
| 'connectionTimeout'
|
|
8
|
+
| 'debugScreenshots'
|
|
9
|
+
| 'defaultMatchSettings'
|
|
10
|
+
| 'disableNMLUrlCache'
|
|
11
|
+
| 'forceFullPageScreenshot'
|
|
12
|
+
| 'hideCaret'
|
|
13
|
+
| 'hideScrollbars'
|
|
14
|
+
| 'hostApp'
|
|
15
|
+
| 'hostAppInfo'
|
|
16
|
+
| 'hostOS'
|
|
17
|
+
| 'hostOSInfo'
|
|
18
|
+
| 'ignoreBaseline'
|
|
19
|
+
| 'ignoreCaret'
|
|
20
|
+
| 'latestCommitInfo'
|
|
21
|
+
| 'isDisabled'
|
|
22
|
+
| 'matchTimeout'
|
|
23
|
+
| 'mobileOptions'
|
|
24
|
+
| 'removeSession'
|
|
25
|
+
| 'rotation'
|
|
26
|
+
| 'scaleRatio'
|
|
27
|
+
| 'scrollRootElement'
|
|
28
|
+
| 'sessionType'
|
|
29
|
+
| 'stitchMode'
|
|
30
|
+
| 'stitchOverlap'
|
|
31
|
+
| 'viewportSize'
|
|
32
|
+
;
|
|
33
|
+
|
|
2
34
|
|
|
3
35
|
/**
|
|
4
|
-
*
|
|
36
|
+
* Configuration options for Applitools Eyes Storybook integration.
|
|
37
|
+
*
|
|
38
|
+
* This configuration can be specified in three ways:
|
|
39
|
+
* - Command line arguments
|
|
40
|
+
* - Environment variables (uppercase with APPLITOOLS_ prefix)
|
|
41
|
+
* - applitools.config.js file (CommonJS module export)
|
|
42
|
+
*
|
|
43
|
+
* Environment variables override applitools.config.js values.
|
|
44
|
+
*
|
|
45
|
+
* @see https://applitools.com/tutorials/sdks/storybook/config
|
|
5
46
|
*/
|
|
6
|
-
export type ApplitoolsConfig = Omit<ConfigurationPlain, '
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
export type ApplitoolsConfig = Omit<ConfigurationPlain, irrelevantToStorybook | 'waitBeforeCapture'> & {
|
|
48
|
+
/**
|
|
49
|
+
* URL for Storybook instance.
|
|
50
|
+
* @example 'http://localhost:9001'
|
|
51
|
+
*/
|
|
52
|
+
storybookUrl?: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Port to run Storybook on.
|
|
56
|
+
* @default 9000
|
|
57
|
+
*/
|
|
58
|
+
storybookPort?: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Host to run Storybook on.
|
|
62
|
+
* @default 'localhost'
|
|
63
|
+
*/
|
|
64
|
+
storybookHost?: string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Path to Storybook's config folder.
|
|
68
|
+
* @default '.storybook'
|
|
69
|
+
*/
|
|
70
|
+
storybookConfigDir?: string;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Path to Storybook's static files folder.
|
|
74
|
+
*/
|
|
75
|
+
storybookStaticDir?: string;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Whether to display Storybook output in console.
|
|
79
|
+
*/
|
|
80
|
+
showStorybookOutput?: boolean;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Set to true if running the SDK in Docker to resolve potential issues.
|
|
84
|
+
* @default false
|
|
85
|
+
*/
|
|
86
|
+
runInDocker?: boolean;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Predicate function, string, or regex specifying which stories should be visually tested.
|
|
90
|
+
* Visual baselines will be created only for specified components.
|
|
91
|
+
* Function receives object with name, kind, storyTitle, and parameters properties.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* // Exclude stories with names starting with [SKIP]
|
|
95
|
+
* ({name, kind, storyTitle, parameters}) => !/^\\[SKIP\\]/.test(name)
|
|
96
|
+
*
|
|
97
|
+
* @default true (includes all stories)
|
|
98
|
+
*/
|
|
99
|
+
include?: ((story: { name: string; kind: string; storyTitle?: string; parameters?: any }) => boolean) | string | RegExp;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Specifies additional variations for all or some stories (e.g., RTL).
|
|
103
|
+
*/
|
|
104
|
+
variations?: Record<string, any>;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Time in milliseconds that Eyes-Storybook waits for Storybook to load.
|
|
108
|
+
* For Storybook versions 2 and 3, this is also the acknowledgment time.
|
|
109
|
+
* Recommended to use small values (e.g., 3000) for versions 2-3.
|
|
110
|
+
*
|
|
111
|
+
* @default 60000
|
|
112
|
+
*/
|
|
113
|
+
readStoriesTimeout?: number;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Low-level options to send to puppeteer.launch().
|
|
117
|
+
* Use with great care.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* { args: ['--no-sandbox'], headless: false, devtools: true }
|
|
121
|
+
*/
|
|
122
|
+
puppeteerOptions?: Record<string, any>;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Options to send to page.setExtraHTTPHeaders().
|
|
126
|
+
* @see https://pptr.dev/api/puppeteer.page.setextrahttpheaders
|
|
127
|
+
*/
|
|
128
|
+
puppeteerExtraHTTPHeaders?: Record<string, string>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* When to consider navigation finished.
|
|
132
|
+
* @default 'load'
|
|
133
|
+
*/
|
|
134
|
+
navigationWaitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Cache all requests from browser for faster performance.
|
|
138
|
+
* @default false
|
|
139
|
+
*/
|
|
140
|
+
browserCacheRequests?: boolean;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Array of browser configurations for screenshot generation.
|
|
144
|
+
* Defines size and browser type for generated screenshots.
|
|
145
|
+
*
|
|
146
|
+
* @default [{ width: 1024, height: 768, name: 'chrome' }]
|
|
147
|
+
*/
|
|
148
|
+
browser?: (DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)[];
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Name for the environment in which the application under test is running.
|
|
152
|
+
*/
|
|
153
|
+
envName?: string;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Maximum number of tests that can run concurrently.
|
|
157
|
+
* Default value is the allowed amount for free accounts.
|
|
158
|
+
* For paid accounts, set to your account quota.
|
|
159
|
+
*
|
|
160
|
+
* @default 5
|
|
161
|
+
*/
|
|
162
|
+
testConcurrency?: number;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Whether to display logs of the Eyes-Storybook plugin.
|
|
166
|
+
* @default false
|
|
167
|
+
*/
|
|
168
|
+
showLogs?: boolean;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* If tests failed or have visual differences, close with non-zero exit code.
|
|
172
|
+
* @default true
|
|
173
|
+
*/
|
|
174
|
+
exitcode?: boolean;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Array of regions to ignore when comparing checkpoint with baseline screenshot.
|
|
178
|
+
*/
|
|
179
|
+
ignoreRegions?: any[];
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Array of regions to consider as floating when comparing checkpoint with baseline.
|
|
183
|
+
*/
|
|
184
|
+
floatingRegions?: any[];
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Array of regions to consider as match level Layout when comparing screenshots.
|
|
188
|
+
*/
|
|
189
|
+
layoutRegions?: any[];
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Array of regions to consider as match level Strict when comparing screenshots.
|
|
193
|
+
*/
|
|
194
|
+
strictRegions?: any[];
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Array of regions to consider as match level Content when comparing screenshots.
|
|
198
|
+
*/
|
|
199
|
+
contentRegions?: any[];
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Array of regions to validate accessibility according to configured accessibilityValidation.
|
|
203
|
+
*/
|
|
204
|
+
accessibilityRegions?: any[];
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Directory path for JSON results file.
|
|
208
|
+
* If set, creates eyes.json file with test results.
|
|
209
|
+
*/
|
|
210
|
+
jsonFilePath?: string;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Directory path for TAP results file.
|
|
214
|
+
* If set, creates eyes.tap file with test results.
|
|
215
|
+
*/
|
|
216
|
+
tapFilePath?: string;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Directory path for XUnit XML results file.
|
|
220
|
+
* If set, creates eyes.xml file with test results.
|
|
221
|
+
*/
|
|
222
|
+
xmlFilePath?: string;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Selector, function, or timeout to wait before capturing.
|
|
226
|
+
*
|
|
227
|
+
* * number: Milliseconds to wait before capturing.
|
|
228
|
+
* * string: CSS selector to wait for before capturing.
|
|
229
|
+
* * function: Predicate or async function to wait for before capturing.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* waitBeforeCapture: '#container.ready',
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* waitBeforeCapture: () => document.querySelector('#container.ready') !== null,
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* waitBeforeCapture: 3_000
|
|
239
|
+
*
|
|
240
|
+
* @see https://applitools.com/tutorials/sdks/storybook/component-config#waitBeforeCapture
|
|
241
|
+
*/
|
|
242
|
+
waitBeforeCapture?: number | string | (() => boolean | Promise<boolean>);
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Unique identifier for the batch of tests - set to the same value if you want to group tests together.
|
|
246
|
+
*/
|
|
247
|
+
batchId?: string;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Name for the batch of tests - will appear in the Eyes dashboard.
|
|
251
|
+
*/
|
|
252
|
+
batchName?: string;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Sequence name for the batch of tests - will appear in the Eyes dashboard (in the 'insights' page and in the batch details).
|
|
256
|
+
*/
|
|
257
|
+
batchSequenceName?: string;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Name for the baseline branch - use it if you want to compare with a specific branch that is different from the current branch.
|
|
261
|
+
*
|
|
262
|
+
* @see for more information and recommendations regarding baseline branches, see the [documentation](https://applitools.com/tutorials/concepts/best-practices/branching).
|
|
263
|
+
*/
|
|
264
|
+
baselineBranchName?: string;
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Dry run - if true, no actual visual testing will be performed.
|
|
268
|
+
* @default false
|
|
269
|
+
*/
|
|
270
|
+
isDisabled?: boolean;
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Whether to ignore the baseline when comparing with the checkpoint (will make all checkpoints `new`)
|
|
274
|
+
* @default false
|
|
275
|
+
*/
|
|
276
|
+
ignoreBaseline?: boolean
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Settings for accessibility validation.
|
|
280
|
+
*/
|
|
281
|
+
accessibilitySettings?: {
|
|
282
|
+
/**
|
|
283
|
+
* Level of accessibility validation to perform.
|
|
284
|
+
*/
|
|
285
|
+
level?: 'AA' | 'AAA';
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Array of specific accessibility guidelines to check.
|
|
289
|
+
*/
|
|
290
|
+
guidelinesVersion?: "WCAG_2_0" | "WCAG_2_1";
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Whether to notify when the test is complete (requires to turn on notifications in the Applitools dashboard).
|
|
295
|
+
* @see https://applitools.com/tutorials/integrations/chat-&-notifications/email
|
|
296
|
+
*/
|
|
297
|
+
notifyOnCompletion?: boolean;
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Whether to show browser logs in the test results.
|
|
301
|
+
* @default false
|
|
302
|
+
*/
|
|
303
|
+
showBrowserLogs?: boolean;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* A string formatted as `<ShardIndex>/<TotalShards>` to enable test sharding (running tests in parallel).
|
|
307
|
+
* @default undefined
|
|
308
|
+
*/
|
|
309
|
+
shard?: string;
|
|
35
310
|
}
|
|
311
|
+
|
|
312
|
+
export type configKeys = keyof ApplitoolsConfig;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
'use strict';
|
|
2
3
|
const chalk = require('chalk');
|
|
3
4
|
const {Configuration} = require('@applitools/eyes');
|
|
5
|
+
const defaultConfig = require('./../defaultConfig');
|
|
4
6
|
|
|
5
7
|
// Get all keys directly from the base Configuration class
|
|
6
8
|
const dynamicBaseKeys = [
|
|
@@ -30,31 +32,30 @@ const knownAliases = [
|
|
|
30
32
|
const applitoolsBaseKeys = [...dynamicBaseKeys, ...knownAliases];
|
|
31
33
|
|
|
32
34
|
// A list of all keys specific to the eyes-storybook package.
|
|
35
|
+
/**
|
|
36
|
+
* @type {Array<keyof (import('../index').ApplitoolsConfig) |
|
|
37
|
+
* 'reloadPagePerStory' |
|
|
38
|
+
* 'startStorybookServerTimeout' |
|
|
39
|
+
* 'networkBlockPatterns' |
|
|
40
|
+
* 'browserRequestsTimeout' |
|
|
41
|
+
* 'browserHeadersOverride' |
|
|
42
|
+
* 'waitBeforeScreenshot' |
|
|
43
|
+
* 'waitBeforeScreenshots' |
|
|
44
|
+
* 'fakeIE' |
|
|
45
|
+
* 'storyConfiguration' |
|
|
46
|
+
* 'storyDataGap' |
|
|
47
|
+
* 'packagePath'
|
|
48
|
+
* >}
|
|
49
|
+
*/
|
|
33
50
|
const storybookSpecificKeys = [
|
|
34
|
-
'
|
|
35
|
-
'storybookHost',
|
|
36
|
-
'storybookConfigDir',
|
|
37
|
-
'storybookUrl',
|
|
38
|
-
'storybookStaticDir',
|
|
39
|
-
'showStorybookOutput',
|
|
40
|
-
'exitcode',
|
|
41
|
-
'include',
|
|
42
|
-
'variations',
|
|
51
|
+
'variations', // TODO - are we sure it should be supported from the applitools config file? https://applitools.com/tutorials/sdks/storybook/component-config#variations
|
|
43
52
|
'runInDocker',
|
|
44
|
-
'readStoriesTimeout',
|
|
45
|
-
'reloadPagePerStory',
|
|
46
|
-
'startStorybookServerTimeout',
|
|
47
53
|
'showLogs',
|
|
48
54
|
|
|
49
55
|
// Browser & Puppeteer Control
|
|
50
56
|
'browser',
|
|
51
57
|
'puppeteerOptions',
|
|
52
|
-
'puppeteerExtraHTTPHeaders',
|
|
53
|
-
'navigationWaitUntil',
|
|
54
|
-
'networkBlockPatterns',
|
|
55
|
-
'browserRequestsTimeout',
|
|
56
|
-
'browserHeadersOverride',
|
|
57
|
-
'browserCacheRequests',
|
|
58
|
+
'puppeteerExtraHTTPHeaders', // created for a specific user, TODO - consider removing
|
|
58
59
|
|
|
59
60
|
// Region Matching
|
|
60
61
|
'ignoreRegions',
|
|
@@ -72,7 +73,6 @@ const storybookSpecificKeys = [
|
|
|
72
73
|
// Legacy & Internal
|
|
73
74
|
'waitBeforeScreenshot', // backward compatibility
|
|
74
75
|
'waitBeforeScreenshots', // backward compatibility
|
|
75
|
-
'waitBeforeCapture',
|
|
76
76
|
'fakeIE',
|
|
77
77
|
'storyConfiguration',
|
|
78
78
|
'storyDataGap',
|
|
@@ -80,7 +80,11 @@ const storybookSpecificKeys = [
|
|
|
80
80
|
];
|
|
81
81
|
|
|
82
82
|
// Combine all known keys into a single Set for efficient O(1) lookups.
|
|
83
|
-
const knownKeys = new Set([
|
|
83
|
+
const knownKeys = new Set([
|
|
84
|
+
...storybookSpecificKeys,
|
|
85
|
+
...applitoolsBaseKeys,
|
|
86
|
+
...Object.keys(defaultConfig),
|
|
87
|
+
]);
|
|
84
88
|
|
|
85
89
|
/**
|
|
86
90
|
* Checks the user's config object for any keys that are not recognized
|
|
@@ -101,6 +105,7 @@ function logUnrecognizedKeys(config, logger) {
|
|
|
101
105
|
unrecognizedKeys.forEach(key => {
|
|
102
106
|
console.log(chalk.yellow(` - ${key}`));
|
|
103
107
|
});
|
|
108
|
+
// @ts-ignore
|
|
104
109
|
logger.log('\n');
|
|
105
110
|
|
|
106
111
|
const docsUrl = 'https://applitools.com/tutorials/sdks/storybook/config#properties';
|
package/src/yargsOptions.js
CHANGED
|
@@ -83,6 +83,27 @@ module.exports = {
|
|
|
83
83
|
choices: ['load', 'domcontentloaded', 'networkidle0', 'networkidle2'], // PuppeteerLifeCycleEvent values - https://pptr.dev/api/puppeteer.puppeteerlifecycleevent
|
|
84
84
|
},
|
|
85
85
|
|
|
86
|
+
shard: {
|
|
87
|
+
description: 'Shard tests (format: current/total, e.g., "1/3")',
|
|
88
|
+
requiresArg: true,
|
|
89
|
+
string: true,
|
|
90
|
+
coerce: function (arg) {
|
|
91
|
+
const match = arg.match(/^(\d+)\/(\d+)$/);
|
|
92
|
+
if (!match) {
|
|
93
|
+
throw new Error('shard must be in format "current/total" (e.g., "1/3")');
|
|
94
|
+
}
|
|
95
|
+
const current = parseInt(match[1], 10);
|
|
96
|
+
const total = parseInt(match[2], 10);
|
|
97
|
+
if (current < 1 || current > total) {
|
|
98
|
+
throw new Error(`shard current (${current}) must be between 1 and total (${total})`);
|
|
99
|
+
}
|
|
100
|
+
if (total < 1) {
|
|
101
|
+
throw new Error(`shard total (${total}) must be at least 1`);
|
|
102
|
+
}
|
|
103
|
+
return {current, total};
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
|
|
86
107
|
// general
|
|
87
108
|
exitcode: {
|
|
88
109
|
alias: 'e',
|
package/dist/getStoryByIndex.js
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
function __getStoryByIndex(...args) {
|
|
3
|
-
var getStoryByIndex = (function () {
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
|
-
const API_VERSIONS = {
|
|
7
|
-
v4: 'v4',
|
|
8
|
-
v5: 'v5',
|
|
9
|
-
v5_2: 'v5_2',
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
function getClientAPI() {
|
|
13
|
-
const frameWindow = getFrameWindow();
|
|
14
|
-
const clientAPI = frameWindow.__STORYBOOK_CLIENT_API__;
|
|
15
|
-
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
16
|
-
|
|
17
|
-
return getAPI(getStorybookVersion());
|
|
18
|
-
|
|
19
|
-
function getStorybookVersion() {
|
|
20
|
-
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
21
|
-
|
|
22
|
-
if (frameWindow.__STORYBOOK_STORY_STORE__) {
|
|
23
|
-
return API_VERSIONS.v5_2;
|
|
24
|
-
} else if (frameWindow.__STORYBOOK_CLIENT_API__ && frameWindow.__STORYBOOK_CLIENT_API__.raw) {
|
|
25
|
-
return API_VERSIONS.v5;
|
|
26
|
-
} else if (
|
|
27
|
-
addons &&
|
|
28
|
-
addons.channel &&
|
|
29
|
-
addons.channel._listeners &&
|
|
30
|
-
addons.channel._listeners.setCurrentStory &&
|
|
31
|
-
addons.channel._listeners.setCurrentStory[0]
|
|
32
|
-
) {
|
|
33
|
-
return API_VERSIONS.v4;
|
|
34
|
-
} else {
|
|
35
|
-
throw new Error("Cannot get client API: couldn't detect storybook version");
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function getAPI(version) {
|
|
40
|
-
if (version) {
|
|
41
|
-
let api;
|
|
42
|
-
switch (version) {
|
|
43
|
-
case API_VERSIONS.v4: {
|
|
44
|
-
api = {
|
|
45
|
-
getStories: () => {
|
|
46
|
-
if (!frameWindow.__APPLITOOLS_STORIES) {
|
|
47
|
-
frameWindow.__APPLITOOLS_STORIES = Object.values(clientAPI._storyStore._data)
|
|
48
|
-
.map(({stories, kind}) => Object.values(stories).map(s => ({...s, kind})))
|
|
49
|
-
.flat();
|
|
50
|
-
}
|
|
51
|
-
return frameWindow.__APPLITOOLS_STORIES;
|
|
52
|
-
},
|
|
53
|
-
selectStory: i => {
|
|
54
|
-
const {kind, name: story} = api.getStories()[i];
|
|
55
|
-
addons.channel._listeners.setCurrentStory[0]({kind, story});
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
case API_VERSIONS.v5: {
|
|
62
|
-
api = {
|
|
63
|
-
getStories: () => {
|
|
64
|
-
return clientAPI.raw();
|
|
65
|
-
},
|
|
66
|
-
selectStory: i => {
|
|
67
|
-
clientAPI._storyStore.setSelection(clientAPI.raw()[i]);
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
case API_VERSIONS.v5_2: {
|
|
74
|
-
api = {
|
|
75
|
-
getStories: () => {
|
|
76
|
-
return clientAPI.raw();
|
|
77
|
-
},
|
|
78
|
-
selectStory: i => {
|
|
79
|
-
frameWindow.__STORYBOOK_STORY_STORE__.setSelection({storyId: clientAPI.raw()[i].id});
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return {version, ...api};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function getFrameWindow() {
|
|
92
|
-
if (/iframe.html/.test(window.location.href)) {
|
|
93
|
-
return window;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const innerFrameWindow = Array.prototype.find.call(window.frames, frame => {
|
|
97
|
-
try {
|
|
98
|
-
return /\/iframe.html/.test(frame.location.href);
|
|
99
|
-
} catch (e) {}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
if (innerFrameWindow) {
|
|
103
|
-
return innerFrameWindow;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (window.__STORYBOOK_CLIENT_API__) {
|
|
107
|
-
return window;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
throw new Error('Cannot get client API: no frameWindow');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
var getClientAPI_1 = getClientAPI;
|
|
114
|
-
|
|
115
|
-
function getStoryIndex(index) {
|
|
116
|
-
let api;
|
|
117
|
-
try {
|
|
118
|
-
api = getClientAPI_1();
|
|
119
|
-
const story = api.getStories()[index];
|
|
120
|
-
if (!story) {
|
|
121
|
-
console.log('error cannot get story', index);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
return story;
|
|
125
|
-
} catch (ex) {
|
|
126
|
-
return {message: ex.message, version: api ? api.version : undefined};
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
var getStoryByIndex = getStoryIndex;
|
|
131
|
-
|
|
132
|
-
return getStoryByIndex;
|
|
133
|
-
|
|
134
|
-
}());
|
|
135
|
-
|
|
136
|
-
return getStoryByIndex.apply(this, args);
|
|
137
|
-
}
|
|
138
|
-
module.exports = __getStoryByIndex
|