@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 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
- - add a retry machanisem for cases we get 0 stories
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 string values, which specifies which variations to add for this story. For each value, an additional visual test will be executed for the component. It will have the same name only with a `[<variation name>]` suffix, and when the component is loaded, the URL will have an additional param: `eyes-variation=<variation name>`.
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 RTL (right to left).
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
 
@@ -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.__STORYBOOK_STORY_STORE__) {
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};
@@ -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.__STORYBOOK_STORY_STORE__) {
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.__STORYBOOK_STORY_STORE__) {
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.__STORYBOOK_STORY_STORE__) {
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.__STORYBOOK_STORY_STORE__) {
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.25.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.2.7",
62
- "@applitools/eyes-puppeteer": "1.8.5",
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.5",
64
+ "@applitools/logger": "1.0.7",
66
65
  "@applitools/monitoring-commons": "1.0.19",
67
- "@applitools/test-server": "1.0.6",
68
- "@applitools/visual-grid-client": "15.8.43",
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.7",
82
+ "@applitools/sdk-shared": "0.9.11",
83
83
  "@applitools/snaptdout": "^1.0.1",
84
84
  "@applitools/utils": "1.2.4",
85
- "@storybook/addon-options": "^5.2.8",
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 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);
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
- const storiesByVariation = {};
24
+ return Object.values(variationStories).reduce((allStories, variationStories) => {
25
+ return allStories.concat(variationStories);
26
+ }, defaultStories);
27
+ }
10
28
 
11
- for (const story of storiesToAddVariations) {
12
- const variations = getStoryVariations(story);
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
- for (const variation of variations) {
18
- const variationArr = storiesByVariation[variation] || (storiesByVariation[variation] = []);
19
- variationArr.push({
20
- ...story,
21
- parameters: addFlagToParameters(story.parameters, variation),
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
- 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;
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
- if (globalVariationFunc) {
36
- return globalVariationFunc(story);
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
- if (globalVariationArray) return globalVariationArray;
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 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}};
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.__STORYBOOK_STORY_STORE__) {
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
  }
@@ -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/eyes-puppeteer/dist/spec-driver');
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: config.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.
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({stories: filteredStories, config});
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;
@@ -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 getStoryTitle = require('./getStoryTitle');
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 = getStoryTitle(story);
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 actualVariationParam = await getEyesVariationParam(page);
19
- const expectedVariationUrlParam = eyesParameters
20
- ? eyesParameters.variationUrlParam
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 snapshots = await takeDomSnapshots({
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 snapshots;
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
- async function getEyesVariationParam() {
77
+ function urlQueryParamsEquals(url, expectedQueryParams) {
82
78
  try {
83
- return new URL(await page.url()).searchParams.get('eyes-variation');
84
- } catch (ex) {
85
- logger.log('failed to get url from page (in need of eyes-variation param)');
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)
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  function getStoryTitle({name, kind, parameters}) {
4
- const variationUrlParam = parameters && parameters.eyes && parameters.eyes.variationUrlParam;
5
- const urlSuffix = variationUrlParam ? ` [${variationUrlParam}]` : '';
4
+ const queryParams = (parameters && parameters.eyes && parameters.eyes.queryParams) || {};
5
+ const eyesVariation = queryParams['eyes-variation'];
6
6
 
7
- return `${kind}: ${name}${urlSuffix}`;
7
+ return `${kind}: ${name}${eyesVariation ? ` [${eyesVariation}]` : ''}`;
8
8
  }
9
9
 
10
10
  module.exports = getStoryTitle;
@@ -2,12 +2,15 @@
2
2
  const getIframeUrl = require('./getIframeUrl');
3
3
 
4
4
  function getStoryUrl({name, kind, parameters}, baseUrl) {
5
- const variationUrlParam = parameters && parameters.eyes && parameters.eyes.variationUrlParam;
6
- const variation = variationUrlParam ? `&eyes-variation=${variationUrlParam}` : '';
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)}${variation}`;
13
+ )}&selectedStory=${encodeURIComponent(name)}${queryString}`;
11
14
  }
12
15
 
13
16
  module.exports = getStoryUrl;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  const getStoryUrl = require('./getStoryUrl');
3
- const getStoryTitle = require('./getStoryTitle');
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 = getStoryTitle(story);
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 = getStoryTitle(story);
145
+ const title = getStoryBaselineName(story);
143
146
  allTestResults.push({title, resultsOrErr});
144
147
  return {title, resultsOrErr};
145
148
  }
@@ -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 eyesOptions = Object.assign({}, config, (parameters && parameters.eyes) || {});
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('running story', title);
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: title,
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(title, async () => {
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', title, 'in', performance[title]);
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}(-.+)? started|Storybook started on =>/,
75
+ /Storybook \d{1,2}\.\d{1,2}\.\d{1,2}(.+)? started|Storybook started on =>/,
76
76
  );
77
77
 
78
78
  if (isReady) {