@applitools/eyes-storybook 3.25.3 → 3.27.1
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 -1
- package/README.md +3 -4
- package/dist/getClientAPI.js +19 -1
- package/dist/getStories.js +19 -1
- package/dist/renderStoryWithClientAPI.js +21 -3
- package/dist/runRunAfterScript.js +19 -1
- package/dist/runRunBeforeScript.js +19 -1
- package/package.json +9 -10
- package/src/addVariationStories.js +84 -34
- package/src/browser/getClientAPI.js +19 -1
- package/src/browser/renderStoryWithClientAPI.js +2 -2
- package/src/eyesStorybook.js +8 -5
- package/src/getStoryBaselineName.js +19 -0
- package/src/getStoryData.js +29 -17
- package/src/getStoryTitle.js +3 -3
- package/src/getStoryUrl.js +6 -3
- package/src/renderStories.js +7 -4
- package/src/renderStory.js +20 -10
- package/src/storybookConnector.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## 3.27.1 - 2021/12/21
|
|
7
|
+
|
|
8
|
+
- add support for storybook api 6.4
|
|
9
|
+
- updated to @applitools/driver@1.4.5 (from 1.3.5)
|
|
10
|
+
- updated to @applitools/eyes-sdk-core@12.24.7 (from 12.24.5)
|
|
11
|
+
- updated to @applitools/logger@1.0.7 (from 1.0.6)
|
|
12
|
+
- updated to @applitools/test-server@1.0.8 (from 1.0.7)
|
|
13
|
+
- updated to @applitools/visual-grid-client@15.8.53 (from 15.8.49)
|
|
14
|
+
|
|
15
|
+
## 3.27.0 - 2021/12/6
|
|
16
|
+
|
|
17
|
+
- support custom properties and query params
|
|
18
|
+
- remove `queryParams` api from story and global config
|
|
19
|
+
|
|
20
|
+
## 3.26.1 - 2021/11/28
|
|
21
|
+
|
|
22
|
+
- add custom test properties to stories with query params
|
|
23
|
+
|
|
24
|
+
## 3.26.0 - 2021/11/26
|
|
25
|
+
|
|
26
|
+
- add support for `queryParams` config property
|
|
27
|
+
- updated to @applitools/driver@1.3.5 (from 1.2.7)
|
|
28
|
+
- updated to @applitools/eyes-puppeteer@1.9.0 (from 1.8.5)
|
|
29
|
+
- updated to @applitools/eyes-sdk-core@12.24.5 (from 12.23.24)
|
|
30
|
+
- updated to @applitools/logger@1.0.6 (from 1.0.5)
|
|
31
|
+
- updated to @applitools/test-server@1.0.7 (from 1.0.6)
|
|
32
|
+
- updated to @applitools/visual-grid-client@15.8.49 (from 15.8.43)
|
|
33
|
+
|
|
5
34
|
## 3.25.3 - 2021/11/1
|
|
6
35
|
|
|
7
|
-
|
|
36
|
+
- add a retry mechanism for cases we get 0 stories
|
|
8
37
|
|
|
9
38
|
## 3.25.2 - 2021/10/30
|
|
10
39
|
|
package/README.md
CHANGED
|
@@ -423,10 +423,9 @@ storiesOf('Some kind', module)
|
|
|
423
423
|
|
|
424
424
|
### `variations`
|
|
425
425
|
|
|
426
|
-
An array of
|
|
426
|
+
An array of object values, which specifies which variations to add for this story. For each value, an additional visual test will be executed for the component. Each variation could contain `queryParams` and `properties` fields to specifies custom query parameters and eyes properties respectfully. Variation tests will have the same name.
|
|
427
427
|
|
|
428
|
-
This can accommodate many use cases, for example
|
|
429
|
-
It's now possible for the component to render its variation version when the relevant URL param is present. For Example, here's a storybook that handles an RTL variation:
|
|
428
|
+
This can accommodate many use cases, for example `@storybook/addon-contexts`. With addons like this it is possible to render components in a different way depends on query parameters in URL. For Example, here's a storybook that handles an RTL variation:
|
|
430
429
|
|
|
431
430
|
```js
|
|
432
431
|
const isRTL = new URL(window.location).searchParams.get('eyes-variation') === 'RTL';
|
|
@@ -443,7 +442,7 @@ storiesOf('Components that support RTL', module)
|
|
|
443
442
|
<span>I am visually perfect!</span>
|
|
444
443
|
<span>{isRTL ? ' and rendered right to left as well :)' : ''}</span>
|
|
445
444
|
</div>,
|
|
446
|
-
{eyes: {variations: ['RTL']}}
|
|
445
|
+
{eyes: {variations: [{queryParams: {'eyes-variation': 'RTL'}, properties: {name: 'isRTL', value: 'true'}, {properties: {name: 'isRTL', value: 'false'}}]}}
|
|
447
446
|
)
|
|
448
447
|
```
|
|
449
448
|
|
package/dist/getClientAPI.js
CHANGED
|
@@ -7,6 +7,7 @@ function __getClientAPI(...args) {
|
|
|
7
7
|
v4: 'v4',
|
|
8
8
|
v5: 'v5',
|
|
9
9
|
v5_2: 'v5_2',
|
|
10
|
+
v6_4: 'v6_4',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function getClientAPI() {
|
|
@@ -19,7 +20,9 @@ function __getClientAPI(...args) {
|
|
|
19
20
|
function getStorybookVersion() {
|
|
20
21
|
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
21
22
|
|
|
22
|
-
if (frameWindow.
|
|
23
|
+
if (frameWindow.__STORYBOOK_PREVIEW__) {
|
|
24
|
+
return API_VERSIONS.v6_4;
|
|
25
|
+
} else if (frameWindow.__STORYBOOK_STORY_STORE__) {
|
|
23
26
|
return API_VERSIONS.v5_2;
|
|
24
27
|
} else if (frameWindow.__STORYBOOK_CLIENT_API__ && frameWindow.__STORYBOOK_CLIENT_API__.raw) {
|
|
25
28
|
return API_VERSIONS.v5;
|
|
@@ -81,6 +84,21 @@ function __getClientAPI(...args) {
|
|
|
81
84
|
};
|
|
82
85
|
break;
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
case API_VERSIONS.v6_4: {
|
|
89
|
+
api = {
|
|
90
|
+
getStories: () => {
|
|
91
|
+
return clientAPI.raw();
|
|
92
|
+
},
|
|
93
|
+
selectStory: async i => {
|
|
94
|
+
frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
|
|
95
|
+
storyId: clientAPI.raw()[i].id,
|
|
96
|
+
});
|
|
97
|
+
await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
return {version, ...api};
|
package/dist/getStories.js
CHANGED
|
@@ -7,6 +7,7 @@ function __getStories(...args) {
|
|
|
7
7
|
v4: 'v4',
|
|
8
8
|
v5: 'v5',
|
|
9
9
|
v5_2: 'v5_2',
|
|
10
|
+
v6_4: 'v6_4',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function getClientAPI() {
|
|
@@ -19,7 +20,9 @@ function __getStories(...args) {
|
|
|
19
20
|
function getStorybookVersion() {
|
|
20
21
|
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
21
22
|
|
|
22
|
-
if (frameWindow.
|
|
23
|
+
if (frameWindow.__STORYBOOK_PREVIEW__) {
|
|
24
|
+
return API_VERSIONS.v6_4;
|
|
25
|
+
} else if (frameWindow.__STORYBOOK_STORY_STORE__) {
|
|
23
26
|
return API_VERSIONS.v5_2;
|
|
24
27
|
} else if (frameWindow.__STORYBOOK_CLIENT_API__ && frameWindow.__STORYBOOK_CLIENT_API__.raw) {
|
|
25
28
|
return API_VERSIONS.v5;
|
|
@@ -81,6 +84,21 @@ function __getStories(...args) {
|
|
|
81
84
|
};
|
|
82
85
|
break;
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
case API_VERSIONS.v6_4: {
|
|
89
|
+
api = {
|
|
90
|
+
getStories: () => {
|
|
91
|
+
return clientAPI.raw();
|
|
92
|
+
},
|
|
93
|
+
selectStory: async i => {
|
|
94
|
+
frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
|
|
95
|
+
storyId: clientAPI.raw()[i].id,
|
|
96
|
+
});
|
|
97
|
+
await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
return {version, ...api};
|
|
@@ -7,6 +7,7 @@ function __renderStoryWithClientAPI(...args) {
|
|
|
7
7
|
v4: 'v4',
|
|
8
8
|
v5: 'v5',
|
|
9
9
|
v5_2: 'v5_2',
|
|
10
|
+
v6_4: 'v6_4',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function getClientAPI() {
|
|
@@ -19,7 +20,9 @@ function __renderStoryWithClientAPI(...args) {
|
|
|
19
20
|
function getStorybookVersion() {
|
|
20
21
|
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
21
22
|
|
|
22
|
-
if (frameWindow.
|
|
23
|
+
if (frameWindow.__STORYBOOK_PREVIEW__) {
|
|
24
|
+
return API_VERSIONS.v6_4;
|
|
25
|
+
} else if (frameWindow.__STORYBOOK_STORY_STORE__) {
|
|
23
26
|
return API_VERSIONS.v5_2;
|
|
24
27
|
} else if (frameWindow.__STORYBOOK_CLIENT_API__ && frameWindow.__STORYBOOK_CLIENT_API__.raw) {
|
|
25
28
|
return API_VERSIONS.v5;
|
|
@@ -81,6 +84,21 @@ function __renderStoryWithClientAPI(...args) {
|
|
|
81
84
|
};
|
|
82
85
|
break;
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
case API_VERSIONS.v6_4: {
|
|
89
|
+
api = {
|
|
90
|
+
getStories: () => {
|
|
91
|
+
return clientAPI.raw();
|
|
92
|
+
},
|
|
93
|
+
selectStory: async i => {
|
|
94
|
+
frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
|
|
95
|
+
storyId: clientAPI.raw()[i].id,
|
|
96
|
+
});
|
|
97
|
+
await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
return {version, ...api};
|
|
@@ -112,11 +130,11 @@ function __renderStoryWithClientAPI(...args) {
|
|
|
112
130
|
|
|
113
131
|
var getClientAPI_1 = getClientAPI;
|
|
114
132
|
|
|
115
|
-
function renderStoryWithClientAPI(index) {
|
|
133
|
+
async function renderStoryWithClientAPI(index) {
|
|
116
134
|
let api;
|
|
117
135
|
try {
|
|
118
136
|
api = getClientAPI_1();
|
|
119
|
-
api.selectStory(index);
|
|
137
|
+
await api.selectStory(index);
|
|
120
138
|
} catch (ex) {
|
|
121
139
|
return {message: ex.message, version: api ? api.version : undefined};
|
|
122
140
|
}
|
|
@@ -7,6 +7,7 @@ function __runRunAfterScript(...args) {
|
|
|
7
7
|
v4: 'v4',
|
|
8
8
|
v5: 'v5',
|
|
9
9
|
v5_2: 'v5_2',
|
|
10
|
+
v6_4: 'v6_4',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function getClientAPI() {
|
|
@@ -19,7 +20,9 @@ function __runRunAfterScript(...args) {
|
|
|
19
20
|
function getStorybookVersion() {
|
|
20
21
|
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
21
22
|
|
|
22
|
-
if (frameWindow.
|
|
23
|
+
if (frameWindow.__STORYBOOK_PREVIEW__) {
|
|
24
|
+
return API_VERSIONS.v6_4;
|
|
25
|
+
} else if (frameWindow.__STORYBOOK_STORY_STORE__) {
|
|
23
26
|
return API_VERSIONS.v5_2;
|
|
24
27
|
} else if (frameWindow.__STORYBOOK_CLIENT_API__ && frameWindow.__STORYBOOK_CLIENT_API__.raw) {
|
|
25
28
|
return API_VERSIONS.v5;
|
|
@@ -81,6 +84,21 @@ function __runRunAfterScript(...args) {
|
|
|
81
84
|
};
|
|
82
85
|
break;
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
case API_VERSIONS.v6_4: {
|
|
89
|
+
api = {
|
|
90
|
+
getStories: () => {
|
|
91
|
+
return clientAPI.raw();
|
|
92
|
+
},
|
|
93
|
+
selectStory: async i => {
|
|
94
|
+
frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
|
|
95
|
+
storyId: clientAPI.raw()[i].id,
|
|
96
|
+
});
|
|
97
|
+
await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
return {version, ...api};
|
|
@@ -7,6 +7,7 @@ function __runRunBeforeScript(...args) {
|
|
|
7
7
|
v4: 'v4',
|
|
8
8
|
v5: 'v5',
|
|
9
9
|
v5_2: 'v5_2',
|
|
10
|
+
v6_4: 'v6_4',
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function getClientAPI() {
|
|
@@ -19,7 +20,9 @@ function __runRunBeforeScript(...args) {
|
|
|
19
20
|
function getStorybookVersion() {
|
|
20
21
|
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
21
22
|
|
|
22
|
-
if (frameWindow.
|
|
23
|
+
if (frameWindow.__STORYBOOK_PREVIEW__) {
|
|
24
|
+
return API_VERSIONS.v6_4;
|
|
25
|
+
} else if (frameWindow.__STORYBOOK_STORY_STORE__) {
|
|
23
26
|
return API_VERSIONS.v5_2;
|
|
24
27
|
} else if (frameWindow.__STORYBOOK_CLIENT_API__ && frameWindow.__STORYBOOK_CLIENT_API__.raw) {
|
|
25
28
|
return API_VERSIONS.v5;
|
|
@@ -81,6 +84,21 @@ function __runRunBeforeScript(...args) {
|
|
|
81
84
|
};
|
|
82
85
|
break;
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
case API_VERSIONS.v6_4: {
|
|
89
|
+
api = {
|
|
90
|
+
getStories: () => {
|
|
91
|
+
return clientAPI.raw();
|
|
92
|
+
},
|
|
93
|
+
selectStory: async i => {
|
|
94
|
+
frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
|
|
95
|
+
storyId: clientAPI.raw()[i].id,
|
|
96
|
+
});
|
|
97
|
+
await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
return {version, ...api};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-storybook",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.27.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=8.6.0"
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
"directory": "packages/eyes-storybook"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@applitools/driver": "1.
|
|
62
|
-
"@applitools/eyes-
|
|
63
|
-
"@applitools/eyes-sdk-core": "12.23.24",
|
|
61
|
+
"@applitools/driver": "1.4.5",
|
|
62
|
+
"@applitools/eyes-sdk-core": "12.24.7",
|
|
64
63
|
"@applitools/functional-commons": "1.6.0",
|
|
65
|
-
"@applitools/logger": "1.0.
|
|
64
|
+
"@applitools/logger": "1.0.7",
|
|
66
65
|
"@applitools/monitoring-commons": "1.0.19",
|
|
67
|
-
"@applitools/
|
|
68
|
-
"@applitools/
|
|
66
|
+
"@applitools/spec-driver-puppeteer": "1.1.0",
|
|
67
|
+
"@applitools/test-server": "1.0.8",
|
|
68
|
+
"@applitools/visual-grid-client": "15.8.53",
|
|
69
69
|
"boxen": "4.2.0",
|
|
70
70
|
"chalk": "3.0.0",
|
|
71
71
|
"detect-port": "1.3.0",
|
|
@@ -79,11 +79,10 @@
|
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@applitools/scripts": "^1.0.1",
|
|
81
81
|
"@applitools/sdk-release-kit": "0.13.4",
|
|
82
|
-
"@applitools/sdk-shared": "0.9.
|
|
82
|
+
"@applitools/sdk-shared": "0.9.11",
|
|
83
83
|
"@applitools/snaptdout": "^1.0.1",
|
|
84
84
|
"@applitools/utils": "1.2.4",
|
|
85
|
-
"@storybook/
|
|
86
|
-
"@storybook/react": "^5.2.8",
|
|
85
|
+
"@storybook/react": "^6.4.0",
|
|
87
86
|
"@testing-library/dom": "^5.6.1",
|
|
88
87
|
"babel-core": "^6.26.3",
|
|
89
88
|
"babel-loader": "^8.0.6",
|
|
@@ -1,54 +1,104 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
function addVariationStories({stories, config}) {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
4
|
+
const defaultStories = [];
|
|
5
|
+
const variationStories = {};
|
|
6
|
+
for (const story of stories) {
|
|
7
|
+
const variations = getStoryVariations(story, config);
|
|
8
|
+
if (variations) {
|
|
9
|
+
for (const variation of variations) {
|
|
10
|
+
const variationKey = stringifyVariation(variation);
|
|
11
|
+
const variationStoriesArray =
|
|
12
|
+
variationStories[variationKey] || (variationStories[variationKey] = []);
|
|
13
|
+
const variationStory = {...story};
|
|
14
|
+
if (variation.queryParams || variation.properties) {
|
|
15
|
+
variationStory.parameters = addVariation(story.parameters, variation);
|
|
16
|
+
}
|
|
17
|
+
variationStoriesArray.push(variationStory);
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
defaultStories.push(story);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
8
23
|
|
|
9
|
-
|
|
24
|
+
return Object.values(variationStories).reduce((allStories, variationStories) => {
|
|
25
|
+
return allStories.concat(variationStories);
|
|
26
|
+
}, defaultStories);
|
|
27
|
+
}
|
|
10
28
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (!Array.isArray(variations)) {
|
|
29
|
+
function getStoryVariations(story, config) {
|
|
30
|
+
if (story.parameters && story.parameters.eyes && story.parameters.eyes.variations) {
|
|
31
|
+
if (!Array.isArray(story.parameters.eyes.variations)) {
|
|
14
32
|
throw new Error('variations should be an array');
|
|
15
33
|
}
|
|
34
|
+
return normalizeVariations(story.parameters.eyes.variations);
|
|
35
|
+
}
|
|
16
36
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
37
|
+
if (config.variations) {
|
|
38
|
+
if (Array.isArray(config.variations)) {
|
|
39
|
+
return normalizeVariations(config.variations);
|
|
40
|
+
} else if (typeof config.variations === 'function') {
|
|
41
|
+
const variations = config.variations(story);
|
|
42
|
+
if (variations) {
|
|
43
|
+
if (!Array.isArray(variations)) {
|
|
44
|
+
throw new Error('global variations should be a function that returns array');
|
|
45
|
+
}
|
|
46
|
+
return normalizeVariations(variations);
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
throw new Error('global variations should be an array or a function that returns array');
|
|
23
50
|
}
|
|
24
51
|
}
|
|
52
|
+
}
|
|
25
53
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
54
|
+
function normalizeVariations(variations) {
|
|
55
|
+
let shouldHasDefault = false; // default variation is one without query params
|
|
56
|
+
const normalizedVariations = variations.map(variation => {
|
|
57
|
+
if (typeof variation === 'string') {
|
|
58
|
+
shouldHasDefault = true;
|
|
59
|
+
return {
|
|
60
|
+
queryParams: {'eyes-variation': variation},
|
|
61
|
+
properties: [{name: 'eyes-variation', value: variation}],
|
|
62
|
+
};
|
|
33
63
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
64
|
+
if (variation.queryParams && (!variation.properties || variation.properties.length === 0)) {
|
|
65
|
+
return {
|
|
66
|
+
...variation,
|
|
67
|
+
properties: Object.entries(variation.queryParams).map(([name, value]) => ({name, value})),
|
|
68
|
+
};
|
|
37
69
|
}
|
|
70
|
+
return variation;
|
|
71
|
+
});
|
|
38
72
|
|
|
39
|
-
|
|
73
|
+
// if it should has default variation and it is not already there
|
|
74
|
+
if (shouldHasDefault && !normalizedVariations.some(variation => !variation.queryParams)) {
|
|
75
|
+
normalizedVariations.unshift({});
|
|
40
76
|
}
|
|
77
|
+
|
|
78
|
+
return normalizedVariations;
|
|
41
79
|
}
|
|
42
80
|
|
|
43
|
-
function
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
81
|
+
function stringifyVariation(variation) {
|
|
82
|
+
if (!variation.queryParams) return '';
|
|
83
|
+
return Object.keys(variation.queryParams)
|
|
84
|
+
.sort()
|
|
85
|
+
.map(name => `${name}=${variation.queryParams[name]}`)
|
|
86
|
+
.join('&');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function addVariation(parameters, variation) {
|
|
90
|
+
parameters = {...parameters};
|
|
91
|
+
parameters.eyes = {...parameters.eyes};
|
|
92
|
+
if (variation.queryParams) {
|
|
93
|
+
parameters.eyes.queryParams = variation.queryParams;
|
|
94
|
+
}
|
|
95
|
+
if (variation.properties) {
|
|
96
|
+
parameters.eyes.properties = [
|
|
97
|
+
...(parameters.eyes.properties || []),
|
|
98
|
+
...(variation.properties || []),
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
return parameters;
|
|
52
102
|
}
|
|
53
103
|
|
|
54
104
|
module.exports = addVariationStories;
|
|
@@ -4,6 +4,7 @@ const API_VERSIONS = {
|
|
|
4
4
|
v4: 'v4',
|
|
5
5
|
v5: 'v5',
|
|
6
6
|
v5_2: 'v5_2',
|
|
7
|
+
v6_4: 'v6_4',
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
function getClientAPI() {
|
|
@@ -16,7 +17,9 @@ function getClientAPI() {
|
|
|
16
17
|
function getStorybookVersion() {
|
|
17
18
|
const addons = frameWindow.__STORYBOOK_ADDONS;
|
|
18
19
|
|
|
19
|
-
if (frameWindow.
|
|
20
|
+
if (frameWindow.__STORYBOOK_PREVIEW__) {
|
|
21
|
+
return API_VERSIONS.v6_4;
|
|
22
|
+
} else if (frameWindow.__STORYBOOK_STORY_STORE__) {
|
|
20
23
|
return API_VERSIONS.v5_2;
|
|
21
24
|
} else if (frameWindow.__STORYBOOK_CLIENT_API__ && frameWindow.__STORYBOOK_CLIENT_API__.raw) {
|
|
22
25
|
return API_VERSIONS.v5;
|
|
@@ -78,6 +81,21 @@ function getClientAPI() {
|
|
|
78
81
|
};
|
|
79
82
|
break;
|
|
80
83
|
}
|
|
84
|
+
|
|
85
|
+
case API_VERSIONS.v6_4: {
|
|
86
|
+
api = {
|
|
87
|
+
getStories: () => {
|
|
88
|
+
return clientAPI.raw();
|
|
89
|
+
},
|
|
90
|
+
selectStory: async i => {
|
|
91
|
+
frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
|
|
92
|
+
storyId: clientAPI.raw()[i].id,
|
|
93
|
+
});
|
|
94
|
+
await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
81
99
|
}
|
|
82
100
|
|
|
83
101
|
return {version, ...api};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const getClientAPI = require('./getClientAPI');
|
|
2
2
|
|
|
3
|
-
function renderStoryWithClientAPI(index) {
|
|
3
|
+
async function renderStoryWithClientAPI(index) {
|
|
4
4
|
let api;
|
|
5
5
|
try {
|
|
6
6
|
api = getClientAPI();
|
|
7
|
-
api.selectStory(index);
|
|
7
|
+
await api.selectStory(index);
|
|
8
8
|
} catch (ex) {
|
|
9
9
|
return {message: ex.message, version: api ? api.version : undefined};
|
|
10
10
|
}
|
package/src/eyesStorybook.js
CHANGED
|
@@ -18,7 +18,7 @@ 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');
|
|
@@ -78,14 +78,14 @@ async function eyesStorybook({
|
|
|
78
78
|
});
|
|
79
79
|
const pagePool = createPagePool({initPage, logger});
|
|
80
80
|
|
|
81
|
-
const doTakeDomSnapshots = async ({page, layoutBreakpoints, waitBeforeCapture}) => {
|
|
82
|
-
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();
|
|
83
83
|
const skipResources = getResourceUrlsInCache();
|
|
84
84
|
const result = await takeDomSnapshots({
|
|
85
85
|
logger,
|
|
86
86
|
driver,
|
|
87
87
|
breakpoints: layoutBreakpoints !== undefined ? layoutBreakpoints : config.layoutBreakpoints,
|
|
88
|
-
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.
|
|
89
89
|
skipResources,
|
|
90
90
|
showLogs: !!config.showLogs,
|
|
91
91
|
disableBrowserFetching: !!config.disableBrowserFetching,
|
|
@@ -116,7 +116,10 @@ async function eyesStorybook({
|
|
|
116
116
|
);
|
|
117
117
|
|
|
118
118
|
const filteredStories = filterStories({stories, config});
|
|
119
|
-
const storiesIncludingVariations = addVariationStories({
|
|
119
|
+
const storiesIncludingVariations = addVariationStories({
|
|
120
|
+
stories: filteredStories,
|
|
121
|
+
config,
|
|
122
|
+
});
|
|
120
123
|
|
|
121
124
|
logger.log(`starting to run ${storiesIncludingVariations.length} stories`);
|
|
122
125
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const getStoryTitle = require('./getStoryTitle');
|
|
3
|
+
|
|
4
|
+
function getStoryBaselineName({name, kind, parameters}) {
|
|
5
|
+
const storyTitle = getStoryTitle({name, kind, parameters});
|
|
6
|
+
const queryParams = parameters && parameters.eyes && parameters.eyes.queryParams;
|
|
7
|
+
if (!queryParams) return storyTitle;
|
|
8
|
+
const customQueryParams = {...queryParams};
|
|
9
|
+
delete customQueryParams['eyes-variation'];
|
|
10
|
+
if (Object.keys(customQueryParams).length === 0) return storyTitle;
|
|
11
|
+
|
|
12
|
+
const queryParamsString = Object.entries(customQueryParams)
|
|
13
|
+
.map(([name, value]) => `${name}=${value}`)
|
|
14
|
+
.join('&');
|
|
15
|
+
|
|
16
|
+
return `${storyTitle} [${queryParamsString}]`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = getStoryBaselineName;
|
package/src/getStoryData.js
CHANGED
|
@@ -3,26 +3,21 @@ 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
11
|
function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPagePerStory}) {
|
|
12
|
-
return async function getStoryData({story, storyUrl, page, waitBeforeStory}) {
|
|
13
|
-
const title =
|
|
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
|
-
: undefined;
|
|
22
|
-
if (
|
|
23
|
-
(!actualVariationParam && !expectedVariationUrlParam) ||
|
|
24
|
-
actualVariationParam === expectedVariationUrlParam
|
|
25
|
-
) {
|
|
18
|
+
const currentUrl = page.url();
|
|
19
|
+
const expectedQueryParams = eyesParameters ? eyesParameters.queryParams : undefined;
|
|
20
|
+
if (urlQueryParamsEquals(currentUrl, expectedQueryParams)) {
|
|
26
21
|
const err = await page.evaluate(renderStoryWithClientAPI, story.index);
|
|
27
22
|
err && handleRenderStoryError(err);
|
|
28
23
|
} else {
|
|
@@ -49,8 +44,9 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
|
|
|
49
44
|
|
|
50
45
|
logger.log(`running takeDomSnapshot(s) for story ${title}`);
|
|
51
46
|
|
|
52
|
-
const
|
|
47
|
+
const result = await takeDomSnapshots({
|
|
53
48
|
page,
|
|
49
|
+
browser,
|
|
54
50
|
layoutBreakpoints: eyesParameters ? eyesParameters.layoutBreakpoints : undefined,
|
|
55
51
|
waitBeforeCapture: wait
|
|
56
52
|
? async () => {
|
|
@@ -67,7 +63,7 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
|
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
logger.log(`done getting data from story`, title);
|
|
70
|
-
return
|
|
66
|
+
return result;
|
|
71
67
|
|
|
72
68
|
async function renderStoryLegacy() {
|
|
73
69
|
logger.log(`getting data from story ${storyUrl}`);
|
|
@@ -78,12 +74,28 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
|
|
|
78
74
|
}
|
|
79
75
|
}
|
|
80
76
|
|
|
81
|
-
|
|
77
|
+
function urlQueryParamsEquals(url, expectedQueryParams) {
|
|
82
78
|
try {
|
|
83
|
-
|
|
84
|
-
} catch (
|
|
85
|
-
logger.
|
|
79
|
+
url = new URL(url);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
logger.error('Error during parsing page url', err);
|
|
82
|
+
return false;
|
|
86
83
|
}
|
|
84
|
+
|
|
85
|
+
expectedQueryParams = expectedQueryParams || {};
|
|
86
|
+
const expectedQueryParamNames = Object.keys(expectedQueryParams);
|
|
87
|
+
const actualQueryParamNames = [];
|
|
88
|
+
for (const [name, value] of url.searchParams) {
|
|
89
|
+
if (['eyes-storybook', 'selectedKind', 'selectedStory'].includes(name)) continue;
|
|
90
|
+
if (!expectedQueryParams.hasOwnProperty(name) || !expectedQueryParams[name] === value) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
actualQueryParamNames.push(name);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (actualQueryParamNames.length !== expectedQueryParamNames.length) return false;
|
|
97
|
+
|
|
98
|
+
return true;
|
|
87
99
|
}
|
|
88
100
|
|
|
89
101
|
// TODO (amit): handle this error in the caller (probably renderStories)
|
package/src/getStoryTitle.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
function getStoryTitle({name, kind, parameters}) {
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const queryParams = (parameters && parameters.eyes && parameters.eyes.queryParams) || {};
|
|
5
|
+
const eyesVariation = queryParams['eyes-variation'];
|
|
6
6
|
|
|
7
|
-
return `${kind}: ${name}${
|
|
7
|
+
return `${kind}: ${name}${eyesVariation ? ` [${eyesVariation}]` : ''}`;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
module.exports = getStoryTitle;
|
package/src/getStoryUrl.js
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
const getIframeUrl = require('./getIframeUrl');
|
|
3
3
|
|
|
4
4
|
function getStoryUrl({name, kind, parameters}, baseUrl) {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const queryParams = (parameters && parameters.eyes && parameters.eyes.queryParams) || {};
|
|
6
|
+
const queryString = Object.entries(queryParams).reduce(
|
|
7
|
+
(queryString, [name, value]) => queryString + `&${name}=${value}`,
|
|
8
|
+
'',
|
|
9
|
+
);
|
|
7
10
|
|
|
8
11
|
return `${getIframeUrl(baseUrl)}&selectedKind=${encodeURIComponent(
|
|
9
12
|
kind,
|
|
10
|
-
)}&selectedStory=${encodeURIComponent(name)}${
|
|
13
|
+
)}&selectedStory=${encodeURIComponent(name)}${queryString}`;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
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,7 +61,7 @@ function makeRenderStories({
|
|
|
61
61
|
async function processStory() {
|
|
62
62
|
const story = stories[currIndex++];
|
|
63
63
|
const storyUrl = getStoryUrl(story, storybookUrl);
|
|
64
|
-
const title =
|
|
64
|
+
const title = getStoryBaselineName(story);
|
|
65
65
|
const {waitBeforeCapture} = (story.parameters && story.parameters.eyes) || {};
|
|
66
66
|
|
|
67
67
|
try {
|
|
@@ -69,6 +69,7 @@ function makeRenderStories({
|
|
|
69
69
|
getStoryData({
|
|
70
70
|
story,
|
|
71
71
|
storyUrl,
|
|
72
|
+
browser: config.browser,
|
|
72
73
|
page,
|
|
73
74
|
waitBeforeStory: waitBeforeCapture,
|
|
74
75
|
}),
|
|
@@ -89,6 +90,7 @@ function makeRenderStories({
|
|
|
89
90
|
getStoryData({
|
|
90
91
|
story,
|
|
91
92
|
storyUrl,
|
|
93
|
+
browser: config.browser,
|
|
92
94
|
page: newPageObj.page,
|
|
93
95
|
waitBeforeStory: waitBeforeCapture,
|
|
94
96
|
}),
|
|
@@ -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,12 +1,19 @@
|
|
|
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
|
-
const
|
|
11
|
+
const eyesParameters = (parameters && parameters.eyes) || {};
|
|
12
|
+
const eyesOptions = {
|
|
13
|
+
...config,
|
|
14
|
+
...eyesParameters,
|
|
15
|
+
properties: [...(config.properties || []), ...(eyesParameters.properties || [])],
|
|
16
|
+
};
|
|
10
17
|
const {
|
|
11
18
|
ignoreDisplacements,
|
|
12
19
|
ignoreRegions,
|
|
@@ -41,16 +48,19 @@ function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
|
|
|
41
48
|
ignoreRegionsBackCompat = ignore;
|
|
42
49
|
}
|
|
43
50
|
|
|
44
|
-
logger.log(
|
|
51
|
+
logger.log(`running story ${title} with baseline ${baselineName}`);
|
|
52
|
+
|
|
53
|
+
const storyProperties = [
|
|
54
|
+
{name: 'Component name', value: kind},
|
|
55
|
+
{name: 'State', value: name},
|
|
56
|
+
...(properties || []),
|
|
57
|
+
];
|
|
45
58
|
|
|
46
59
|
const openParams = {
|
|
47
|
-
testName:
|
|
60
|
+
testName: baselineName,
|
|
61
|
+
displayName: title,
|
|
48
62
|
browser: config.browser,
|
|
49
|
-
properties:
|
|
50
|
-
{name: 'Component name', value: kind},
|
|
51
|
-
{name: 'State', value: name},
|
|
52
|
-
...(properties || []),
|
|
53
|
-
],
|
|
63
|
+
properties: storyProperties,
|
|
54
64
|
accessibilitySettings: accessibilityValidation,
|
|
55
65
|
};
|
|
56
66
|
|
|
@@ -77,12 +87,12 @@ function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
|
|
|
77
87
|
ignoreDisplacements,
|
|
78
88
|
};
|
|
79
89
|
|
|
80
|
-
return timeItAsync(
|
|
90
|
+
return timeItAsync(baselineName, async () => {
|
|
81
91
|
return testWindow({openParams, checkParams, throwEx: false});
|
|
82
92
|
}).then(onDoneStory);
|
|
83
93
|
|
|
84
94
|
function onDoneStory(results) {
|
|
85
|
-
logger.log('finished story',
|
|
95
|
+
logger.log('finished story', baselineName, 'in', performance[baselineName]);
|
|
86
96
|
return results;
|
|
87
97
|
}
|
|
88
98
|
};
|
|
@@ -72,7 +72,7 @@ class StorybookConnector extends EventEmitter {
|
|
|
72
72
|
|
|
73
73
|
const successMessageListener = str => {
|
|
74
74
|
const isReady = stripAnsi(str).match(
|
|
75
|
-
/Storybook \d{1,2}\.\d{1,2}\.\d{1,2}(
|
|
75
|
+
/Storybook \d{1,2}\.\d{1,2}\.\d{1,2}(.+)? started|Storybook started on =>/,
|
|
76
76
|
);
|
|
77
77
|
|
|
78
78
|
if (isReady) {
|