@applitools/eyes-storybook 3.25.0 → 3.26.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 +30 -0
- package/README.md +59 -42
- package/package.json +14 -10
- package/src/addParametrizedStories.js +81 -0
- package/src/cli.js +2 -3
- package/src/defaultConfig.js +2 -1
- package/src/eyesStorybook.js +33 -14
- package/src/generateConfig.js +21 -16
- package/src/getStoryBaselineName.js +13 -0
- package/src/getStoryData.js +35 -16
- package/src/getStoryTitle.js +4 -3
- package/src/getStoryUrl.js +3 -3
- package/src/renderStories.js +10 -7
- package/src/renderStory.js +7 -4
- package/src/addVariationStories.js +0 -54
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,36 @@
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## 3.26.0 - 2021/11/26
|
|
7
|
+
|
|
8
|
+
- add support for `queryParams` config property
|
|
9
|
+
- updated to @applitools/driver@1.3.5 (from 1.2.7)
|
|
10
|
+
- updated to @applitools/eyes-puppeteer@1.9.0 (from 1.8.5)
|
|
11
|
+
- updated to @applitools/eyes-sdk-core@12.24.5 (from 12.23.24)
|
|
12
|
+
- updated to @applitools/logger@1.0.6 (from 1.0.5)
|
|
13
|
+
- updated to @applitools/test-server@1.0.7 (from 1.0.6)
|
|
14
|
+
- updated to @applitools/visual-grid-client@15.8.49 (from 15.8.43)
|
|
15
|
+
|
|
16
|
+
## 3.25.3 - 2021/11/1
|
|
17
|
+
|
|
18
|
+
- add a retry mechanism for cases we get 0 stories
|
|
19
|
+
|
|
20
|
+
## 3.25.2 - 2021/10/30
|
|
21
|
+
|
|
22
|
+
- replace legacy logger construction with new
|
|
23
|
+
- deprecate `waitBeforeScreenshot` and introduce `waitBeforeCapture` instead
|
|
24
|
+
- updated to @applitools/driver@1.2.7 (from 1.2.6)
|
|
25
|
+
- updated to @applitools/eyes-puppeteer@1.8.5 (from 1.8.4)
|
|
26
|
+
- updated to @applitools/eyes-sdk-core@12.23.24 (from 12.23.18)
|
|
27
|
+
- updated to @applitools/test-server@1.0.6 (from 1.0.5)
|
|
28
|
+
- updated to @applitools/visual-grid-client@15.8.43 (from 15.8.37)
|
|
29
|
+
|
|
30
|
+
## 3.25.1 - 2021/10/20
|
|
31
|
+
|
|
32
|
+
- updated to @applitools/eyes-puppeteer@1.8.4 (from 1.8.3)
|
|
33
|
+
- updated to @applitools/eyes-sdk-core@12.23.18 (from 12.23.17)
|
|
34
|
+
- updated to @applitools/visual-grid-client@15.8.37 (from 15.8.36)
|
|
35
|
+
|
|
6
36
|
## 3.25.0 - 2021/10/18
|
|
7
37
|
|
|
8
38
|
- updated to @applitools/driver@1.2.6 (from 1.1.3)
|
package/README.md
CHANGED
|
@@ -4,43 +4,52 @@ Applitools Eyes SDK for [Storybook](http://storybook.js.org).
|
|
|
4
4
|
|
|
5
5
|
### Table of contents
|
|
6
6
|
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- [
|
|
42
|
-
- [
|
|
43
|
-
- [
|
|
7
|
+
- [Eyes-Storybook](#eyes-storybook)
|
|
8
|
+
- [Table of contents](#table-of-contents)
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Install npm package](#install-npm-package)
|
|
11
|
+
- [Applitools API key](#applitools-api-key)
|
|
12
|
+
- [Usage](#usage)
|
|
13
|
+
- [Configuring local storybook server](#configuring-local-storybook-server)
|
|
14
|
+
- [Standalone server](#standalone-server)
|
|
15
|
+
- [Command line arguments](#command-line-arguments)
|
|
16
|
+
- [Concurrency](#concurrency)
|
|
17
|
+
- [Advanced configuration](#advanced-configuration)
|
|
18
|
+
- [Method 1: Environment variables](#method-1-environment-variables)
|
|
19
|
+
- [Method 2: The `applitools.config.js` file](#method-2-the-applitoolsconfigjs-file)
|
|
20
|
+
- [Configuring the browser](#configuring-the-browser)
|
|
21
|
+
- [Previous browser versions](#previous-browser-versions)
|
|
22
|
+
- [Getting a screenshot of multiple browsers in parallel](#getting-a-screenshot-of-multiple-browsers-in-parallel)
|
|
23
|
+
- [Device emulation](#device-emulation)
|
|
24
|
+
- [iOS device](#ios-device)
|
|
25
|
+
- [Faking IE Browser](#faking-ie-browser)
|
|
26
|
+
- [Per component configuration](#per-component-configuration)
|
|
27
|
+
- [`include`](#include)
|
|
28
|
+
- [global](#global)
|
|
29
|
+
- [component](#component)
|
|
30
|
+
- [`variations`](#variations)
|
|
31
|
+
- [`queryParams`](#queryparams)
|
|
32
|
+
- [`waitBeforeCapture`](#waitbeforecapture)
|
|
33
|
+
- [`properties`](#properties)
|
|
34
|
+
- [`ignoreRegions`](#ignoreregions)
|
|
35
|
+
- [`floatingRegions`](#floatingregions)
|
|
36
|
+
- [`layoutRegions`](#layoutregions)
|
|
37
|
+
- [`contentRegions`](#contentregions)
|
|
38
|
+
- [`strictRegions`](#strictregions)
|
|
39
|
+
- [`accessibilityRegions`](#accessibilityregions)
|
|
40
|
+
- [`accessibilityValidation`](#accessibilityvalidation)
|
|
41
|
+
- [`ignoreDisplacements`](#ignoredisplacements)
|
|
42
|
+
- [`sendDom`](#senddom)
|
|
43
|
+
- [`visualGridOptions`](#visualgridoptions)
|
|
44
|
+
- [`scriptHooks`](#scripthooks)
|
|
45
|
+
- [beforeCaptureScreenshot](#beforecapturescreenshot)
|
|
46
|
+
- [Parameters that cannot be set as an advanced configuration](#parameters-that-cannot-be-set-as-an-advanced-configuration)
|
|
47
|
+
- [`runBefore` and `runAfter` functions](#runbefore-and-runafter-functions)
|
|
48
|
+
- [`runBefore`](#runbefore)
|
|
49
|
+
- [`runAfter`](#runafter)
|
|
50
|
+
- [`layoutBreakpoints`](#layoutbreakpoints)
|
|
51
|
+
- [Running Eyes-Storybook in Docker](#running-eyes-storybook-in-docker)
|
|
52
|
+
- [Dealing with dynamic data](#dealing-with-dynamic-data)
|
|
44
53
|
|
|
45
54
|
## Installation
|
|
46
55
|
|
|
@@ -169,9 +178,10 @@ In addition to command-line arguments, it's possible to define the following con
|
|
|
169
178
|
| `jsonFilePath` | undefined | Directory path of a results file. If set, then a [JSON](https://www.json.org/json-en.html) file is created in this directory, the file is created with the name eyes.json and contains the Eyes test results. |
|
|
170
179
|
| `tapFilePath` | undefined | Directory path of a results file. If set, then a [TAP](https://en.wikipedia.org/wiki/Test_Anything_Protocol#Specification) file is created in this directory, the file is created with the name eyes.tap and contains the Eyes test results. |
|
|
171
180
|
| `xmlFilePath` | undefined | Directory path of a results file. If set, then a [XUnit XML](https://google.github.io/rich-test-results/xunitxml) file is created in this directory, the file is created with the name eyes.xml and contains the Eyes test results. |
|
|
172
|
-
| `
|
|
181
|
+
| `waitBeforeCapture` | undefined | Selector, function or timeout.<br/>If ```number``` then the argument is treated as time in milliseconds to wait before all screenshots.<br/>If ```string``` then the argument is treated as a selector for elements to wait for before all screenshots.<br/>If ```function```, then the argument is treated as a predicate to wait for before all screenshots.<br/><hr/>For per component configuration see [waitBeforeCapture.](#waitBeforeCapture)<br/>Note that we use Puppeteer's [page.waitForTimeout()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitfortimeoutmilliseconds), [page.waitForSelector()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforselectorselector-options), [page.waitForXPath()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforxpathxpath-options) and [page.waitForFunction()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforfunctionpagefunction-options-args), checkout it's API for more details. |
|
|
173
182
|
| `include` | true | A predicate function, a string or a regular expression specifying which stories should be visually tested.<br/>Visual baselines will be created only for the components specified.<br/>The function receives an object with ```name```, ```kind```, ```storyTitle``` and ```parameters``` properties.<br/>For example (exclude all stories with a name that start with [SKIP]):<br/>```({name, kind, storyTitle, parameters}) => !/^\[SKIP\]/.test(name)```<br/>For more information, see [per component configuration - include](#include). |
|
|
174
183
|
| `variations` | undefined | Specifies additional variations for all or some of the stories. For example, RTL. For more information, see [per component configuration - variations](#variations).|
|
|
184
|
+
| `queryParam` | undefined | Specifies additional query parameters for all or some of the stories. For more information, see [per component configuration - queryParams](#queryParams).|
|
|
175
185
|
| `notifyOnCompletion` | false | If `true` batch completion notifications are sent. |
|
|
176
186
|
| `dontCloseBatches` | false | If true, batches are not closed for notifyOnCompletion.|
|
|
177
187
|
| `testConcurrency` | 5 | The maximum number of tests that can run concurrently. The default value is the allowed amount for free accounts. For paid accounts, set this number to the quota set for your account. |
|
|
@@ -439,20 +449,27 @@ storiesOf('Components that support RTL', module)
|
|
|
439
449
|
)
|
|
440
450
|
```
|
|
441
451
|
|
|
442
|
-
### `
|
|
452
|
+
### `queryParams`
|
|
453
|
+
|
|
454
|
+
An array of object values, which specifies `name` and `value` of query parameter which will be added to the story. For each value, an additional visual test will be executed for the component. It will have the same name display name, but still generate a different baseline.
|
|
455
|
+
|
|
456
|
+
This can accommodate many use cases, for example `@storybook/addon-contexts`.
|
|
457
|
+
With addons like this it is possible to render components in a different way depends on query parameters in URL.
|
|
458
|
+
|
|
459
|
+
### `waitBeforeCapture`
|
|
443
460
|
|
|
444
461
|
Selector or timeout, see [advanced configuration](#advanced-configuration) for more details.
|
|
445
462
|
|
|
446
463
|
```js
|
|
447
|
-
storiesOf('Components with a
|
|
464
|
+
storiesOf('Components with a waitBeforeCapture', module)
|
|
448
465
|
.add(
|
|
449
466
|
'Some story',
|
|
450
467
|
() => <span id="container" class="loading"></span>,
|
|
451
|
-
{eyes: {
|
|
468
|
+
{eyes: { waitBeforeCapture: '#container.ready' }}
|
|
452
469
|
);
|
|
453
470
|
```
|
|
454
471
|
|
|
455
|
-
_Note that the predicate option for `
|
|
472
|
+
_Note that the predicate option for `waitBeforeCapture` is currently not available in the per component configuration._
|
|
456
473
|
|
|
457
474
|
### `properties`
|
|
458
475
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-storybook",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=8.6.0"
|
|
@@ -25,10 +25,12 @@
|
|
|
25
25
|
"storybook": "start-storybook -c test/fixtures/appWithStorybook -p 9001 -s test/fixtures",
|
|
26
26
|
"storybook:jslayout": "start-storybook -c test/fixtures/jsLayoutStorybookLocal -p 9001 -s test/fixtures",
|
|
27
27
|
"storybook:heavy": "start-storybook -c test/fixtures/heavyStorybook -p 9002 -s test/fixtures",
|
|
28
|
+
"storybook:zeroStories": "start-storybook -c test/fixtures/zeroStoriesRetry -p 9003 -s test/fixtures",
|
|
28
29
|
"eyes-storybook": "node bin/eyes-storybook.js -f test/fixtures/applitools.config.js",
|
|
29
30
|
"eyes-storybook:jslayout": "node bin/eyes-storybook.js -f test/e2e/happy-config/layout-breakpoints-local.config.js",
|
|
30
31
|
"eyes-storybook:heavy": "node bin/eyes-storybook.js -f test/fixtures/heavyStorybook/applitools.config.js",
|
|
31
32
|
"eyes-storybook:configured": "node bin/eyes-storybook.js -f scripts/preconfigured.config.js",
|
|
33
|
+
"eyes-storybook:zeroStories": "node bin/eyes-storybook.js -f test/fixtures/zeroStoriesRetry/applitools.config.js",
|
|
32
34
|
"changelog": "git changelog -x -p -f v$npm_package_version > History.md && git add ./History.md && git commit -am 'changelog'",
|
|
33
35
|
"changelog:init": "git config changelog.format \"* %s [[%h]($(echo $npm_package_repository_url|cut -d+ -f2|cut -d. -f1-2)/commit/%H)]\"",
|
|
34
36
|
"changelog:install": "sudo apt-get install git-extras",
|
|
@@ -52,16 +54,18 @@
|
|
|
52
54
|
"license": "SEE LICENSE IN LICENSE",
|
|
53
55
|
"repository": {
|
|
54
56
|
"type": "git",
|
|
55
|
-
"url": "git://github.com/applitools/eyes.sdk.javascript1.git"
|
|
57
|
+
"url": "git://github.com/applitools/eyes.sdk.javascript1.git",
|
|
58
|
+
"directory": "packages/eyes-storybook"
|
|
56
59
|
},
|
|
57
60
|
"dependencies": {
|
|
58
|
-
"@applitools/driver": "1.
|
|
59
|
-
"@applitools/eyes-
|
|
60
|
-
"@applitools/eyes-sdk-core": "12.23.17",
|
|
61
|
+
"@applitools/driver": "1.3.5",
|
|
62
|
+
"@applitools/eyes-sdk-core": "12.24.5",
|
|
61
63
|
"@applitools/functional-commons": "1.6.0",
|
|
64
|
+
"@applitools/logger": "1.0.6",
|
|
62
65
|
"@applitools/monitoring-commons": "1.0.19",
|
|
63
|
-
"@applitools/
|
|
64
|
-
"@applitools/
|
|
66
|
+
"@applitools/spec-driver-puppeteer": "1.1.0",
|
|
67
|
+
"@applitools/test-server": "1.0.7",
|
|
68
|
+
"@applitools/visual-grid-client": "15.8.49",
|
|
65
69
|
"boxen": "4.2.0",
|
|
66
70
|
"chalk": "3.0.0",
|
|
67
71
|
"detect-port": "1.3.0",
|
|
@@ -74,10 +78,10 @@
|
|
|
74
78
|
},
|
|
75
79
|
"devDependencies": {
|
|
76
80
|
"@applitools/scripts": "^1.0.1",
|
|
77
|
-
"@applitools/sdk-release-kit": "0.13.
|
|
78
|
-
"@applitools/sdk-shared": "0.9.
|
|
81
|
+
"@applitools/sdk-release-kit": "0.13.4",
|
|
82
|
+
"@applitools/sdk-shared": "0.9.9",
|
|
79
83
|
"@applitools/snaptdout": "^1.0.1",
|
|
80
|
-
"@applitools/utils": "1.2.
|
|
84
|
+
"@applitools/utils": "1.2.4",
|
|
81
85
|
"@storybook/addon-options": "^5.2.8",
|
|
82
86
|
"@storybook/react": "^5.2.8",
|
|
83
87
|
"@testing-library/dom": "^5.6.1",
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function addParametrizedStories({stories, config}) {
|
|
4
|
+
const parametrizedStories = {};
|
|
5
|
+
for (const story of stories) {
|
|
6
|
+
const queryParams = getStoryQueryParams(story, config);
|
|
7
|
+
if (!queryParams) continue;
|
|
8
|
+
for (const queryParam of queryParams) {
|
|
9
|
+
const queryParamString = `${queryParam.name}=${queryParam.value}`;
|
|
10
|
+
const parametrizeStoriesArray =
|
|
11
|
+
parametrizedStories[queryParamString] || (parametrizedStories[queryParamString] = []);
|
|
12
|
+
parametrizeStoriesArray.push({
|
|
13
|
+
...story,
|
|
14
|
+
parameters: addQueryParam(story.parameters, queryParam),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return Object.values(parametrizedStories).reduce((allStories, parametrizedStories) => {
|
|
20
|
+
return allStories.concat(parametrizedStories);
|
|
21
|
+
}, stories);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getStoryQueryParams(story, config) {
|
|
25
|
+
let queryParams;
|
|
26
|
+
if (story.parameters && story.parameters.eyes && story.parameters.eyes.queryParams) {
|
|
27
|
+
if (!Array.isArray(story.parameters.eyes.queryParams)) {
|
|
28
|
+
throw new Error('queryParams should be an array');
|
|
29
|
+
}
|
|
30
|
+
queryParams = [...story.parameters.eyes.queryParams];
|
|
31
|
+
}
|
|
32
|
+
if (story.parameters && story.parameters.eyes && story.parameters.eyes.variations) {
|
|
33
|
+
if (!Array.isArray(story.parameters.eyes.variations)) {
|
|
34
|
+
throw new Error('variations should be an array');
|
|
35
|
+
}
|
|
36
|
+
queryParams = [
|
|
37
|
+
...(queryParams || []),
|
|
38
|
+
...variationsToQueryParams(story.parameters.eyes.variations),
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (queryParams) return queryParams;
|
|
43
|
+
|
|
44
|
+
if (config.queryParams) {
|
|
45
|
+
if (!Array.isArray(config.queryParams)) {
|
|
46
|
+
throw new Error('global queryParams should be an array');
|
|
47
|
+
}
|
|
48
|
+
queryParams = [...config.queryParams];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (config.variations) {
|
|
52
|
+
if (Array.isArray(config.variations)) {
|
|
53
|
+
queryParams = [...(queryParams || []), ...variationsToQueryParams(config.variations)];
|
|
54
|
+
} else if (typeof config.variations === 'function') {
|
|
55
|
+
const variations = config.variations(story);
|
|
56
|
+
if (variations) {
|
|
57
|
+
if (!Array.isArray(variations)) {
|
|
58
|
+
throw new Error('global variations should be a function that returns array');
|
|
59
|
+
}
|
|
60
|
+
queryParams = [...(queryParams || []), ...variationsToQueryParams(variations)];
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
throw new Error('global variations should be an array or a function that returns array');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (queryParams) return queryParams;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function variationsToQueryParams(variations) {
|
|
71
|
+
return variations.map(variation => ({name: 'eyes-variation', value: variation}));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function addQueryParam(parameters, queryParam) {
|
|
75
|
+
parameters = {...parameters};
|
|
76
|
+
parameters.eyes = {...parameters.eyes};
|
|
77
|
+
parameters.eyes.queryParam = queryParam;
|
|
78
|
+
return parameters;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = addParametrizedStories;
|
package/src/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const yargs = require('yargs');
|
|
3
|
-
const {
|
|
3
|
+
const {makeLogger} = require('@applitools/logger');
|
|
4
4
|
const {configParams: externalConfigParams} = require('@applitools/visual-grid-client');
|
|
5
5
|
const VERSION = require('../package.json').version;
|
|
6
6
|
const eyesStorybook = require('./eyesStorybook');
|
|
@@ -32,8 +32,7 @@ const {performance, timeItAsync} = makeTiming();
|
|
|
32
32
|
console.log(`Using @applitools/eyes-storybook version ${VERSION}.\n`);
|
|
33
33
|
|
|
34
34
|
const config = generateConfig({argv, defaultConfig, externalConfigParams});
|
|
35
|
-
const logger =
|
|
36
|
-
logger.setIncludeTime(true);
|
|
35
|
+
const logger = makeLogger({level: config.showLogs ? 'info' : 'silent', label: 'eyes'});
|
|
37
36
|
await validateAndPopulateConfig({config, logger, packagePath: process.cwd()});
|
|
38
37
|
logger.log(`Running with the following config:\n${configDigest(config)}`);
|
|
39
38
|
const [err, results] = await presult(
|
package/src/defaultConfig.js
CHANGED
|
@@ -7,8 +7,9 @@ module.exports = {
|
|
|
7
7
|
storybookUrl: undefined,
|
|
8
8
|
storybookStaticDir: undefined,
|
|
9
9
|
showStorybookOutput: false,
|
|
10
|
-
waitBeforeScreenshot: 50,
|
|
10
|
+
waitBeforeScreenshot: 50, // backward compatibility
|
|
11
11
|
waitBeforeScreenshots: 50, // backward compatibility
|
|
12
|
+
waitBeforeCapture: 50,
|
|
12
13
|
viewportSize: {width: 1024, height: 768},
|
|
13
14
|
tapFilePath: undefined,
|
|
14
15
|
xmlFilePath: undefined,
|
package/src/eyesStorybook.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const puppeteer = require('puppeteer');
|
|
3
3
|
const getStories = require('../dist/getStories');
|
|
4
4
|
const {makeVisualGridClient} = require('@applitools/visual-grid-client');
|
|
5
|
-
const {presult} = require('@applitools/functional-commons');
|
|
5
|
+
const {presult, delay} = require('@applitools/functional-commons');
|
|
6
6
|
const chalk = require('./chalkify');
|
|
7
7
|
const makeInitPage = require('./initPage');
|
|
8
8
|
const makeRenderStory = require('./renderStory');
|
|
@@ -10,7 +10,7 @@ const makeRenderStories = require('./renderStories');
|
|
|
10
10
|
const makeGetStoryData = require('./getStoryData');
|
|
11
11
|
const ora = require('ora');
|
|
12
12
|
const filterStories = require('./filterStories');
|
|
13
|
-
const
|
|
13
|
+
const addParametrizedStories = require('./addParametrizedStories');
|
|
14
14
|
const browserLog = require('./browserLog');
|
|
15
15
|
const memoryLog = require('./memoryLog');
|
|
16
16
|
const getIframeUrl = require('./getIframeUrl');
|
|
@@ -18,12 +18,14 @@ const createPagePool = require('./pagePool');
|
|
|
18
18
|
const getClientAPI = require('../dist/getClientAPI');
|
|
19
19
|
const {takeDomSnapshots} = require('@applitools/eyes-sdk-core');
|
|
20
20
|
const {Driver} = require('@applitools/driver');
|
|
21
|
-
const spec = require('@applitools/
|
|
21
|
+
const spec = require('@applitools/spec-driver-puppeteer');
|
|
22
22
|
const {refineErrorMessage} = require('./errMessages');
|
|
23
23
|
const {splitConfigsByBrowser} = require('./shouldRenderIE');
|
|
24
24
|
const executeRenders = require('./executeRenders');
|
|
25
25
|
|
|
26
26
|
const CONCURRENT_PAGES = 3;
|
|
27
|
+
const MAX_RETRIES = 10;
|
|
28
|
+
const RETRY_INTERVAL = 1000;
|
|
27
29
|
|
|
28
30
|
async function eyesStorybook({
|
|
29
31
|
config,
|
|
@@ -37,7 +39,7 @@ async function eyesStorybook({
|
|
|
37
39
|
let transitioning = false;
|
|
38
40
|
takeMemLoop();
|
|
39
41
|
logger.log('eyesStorybook started');
|
|
40
|
-
const {storybookUrl,
|
|
42
|
+
const {storybookUrl, waitBeforeCapture, readStoriesTimeout, reloadPagePerStory} = config;
|
|
41
43
|
|
|
42
44
|
let iframeUrl;
|
|
43
45
|
try {
|
|
@@ -76,20 +78,21 @@ async function eyesStorybook({
|
|
|
76
78
|
});
|
|
77
79
|
const pagePool = createPagePool({initPage, logger});
|
|
78
80
|
|
|
79
|
-
const doTakeDomSnapshots = async ({page, layoutBreakpoints}) => {
|
|
80
|
-
const driver = new Driver({spec, driver: page, logger
|
|
81
|
+
const doTakeDomSnapshots = async ({page, browser, layoutBreakpoints, waitBeforeCapture}) => {
|
|
82
|
+
const driver = await new Driver({spec, driver: page, logger}).init();
|
|
81
83
|
const skipResources = getResourceUrlsInCache();
|
|
82
84
|
const result = await takeDomSnapshots({
|
|
83
85
|
logger,
|
|
84
86
|
driver,
|
|
85
87
|
breakpoints: layoutBreakpoints !== undefined ? layoutBreakpoints : config.layoutBreakpoints,
|
|
86
|
-
browsers:
|
|
88
|
+
browsers: browser || [true], // this is a hack, since takeDomSnapshots expects an array. And VGC has a default in case browser is not specified. So we just need an array with length of 1 here.
|
|
87
89
|
skipResources,
|
|
88
90
|
showLogs: !!config.showLogs,
|
|
89
91
|
disableBrowserFetching: !!config.disableBrowserFetching,
|
|
90
92
|
getViewportSize: () => config.viewportSize,
|
|
91
93
|
getIosDevicesSizes,
|
|
92
94
|
getEmulatedDevicesSizes,
|
|
95
|
+
waitBeforeCapture,
|
|
93
96
|
});
|
|
94
97
|
return result;
|
|
95
98
|
};
|
|
@@ -113,14 +116,17 @@ async function eyesStorybook({
|
|
|
113
116
|
);
|
|
114
117
|
|
|
115
118
|
const filteredStories = filterStories({stories, config});
|
|
116
|
-
const
|
|
119
|
+
const storiesIncludingParametrizedVariations = addParametrizedStories({
|
|
120
|
+
stories: filteredStories,
|
|
121
|
+
config,
|
|
122
|
+
});
|
|
117
123
|
|
|
118
|
-
logger.log(`starting to run ${
|
|
124
|
+
logger.log(`starting to run ${storiesIncludingParametrizedVariations.length} stories`);
|
|
119
125
|
|
|
120
126
|
const getStoryData = makeGetStoryData({
|
|
121
127
|
logger,
|
|
122
128
|
takeDomSnapshots: doTakeDomSnapshots,
|
|
123
|
-
|
|
129
|
+
waitBeforeCapture,
|
|
124
130
|
});
|
|
125
131
|
|
|
126
132
|
const renderStory = makeRenderStory({
|
|
@@ -152,7 +158,7 @@ async function eyesStorybook({
|
|
|
152
158
|
setRenderIE,
|
|
153
159
|
setTransitioningIntoIE,
|
|
154
160
|
configs,
|
|
155
|
-
stories:
|
|
161
|
+
stories: storiesIncludingParametrizedVariations,
|
|
156
162
|
pagePool,
|
|
157
163
|
logger,
|
|
158
164
|
timeItAsync,
|
|
@@ -202,9 +208,9 @@ async function eyesStorybook({
|
|
|
202
208
|
spinner.fail(failMsg);
|
|
203
209
|
throw new Error();
|
|
204
210
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
211
|
+
|
|
212
|
+
const [getStoriesErr, stories] = await readStoriesWithRetry(MAX_RETRIES);
|
|
213
|
+
|
|
208
214
|
if (getStoriesErr) {
|
|
209
215
|
logger.log('Error in getStories:', getStoriesErr);
|
|
210
216
|
const failMsg = refineErrorMessage({
|
|
@@ -256,6 +262,19 @@ async function eyesStorybook({
|
|
|
256
262
|
function getTransitiongIntoIE() {
|
|
257
263
|
return transitioning;
|
|
258
264
|
}
|
|
265
|
+
|
|
266
|
+
async function readStoriesWithRetry(remainingRetries) {
|
|
267
|
+
const [getStoriesErr, stories] = await presult(
|
|
268
|
+
page.evaluate(getStories, {timeout: readStoriesTimeout}),
|
|
269
|
+
);
|
|
270
|
+
if (getStoriesErr || stories.length > 0 || remainingRetries == 0) {
|
|
271
|
+
return [getStoriesErr, stories];
|
|
272
|
+
} else {
|
|
273
|
+
logger.log(`Got 0 stories, retrying to read stories... ${remainingRetries - 1} are left`);
|
|
274
|
+
await delay(RETRY_INTERVAL);
|
|
275
|
+
return await readStoriesWithRetry(remainingRetries - 1);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
259
278
|
}
|
|
260
279
|
|
|
261
280
|
module.exports = eyesStorybook;
|
package/src/generateConfig.js
CHANGED
|
@@ -14,24 +14,29 @@ function generateConfig({argv = {}, defaultConfig = {}, externalConfigParams = [
|
|
|
14
14
|
const result = Object.assign({}, defaultConfig, config, argvConfig);
|
|
15
15
|
|
|
16
16
|
// backward compatibility
|
|
17
|
-
if (
|
|
18
|
-
result.waitBeforeScreenshots !== defaultConfig.waitBeforeScreenshots
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
result.waitBeforeScreenshot
|
|
17
|
+
if (result.waitBeforeCapture === defaultConfig.waitBeforeCapture) {
|
|
18
|
+
if (result.waitBeforeScreenshots !== defaultConfig.waitBeforeScreenshots) {
|
|
19
|
+
console.log(
|
|
20
|
+
deprecationWarning({
|
|
21
|
+
deprecatedThing: "'waitBeforeScreenshots'",
|
|
22
|
+
newThing: "'waitBeforeCapture'",
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
result.waitBeforeCapture = result.waitBeforeScreenshots;
|
|
26
|
+
}
|
|
27
|
+
if (result.waitBeforeScreenshot !== defaultConfig.waitBeforeScreenshot) {
|
|
28
|
+
console.log(
|
|
29
|
+
deprecationWarning({
|
|
30
|
+
deprecatedThing: "'waitBeforeScreenshot'",
|
|
31
|
+
newThing: "'waitBeforeCapture'",
|
|
32
|
+
}),
|
|
33
|
+
);
|
|
34
|
+
result.waitBeforeCapture = result.waitBeforeScreenshot;
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
!isNaN(parseInt(result.waitBeforeScreenshot))
|
|
33
|
-
) {
|
|
34
|
-
result.waitBeforeScreenshot = Number(result.waitBeforeScreenshot);
|
|
38
|
+
if (typeof result.waitBeforeCapture === 'string' && !isNaN(parseInt(result.waitBeforeCapture))) {
|
|
39
|
+
result.waitBeforeCapture = Number(result.waitBeforeCapture);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
if (result.showLogs === '1') {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const getStoryTitle = require('./getStoryTitle');
|
|
3
|
+
|
|
4
|
+
function getStoryBaselineName({name, kind, parameters}) {
|
|
5
|
+
const storyTitle = getStoryTitle({name, kind, parameters});
|
|
6
|
+
const queryParam = parameters && parameters.eyes && parameters.eyes.queryParam;
|
|
7
|
+
|
|
8
|
+
if (!queryParam || queryParam.name === 'eyes-variation') return storyTitle;
|
|
9
|
+
|
|
10
|
+
return `${storyTitle} [${queryParam.name}=${queryParam.value}]`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = getStoryBaselineName;
|
package/src/getStoryData.js
CHANGED
|
@@ -3,25 +3,30 @@ const {presult} = require('@applitools/functional-commons');
|
|
|
3
3
|
const {ArgumentGuard} = require('@applitools/eyes-sdk-core');
|
|
4
4
|
const renderStoryWithClientAPI = require('../dist/renderStoryWithClientAPI');
|
|
5
5
|
const runRunBeforeScript = require('../dist/runRunBeforeScript');
|
|
6
|
-
const
|
|
6
|
+
const getStoryBaselineName = require('./getStoryBaselineName');
|
|
7
7
|
const {URL} = require('url');
|
|
8
8
|
const runRunAfterScript = require('../dist/runRunAfterScript');
|
|
9
9
|
const waitFor = require('./waitFor');
|
|
10
10
|
|
|
11
|
-
function makeGetStoryData({logger, takeDomSnapshots,
|
|
12
|
-
return async function getStoryData({story, storyUrl, page, waitBeforeStory}) {
|
|
13
|
-
const title =
|
|
11
|
+
function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPagePerStory}) {
|
|
12
|
+
return async function getStoryData({story, storyUrl, page, browser, waitBeforeStory}) {
|
|
13
|
+
const title = getStoryBaselineName(story);
|
|
14
14
|
logger.log(`getting data from story`, title);
|
|
15
15
|
|
|
16
16
|
const eyesParameters = story.parameters && story.parameters.eyes;
|
|
17
17
|
if (story.isApi && !reloadPagePerStory) {
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const expectedQueryParam = eyesParameters ? eyesParameters.queryParam : undefined;
|
|
19
|
+
const actualQueryParam = await getQueryParam(
|
|
20
|
+
eyesParameters && eyesParameters.queryParams
|
|
21
|
+
? eyesParameters.queryParams.map(queryParam => queryParam.name)
|
|
22
|
+
: undefined,
|
|
23
|
+
);
|
|
22
24
|
if (
|
|
23
|
-
(!
|
|
24
|
-
|
|
25
|
+
(!actualQueryParam && !expectedQueryParam) ||
|
|
26
|
+
(actualQueryParam &&
|
|
27
|
+
expectedQueryParam &&
|
|
28
|
+
actualQueryParam.value === expectedQueryParam.name &&
|
|
29
|
+
actualQueryParam.value === expectedQueryParam.value)
|
|
25
30
|
) {
|
|
26
31
|
const err = await page.evaluate(renderStoryWithClientAPI, story.index);
|
|
27
32
|
err && handleRenderStoryError(err);
|
|
@@ -32,9 +37,9 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeScreenshot, reloa
|
|
|
32
37
|
await renderStoryLegacy();
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
const wait = waitBeforeStory ||
|
|
40
|
+
const wait = waitBeforeStory || waitBeforeCapture;
|
|
36
41
|
if (typeof wait === 'number') {
|
|
37
|
-
ArgumentGuard.greaterThanOrEqualToZero(wait, '
|
|
42
|
+
ArgumentGuard.greaterThanOrEqualToZero(wait, 'waitBeforeCapture', true);
|
|
38
43
|
}
|
|
39
44
|
if (wait) {
|
|
40
45
|
logger.log(`waiting before screenshot of ${title} ${wait}`);
|
|
@@ -49,9 +54,16 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeScreenshot, reloa
|
|
|
49
54
|
|
|
50
55
|
logger.log(`running takeDomSnapshot(s) for story ${title}`);
|
|
51
56
|
|
|
52
|
-
const
|
|
57
|
+
const result = await takeDomSnapshots({
|
|
53
58
|
page,
|
|
59
|
+
browser,
|
|
54
60
|
layoutBreakpoints: eyesParameters ? eyesParameters.layoutBreakpoints : undefined,
|
|
61
|
+
waitBeforeCapture: wait
|
|
62
|
+
? async () => {
|
|
63
|
+
logger.log(`waiting before screenshot of ${title} ${wait}`);
|
|
64
|
+
await waitFor(page, wait);
|
|
65
|
+
}
|
|
66
|
+
: undefined,
|
|
55
67
|
});
|
|
56
68
|
|
|
57
69
|
if (eyesParameters && eyesParameters.runAfter) {
|
|
@@ -61,7 +73,7 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeScreenshot, reloa
|
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
logger.log(`done getting data from story`, title);
|
|
64
|
-
return
|
|
76
|
+
return result;
|
|
65
77
|
|
|
66
78
|
async function renderStoryLegacy() {
|
|
67
79
|
logger.log(`getting data from story ${storyUrl}`);
|
|
@@ -72,9 +84,16 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeScreenshot, reloa
|
|
|
72
84
|
}
|
|
73
85
|
}
|
|
74
86
|
|
|
75
|
-
async function
|
|
87
|
+
async function getQueryParam(queryParamNames = []) {
|
|
76
88
|
try {
|
|
77
|
-
|
|
89
|
+
const url = new URL(await page.url());
|
|
90
|
+
queryParamNames = [...queryParamNames, 'eyes-variation'];
|
|
91
|
+
const queryParamName = queryParamNames.find(queryParamName =>
|
|
92
|
+
url.searchParams.has(queryParamName),
|
|
93
|
+
);
|
|
94
|
+
if (queryParamName) {
|
|
95
|
+
return {name: queryParamName, value: url.searchParams.get(queryParamName)};
|
|
96
|
+
}
|
|
78
97
|
} catch (ex) {
|
|
79
98
|
logger.log('failed to get url from page (in need of eyes-variation param)');
|
|
80
99
|
}
|
package/src/getStoryTitle.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
function getStoryTitle({name, kind, parameters}) {
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const queryParam = parameters && parameters.eyes && parameters.eyes.queryParam;
|
|
5
|
+
const variation =
|
|
6
|
+
queryParam && queryParam.name === 'eyes-variation' ? queryParam.value : undefined;
|
|
6
7
|
|
|
7
|
-
return `${kind}: ${name}${
|
|
8
|
+
return `${kind}: ${name}${variation ? ` [${variation}]` : ''}`;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
module.exports = getStoryTitle;
|
package/src/getStoryUrl.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
const getIframeUrl = require('./getIframeUrl');
|
|
3
3
|
|
|
4
4
|
function getStoryUrl({name, kind, parameters}, baseUrl) {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const queryParam = parameters && parameters.eyes && parameters.eyes.queryParam;
|
|
6
|
+
const queryParamString = queryParam ? `&${queryParam.name}=${queryParam.value}` : '';
|
|
7
7
|
|
|
8
8
|
return `${getIframeUrl(baseUrl)}&selectedKind=${encodeURIComponent(
|
|
9
9
|
kind,
|
|
10
|
-
)}&selectedStory=${encodeURIComponent(name)}${
|
|
10
|
+
)}&selectedStory=${encodeURIComponent(name)}${queryParamString}`;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
module.exports = getStoryUrl;
|
package/src/renderStories.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const getStoryUrl = require('./getStoryUrl');
|
|
3
|
-
const
|
|
3
|
+
const getStoryBaselineName = require('./getStoryBaselineName');
|
|
4
4
|
const ora = require('ora');
|
|
5
5
|
const {presult} = require('@applitools/functional-commons');
|
|
6
6
|
const {shouldRenderIE} = require('./shouldRenderIE');
|
|
@@ -61,16 +61,17 @@ function makeRenderStories({
|
|
|
61
61
|
async function processStory() {
|
|
62
62
|
const story = stories[currIndex++];
|
|
63
63
|
const storyUrl = getStoryUrl(story, storybookUrl);
|
|
64
|
-
const title =
|
|
65
|
-
const {
|
|
64
|
+
const title = getStoryBaselineName(story);
|
|
65
|
+
const {waitBeforeCapture} = (story.parameters && story.parameters.eyes) || {};
|
|
66
66
|
|
|
67
67
|
try {
|
|
68
68
|
let [error, storyData] = await presult(
|
|
69
69
|
getStoryData({
|
|
70
70
|
story,
|
|
71
71
|
storyUrl,
|
|
72
|
+
browser: config.browser,
|
|
72
73
|
page,
|
|
73
|
-
waitBeforeStory:
|
|
74
|
+
waitBeforeStory: waitBeforeCapture,
|
|
74
75
|
}),
|
|
75
76
|
);
|
|
76
77
|
|
|
@@ -89,8 +90,9 @@ function makeRenderStories({
|
|
|
89
90
|
getStoryData({
|
|
90
91
|
story,
|
|
91
92
|
storyUrl,
|
|
93
|
+
browser: config.browser,
|
|
92
94
|
page: newPageObj.page,
|
|
93
|
-
waitBeforeStory:
|
|
95
|
+
waitBeforeStory: waitBeforeCapture,
|
|
94
96
|
}),
|
|
95
97
|
);
|
|
96
98
|
error = newError;
|
|
@@ -107,7 +109,8 @@ function makeRenderStories({
|
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
const testResults = await renderStory({
|
|
110
|
-
snapshot: storyData,
|
|
112
|
+
snapshot: storyData.snapshots,
|
|
113
|
+
cookies: storyData.cookies,
|
|
111
114
|
url: storyUrl,
|
|
112
115
|
story,
|
|
113
116
|
config,
|
|
@@ -139,7 +142,7 @@ function makeRenderStories({
|
|
|
139
142
|
|
|
140
143
|
function onDoneStory(resultsOrErr, story) {
|
|
141
144
|
spinner.text = updateSpinnerText(++doneStories, stories.length);
|
|
142
|
-
const title =
|
|
145
|
+
const title = getStoryBaselineName(story);
|
|
143
146
|
allTestResults.push({title, resultsOrErr});
|
|
144
147
|
return {title, resultsOrErr};
|
|
145
148
|
}
|
package/src/renderStory.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const getStoryTitle = require('./getStoryTitle');
|
|
3
|
+
const getStoryBaselineName = require('./getStoryBaselineName');
|
|
3
4
|
const {deprecationWarning} = require('@applitools/eyes-sdk-core').GeneralUtils;
|
|
4
5
|
|
|
5
6
|
function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
|
|
6
7
|
return function renderStory({config, story, snapshot, url}) {
|
|
7
8
|
const {name, kind, parameters} = story;
|
|
9
|
+
const baselineName = getStoryBaselineName({name, kind, parameters});
|
|
8
10
|
const title = getStoryTitle({name, kind, parameters});
|
|
9
11
|
const eyesOptions = Object.assign({}, config, (parameters && parameters.eyes) || {});
|
|
10
12
|
const {
|
|
@@ -41,10 +43,11 @@ function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
|
|
|
41
43
|
ignoreRegionsBackCompat = ignore;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
logger.log(
|
|
46
|
+
logger.log(`running story ${title} with baseline ${baselineName}`);
|
|
45
47
|
|
|
46
48
|
const openParams = {
|
|
47
|
-
testName:
|
|
49
|
+
testName: baselineName,
|
|
50
|
+
displayName: title,
|
|
48
51
|
browser: config.browser,
|
|
49
52
|
properties: [
|
|
50
53
|
{name: 'Component name', value: kind},
|
|
@@ -77,12 +80,12 @@ function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
|
|
|
77
80
|
ignoreDisplacements,
|
|
78
81
|
};
|
|
79
82
|
|
|
80
|
-
return timeItAsync(
|
|
83
|
+
return timeItAsync(baselineName, async () => {
|
|
81
84
|
return testWindow({openParams, checkParams, throwEx: false});
|
|
82
85
|
}).then(onDoneStory);
|
|
83
86
|
|
|
84
87
|
function onDoneStory(results) {
|
|
85
|
-
logger.log('finished story',
|
|
88
|
+
logger.log('finished story', baselineName, 'in', performance[baselineName]);
|
|
86
89
|
return results;
|
|
87
90
|
}
|
|
88
91
|
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function addVariationStories({stories, config}) {
|
|
4
|
-
const globalVariationFunc =
|
|
5
|
-
typeof config.variations === 'function' ? config.variations : undefined;
|
|
6
|
-
const globalVariationArray = Array.isArray(config.variations) ? config.variations : undefined;
|
|
7
|
-
const storiesToAddVariations = stories.filter(getStoryVariations);
|
|
8
|
-
|
|
9
|
-
const storiesByVariation = {};
|
|
10
|
-
|
|
11
|
-
for (const story of storiesToAddVariations) {
|
|
12
|
-
const variations = getStoryVariations(story);
|
|
13
|
-
if (!Array.isArray(variations)) {
|
|
14
|
-
throw new Error('variations should be an array');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
for (const variation of variations) {
|
|
18
|
-
const variationArr = storiesByVariation[variation] || (storiesByVariation[variation] = []);
|
|
19
|
-
variationArr.push({
|
|
20
|
-
...story,
|
|
21
|
-
parameters: addFlagToParameters(story.parameters, variation),
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return Object.keys(storiesByVariation).reduce((storiesWithVariations, variation) => {
|
|
27
|
-
return storiesWithVariations.concat(storiesByVariation[variation]);
|
|
28
|
-
}, stories);
|
|
29
|
-
|
|
30
|
-
function getStoryVariations(story) {
|
|
31
|
-
if (story.parameters && story.parameters.eyes && story.parameters.eyes.variations) {
|
|
32
|
-
return story.parameters.eyes.variations;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (globalVariationFunc) {
|
|
36
|
-
return globalVariationFunc(story);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (globalVariationArray) return globalVariationArray;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function addFlagToParameters(parameters, variation) {
|
|
44
|
-
return parameters
|
|
45
|
-
? {
|
|
46
|
-
...parameters,
|
|
47
|
-
eyes: parameters.eyes
|
|
48
|
-
? {...parameters.eyes, variationUrlParam: variation}
|
|
49
|
-
: {variationUrlParam: variation},
|
|
50
|
-
}
|
|
51
|
-
: {eyes: {variationUrlParam: variation}};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
module.exports = addVariationStories;
|