@applitools/eyes-storybook 3.25.3 → 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 CHANGED
@@ -2,9 +2,20 @@
2
2
 
3
3
  ## Unreleased
4
4
 
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
+
5
16
  ## 3.25.3 - 2021/11/1
6
17
 
7
- - add a retry machanisem for cases we get 0 stories
18
+ - add a retry mechanism for cases we get 0 stories
8
19
 
9
20
  ## 3.25.2 - 2021/10/30
10
21
 
package/README.md CHANGED
@@ -28,6 +28,7 @@ Applitools Eyes SDK for [Storybook](http://storybook.js.org).
28
28
  - [global](#global)
29
29
  - [component](#component)
30
30
  - [`variations`](#variations)
31
+ - [`queryParams`](#queryparams)
31
32
  - [`waitBeforeCapture`](#waitbeforecapture)
32
33
  - [`properties`](#properties)
33
34
  - [`ignoreRegions`](#ignoreregions)
@@ -180,6 +181,7 @@ In addition to command-line arguments, it's possible to define the following con
180
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. |
181
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). |
182
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).|
183
185
  | `notifyOnCompletion` | false | If `true` batch completion notifications are sent. |
184
186
  | `dontCloseBatches` | false | If true, batches are not closed for notifyOnCompletion.|
185
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. |
@@ -447,6 +449,13 @@ storiesOf('Components that support RTL', module)
447
449
  )
448
450
  ```
449
451
 
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
+
450
459
  ### `waitBeforeCapture`
451
460
 
452
461
  Selector or timeout, see [advanced configuration](#advanced-configuration) for more details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/eyes-storybook",
3
- "version": "3.25.3",
3
+ "version": "3.26.0",
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.3.5",
62
+ "@applitools/eyes-sdk-core": "12.24.5",
64
63
  "@applitools/functional-commons": "1.6.0",
65
- "@applitools/logger": "1.0.5",
64
+ "@applitools/logger": "1.0.6",
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.7",
68
+ "@applitools/visual-grid-client": "15.8.49",
69
69
  "boxen": "4.2.0",
70
70
  "chalk": "3.0.0",
71
71
  "detect-port": "1.3.0",
@@ -79,7 +79,7 @@
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.9",
83
83
  "@applitools/snaptdout": "^1.0.1",
84
84
  "@applitools/utils": "1.2.4",
85
85
  "@storybook/addon-options": "^5.2.8",
@@ -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;
@@ -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 addVariationStories = require('./addVariationStories');
13
+ const addParametrizedStories = require('./addParametrizedStories');
14
14
  const browserLog = require('./browserLog');
15
15
  const memoryLog = require('./memoryLog');
16
16
  const getIframeUrl = require('./getIframeUrl');
@@ -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,9 +116,12 @@ async function eyesStorybook({
116
116
  );
117
117
 
118
118
  const filteredStories = filterStories({stories, config});
119
- const storiesIncludingVariations = addVariationStories({stories: filteredStories, config});
119
+ const storiesIncludingParametrizedVariations = addParametrizedStories({
120
+ stories: filteredStories,
121
+ config,
122
+ });
120
123
 
121
- logger.log(`starting to run ${storiesIncludingVariations.length} stories`);
124
+ logger.log(`starting to run ${storiesIncludingParametrizedVariations.length} stories`);
122
125
 
123
126
  const getStoryData = makeGetStoryData({
124
127
  logger,
@@ -155,7 +158,7 @@ async function eyesStorybook({
155
158
  setRenderIE,
156
159
  setTransitioningIntoIE,
157
160
  configs,
158
- stories: storiesIncludingVariations,
161
+ stories: storiesIncludingParametrizedVariations,
159
162
  pagePool,
160
163
  logger,
161
164
  timeItAsync,
@@ -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;
@@ -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 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;
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
- (!actualVariationParam && !expectedVariationUrlParam) ||
24
- actualVariationParam === expectedVariationUrlParam
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);
@@ -49,8 +54,9 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
49
54
 
50
55
  logger.log(`running takeDomSnapshot(s) for story ${title}`);
51
56
 
52
- const snapshots = await takeDomSnapshots({
57
+ const result = await takeDomSnapshots({
53
58
  page,
59
+ browser,
54
60
  layoutBreakpoints: eyesParameters ? eyesParameters.layoutBreakpoints : undefined,
55
61
  waitBeforeCapture: wait
56
62
  ? async () => {
@@ -67,7 +73,7 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
67
73
  }
68
74
 
69
75
  logger.log(`done getting data from story`, title);
70
- return snapshots;
76
+ return result;
71
77
 
72
78
  async function renderStoryLegacy() {
73
79
  logger.log(`getting data from story ${storyUrl}`);
@@ -78,9 +84,16 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
78
84
  }
79
85
  }
80
86
 
81
- async function getEyesVariationParam() {
87
+ async function getQueryParam(queryParamNames = []) {
82
88
  try {
83
- return new URL(await page.url()).searchParams.get('eyes-variation');
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
+ }
84
97
  } catch (ex) {
85
98
  logger.log('failed to get url from page (in need of eyes-variation param)');
86
99
  }
@@ -1,10 +1,11 @@
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 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}${urlSuffix}`;
8
+ return `${kind}: ${name}${variation ? ` [${variation}]` : ''}`;
8
9
  }
9
10
 
10
11
  module.exports = getStoryTitle;
@@ -2,12 +2,12 @@
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 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)}${variation}`;
10
+ )}&selectedStory=${encodeURIComponent(name)}${queryParamString}`;
11
11
  }
12
12
 
13
13
  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,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('running story', title);
46
+ logger.log(`running story ${title} with baseline ${baselineName}`);
45
47
 
46
48
  const openParams = {
47
- testName: title,
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(title, async () => {
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', title, 'in', performance[title]);
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;