@applitools/eyes-storybook 3.29.4 → 3.30.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
@@ -3,6 +3,22 @@
3
3
  ## Unreleased
4
4
 
5
5
 
6
+ ## 3.30.1 - 2023/1/3
7
+
8
+ ### Features
9
+ - Additional internal event logs
10
+ ### Bug fixes
11
+ - fixed bug in mobile environment
12
+
13
+ ## 3.30.0 - 2022/12/19
14
+
15
+ ### Features
16
+ - Deprecated "Content" match level value in favor of "IgnoreColors"
17
+ - Add Support for storyStoreV7 flag
18
+ ### Bug fixes
19
+ - Handle fake shadowRoot with UFG
20
+ - Handed error during polling in long requests to eyes server
21
+
6
22
  ## 3.29.4 - 2022/9/12
7
23
 
8
24
  ### Features
package/README.md CHANGED
@@ -154,8 +154,8 @@ In addition to command-line arguments, it's possible to define the following con
154
154
  | `storybookStaticDir` | undefined | Path to Storybook's static files folder (also available as command-line argument). |
155
155
  | `showStorybookOutput` | undefined | Whether or not you want to see Storybook output (also available as command-line argument). |
156
156
  | `viewportSize` | { width: 1024, height: 600} | The size of the puppeteer browser's window. This is the browser window which renders the stories originally (and opens at the size provided in the `viewportSize` parameter), and then a DOM snapshot is uploaded to the server, which renders this snapshot on all the browsers and sizes provided in the `browser` parameter.|
157
- | `exitcode` | true | If tests failed close with non-zero exit code (also available as command-line argument). |
158
- | `browser` | { width: 800, height: 600, name: 'chrome' } | The size and browser of the generated screenshots. For more info and possible values, see the [browser section below](#configuring-the-browser).|
157
+ | `exitcode` | true | If tests failed or has visual differences close with non-zero exit code (also available as command-line argument).|
158
+ | `browser` | { width: 1024, height: 768, name: 'chrome' } | The size and browser of the generated screenshots. For more info and possible values, see the [browser section below](#configuring-the-browser).|
159
159
  | `showLogs` | false | Whether or not you want to see logs of the Eyes-Storybook plugin. |
160
160
  | `batch` | undefined | An object which describes different aspects of the batch. The following lines in this table depict the various ways to configure the batch. |
161
161
  | `batch.id` | random | Provides ability to group tests into batches. Read more about batches [here](https://applitools.com/docs/topics/working-with-test-batches/how-to-group-tests-into-batches.html). |
@@ -98,12 +98,20 @@ function __getClientAPI(...args) {
98
98
 
99
99
  case API_VERSIONS.v6_4: {
100
100
  api = {
101
- getStories: () => {
101
+ getStories: async () => {
102
+ if (clientAPI.storyStore.cacheAllCSFFiles) {
103
+ await clientAPI.storyStore.cacheAllCSFFiles();
104
+ }
102
105
  return clientAPI.raw();
103
106
  },
104
- selectStory: async i => {
107
+ selectStory: async (i, id) => {
108
+ let storyId = !clientAPI.storyStore.cacheAllCSFFiles ? clientAPI.raw()[i].id : id;
109
+ if (!storyId) {
110
+ await clientAPI.storyStore.cacheAllCSFFiles();
111
+ storyId = clientAPI.raw()[i].id;
112
+ }
105
113
  frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
106
- storyId: clientAPI.raw()[i].id,
114
+ storyId,
107
115
  });
108
116
  await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
109
117
  },
@@ -98,12 +98,20 @@ function __getStories(...args) {
98
98
 
99
99
  case API_VERSIONS.v6_4: {
100
100
  api = {
101
- getStories: () => {
101
+ getStories: async () => {
102
+ if (clientAPI.storyStore.cacheAllCSFFiles) {
103
+ await clientAPI.storyStore.cacheAllCSFFiles();
104
+ }
102
105
  return clientAPI.raw();
103
106
  },
104
- selectStory: async i => {
107
+ selectStory: async (i, id) => {
108
+ let storyId = !clientAPI.storyStore.cacheAllCSFFiles ? clientAPI.raw()[i].id : id;
109
+ if (!storyId) {
110
+ await clientAPI.storyStore.cacheAllCSFFiles();
111
+ storyId = clientAPI.raw()[i].id;
112
+ }
105
113
  frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
106
- storyId: clientAPI.raw()[i].id,
114
+ storyId,
107
115
  });
108
116
  await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
109
117
  },
@@ -246,9 +254,10 @@ function __getStories(...args) {
246
254
  }
247
255
  }
248
256
 
249
- function getStoriesThroughClientAPI(clientApi) {
250
- return clientApi.getStories().map((story, index) => {
251
- const {name, kind, parameters} = story;
257
+ async function getStoriesThroughClientAPI(clientApi) {
258
+ const stories = await clientApi.getStories();
259
+ return stories.map((story, index) => {
260
+ const {name, kind, parameters, id} = story;
252
261
  const hasEyesParameters =
253
262
  parameters && parameters.eyes && typeof parameters.eyes === 'object';
254
263
  let parametersIfSerialized, error;
@@ -278,6 +287,7 @@ function __getStories(...args) {
278
287
  index,
279
288
  name,
280
289
  kind,
290
+ id,
281
291
  parameters: parametersIfSerialized,
282
292
  error,
283
293
  };
@@ -98,12 +98,20 @@ function __renderStoryWithClientAPI(...args) {
98
98
 
99
99
  case API_VERSIONS.v6_4: {
100
100
  api = {
101
- getStories: () => {
101
+ getStories: async () => {
102
+ if (clientAPI.storyStore.cacheAllCSFFiles) {
103
+ await clientAPI.storyStore.cacheAllCSFFiles();
104
+ }
102
105
  return clientAPI.raw();
103
106
  },
104
- selectStory: async i => {
107
+ selectStory: async (i, id) => {
108
+ let storyId = !clientAPI.storyStore.cacheAllCSFFiles ? clientAPI.raw()[i].id : id;
109
+ if (!storyId) {
110
+ await clientAPI.storyStore.cacheAllCSFFiles();
111
+ storyId = clientAPI.raw()[i].id;
112
+ }
105
113
  frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
106
- storyId: clientAPI.raw()[i].id,
114
+ storyId,
107
115
  });
108
116
  await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
109
117
  },
@@ -142,12 +150,12 @@ function __renderStoryWithClientAPI(...args) {
142
150
 
143
151
  var getClientAPI_1 = getClientAPI;
144
152
 
145
- function renderStoryWithClientAPI(index) {
153
+ function renderStoryWithClientAPI(index, id) {
146
154
  return new Promise(resolve => {
147
155
  let api;
148
156
  try {
149
157
  api = getClientAPI_1();
150
- api.selectStory(index);
158
+ api.selectStory(index, id);
151
159
  api.onStoryRendered(resolve);
152
160
  } catch (ex) {
153
161
  resolve({message: ex.message, version: api ? api.version : undefined});
@@ -98,12 +98,20 @@ function __runRunAfterScript(...args) {
98
98
 
99
99
  case API_VERSIONS.v6_4: {
100
100
  api = {
101
- getStories: () => {
101
+ getStories: async () => {
102
+ if (clientAPI.storyStore.cacheAllCSFFiles) {
103
+ await clientAPI.storyStore.cacheAllCSFFiles();
104
+ }
102
105
  return clientAPI.raw();
103
106
  },
104
- selectStory: async i => {
107
+ selectStory: async (i, id) => {
108
+ let storyId = !clientAPI.storyStore.cacheAllCSFFiles ? clientAPI.raw()[i].id : id;
109
+ if (!storyId) {
110
+ await clientAPI.storyStore.cacheAllCSFFiles();
111
+ storyId = clientAPI.raw()[i].id;
112
+ }
105
113
  frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
106
- storyId: clientAPI.raw()[i].id,
114
+ storyId,
107
115
  });
108
116
  await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
109
117
  },
@@ -142,15 +150,15 @@ function __runRunAfterScript(...args) {
142
150
 
143
151
  var getClientAPI_1 = getClientAPI;
144
152
 
145
- function getStoryByIndex(index) {
153
+ async function getStoryByIndex(index) {
146
154
  let api;
147
155
  try {
148
156
  api = getClientAPI_1();
149
- const story = api.getStories()[index];
150
- if (!story) {
157
+ const stories = await api.getStories();
158
+ if (!stories[index]) {
151
159
  console.log('error cannot get story', index);
152
160
  }
153
- return story;
161
+ return stories[index];
154
162
  } catch (ex) {
155
163
  throw new Error(JSON.stringify({message: ex.message, version: api ? api.version : undefined}));
156
164
  }
@@ -158,9 +166,9 @@ function __runRunAfterScript(...args) {
158
166
 
159
167
  var getStoryByIndex_1 = getStoryByIndex;
160
168
 
161
- function runRunAfterScript(index) {
169
+ async function runRunAfterScript(index) {
162
170
  try {
163
- const story = getStoryByIndex_1(index);
171
+ const story = await getStoryByIndex_1(index);
164
172
  if (!story) return;
165
173
  return story.parameters.eyes.runAfter({rootEl: document.getElementById('root'), story});
166
174
  } catch (ex) {
@@ -98,12 +98,20 @@ function __runRunBeforeScript(...args) {
98
98
 
99
99
  case API_VERSIONS.v6_4: {
100
100
  api = {
101
- getStories: () => {
101
+ getStories: async () => {
102
+ if (clientAPI.storyStore.cacheAllCSFFiles) {
103
+ await clientAPI.storyStore.cacheAllCSFFiles();
104
+ }
102
105
  return clientAPI.raw();
103
106
  },
104
- selectStory: async i => {
107
+ selectStory: async (i, id) => {
108
+ let storyId = !clientAPI.storyStore.cacheAllCSFFiles ? clientAPI.raw()[i].id : id;
109
+ if (!storyId) {
110
+ await clientAPI.storyStore.cacheAllCSFFiles();
111
+ storyId = clientAPI.raw()[i].id;
112
+ }
105
113
  frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
106
- storyId: clientAPI.raw()[i].id,
114
+ storyId,
107
115
  });
108
116
  await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
109
117
  },
@@ -142,15 +150,15 @@ function __runRunBeforeScript(...args) {
142
150
 
143
151
  var getClientAPI_1 = getClientAPI;
144
152
 
145
- function getStoryByIndex(index) {
153
+ async function getStoryByIndex(index) {
146
154
  let api;
147
155
  try {
148
156
  api = getClientAPI_1();
149
- const story = api.getStories()[index];
150
- if (!story) {
157
+ const stories = await api.getStories();
158
+ if (!stories[index]) {
151
159
  console.log('error cannot get story', index);
152
160
  }
153
- return story;
161
+ return stories[index];
154
162
  } catch (ex) {
155
163
  throw new Error(JSON.stringify({message: ex.message, version: api ? api.version : undefined}));
156
164
  }
@@ -158,9 +166,9 @@ function __runRunBeforeScript(...args) {
158
166
 
159
167
  var getStoryByIndex_1 = getStoryByIndex;
160
168
 
161
- function runRunBeforeScript(index) {
169
+ async function runRunBeforeScript(index) {
162
170
  try {
163
- const story = getStoryByIndex_1(index);
171
+ const story = await getStoryByIndex_1(index);
164
172
  if (!story) return;
165
173
  return story.parameters.eyes.runBefore({rootEl: document.getElementById('root'), story: story});
166
174
  } catch (ex) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/eyes-storybook",
3
- "version": "3.29.4",
3
+ "version": "3.30.1",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "applitools",
@@ -48,11 +48,13 @@
48
48
  "storybook:csf-service": "cp -r test/fixtures/storybookCSF/.storybook/. test/fixtures/storybookCSF/.storybook-temp && rm test/fixtures/storybookCSF/.storybook-temp/config.js",
49
49
  "storybook:heavy": "start-storybook -c test/fixtures/heavyStorybook -p 9002 -s test/fixtures",
50
50
  "storybook:zeroStories": "start-storybook -c test/fixtures/zeroStoriesRetry -p 9003 -s test/fixtures",
51
+ "storybook:csf-v7": "start-storybook -c test/fixtures/storybookCSFV7/.storybook/ -p 9004 -s test/fixtures/",
51
52
  "eyes-storybook": "node bin/eyes-storybook.js -f test/fixtures/applitools.config.js",
52
53
  "eyes-storybook:jslayout": "node bin/eyes-storybook.js -f test/e2e/happy-config/layout-breakpoints-local.config.js",
53
54
  "eyes-storybook:heavy": "node bin/eyes-storybook.js -f test/fixtures/heavyStorybook/applitools.config.js",
54
55
  "eyes-storybook:configured": "node bin/eyes-storybook.js -f scripts/preconfigured.config.js",
55
56
  "eyes-storybook:zeroStories": "node bin/eyes-storybook.js -f test/fixtures/zeroStoriesRetry/applitools.config.js",
57
+ "eyes-storybook:csf-v7": "node bin/eyes-storybook.js -f test/fixtures/storybookCSFV7/applitools.config.js",
56
58
  "changelog": "git changelog -x -p -f v$npm_package_version > History.md && git add ./History.md && git commit -am 'changelog'",
57
59
  "changelog:init": "git config changelog.format \"* %s [[%h]($(echo $npm_package_repository_url|cut -d+ -f2|cut -d. -f1-2)/commit/%H)]\"",
58
60
  "changelog:install": "sudo apt-get install git-extras",
@@ -70,15 +72,15 @@
70
72
  }
71
73
  },
72
74
  "dependencies": {
73
- "@applitools/driver": "1.9.26",
74
- "@applitools/eyes-sdk-core": "13.8.26",
75
+ "@applitools/core": "1.3.7",
76
+ "@applitools/driver": "1.11.21",
75
77
  "@applitools/functional-commons": "1.6.0",
76
- "@applitools/logger": "1.1.16",
78
+ "@applitools/logger": "1.1.36",
77
79
  "@applitools/monitoring-commons": "1.0.19",
78
- "@applitools/spec-driver-puppeteer": "1.1.8",
79
- "@applitools/test-server": "1.1.4",
80
- "@applitools/utils": "1.3.10",
81
- "@applitools/visual-grid-client": "15.13.21",
80
+ "@applitools/spec-driver-puppeteer": "1.1.31",
81
+ "@applitools/test-server": "1.1.16",
82
+ "@applitools/ufg-client": "1.1.12",
83
+ "@applitools/utils": "1.3.22",
82
84
  "boxen": "4.2.0",
83
85
  "chalk": "3.0.0",
84
86
  "detect-port": "1.3.0",
@@ -87,18 +89,20 @@
87
89
  "ora": "3.4.0",
88
90
  "puppeteer": "10.2.0",
89
91
  "strip-ansi": "6.0.0",
92
+ "throat": "6.0.1",
90
93
  "yargs": "15.4.1"
91
94
  },
92
95
  "devDependencies": {
93
96
  "@applitools/bongo": "^2.2.0",
94
- "@applitools/scripts": "^1.1.0",
95
- "@applitools/sdk-shared": "0.9.13",
97
+ "@applitools/scripts": "^1.2.0",
98
+ "@applitools/sdk-shared": "0.9.15",
96
99
  "@applitools/snaptdout": "^1.0.1",
97
100
  "@storybook/addon-interactions": "^6.4.18",
98
101
  "@storybook/react": "^6.4.18",
99
102
  "@storybook/testing-library": "^0.0.9",
100
103
  "@testing-library/dom": "^5.6.1",
101
104
  "babel-core": "^6.26.3",
105
+ "babel-eslint": "^10.1.0",
102
106
  "babel-loader": "^8.0.6",
103
107
  "babel-preset-env": "^1.7.0",
104
108
  "babel-preset-react": "^6.24.1",
@@ -95,12 +95,20 @@ function getClientAPI() {
95
95
 
96
96
  case API_VERSIONS.v6_4: {
97
97
  api = {
98
- getStories: () => {
98
+ getStories: async () => {
99
+ if (clientAPI.storyStore.cacheAllCSFFiles) {
100
+ await clientAPI.storyStore.cacheAllCSFFiles();
101
+ }
99
102
  return clientAPI.raw();
100
103
  },
101
- selectStory: async i => {
104
+ selectStory: async (i, id) => {
105
+ let storyId = !clientAPI.storyStore.cacheAllCSFFiles ? clientAPI.raw()[i].id : id;
106
+ if (!storyId) {
107
+ await clientAPI.storyStore.cacheAllCSFFiles();
108
+ storyId = clientAPI.raw()[i].id;
109
+ }
102
110
  frameWindow.__STORYBOOK_PREVIEW__.urlStore.setSelection({
103
- storyId: clientAPI.raw()[i].id,
111
+ storyId,
104
112
  });
105
113
  await frameWindow.__STORYBOOK_PREVIEW__.renderSelection();
106
114
  },
@@ -104,9 +104,10 @@ async function getStories({timeout = DEFAULT_TIMEOUT} = {timeout: DEFAULT_TIMEOU
104
104
  }
105
105
  }
106
106
 
107
- function getStoriesThroughClientAPI(clientApi) {
108
- return clientApi.getStories().map((story, index) => {
109
- const {name, kind, parameters} = story;
107
+ async function getStoriesThroughClientAPI(clientApi) {
108
+ const stories = await clientApi.getStories();
109
+ return stories.map((story, index) => {
110
+ const {name, kind, parameters, id} = story;
110
111
  const hasEyesParameters =
111
112
  parameters && parameters.eyes && typeof parameters.eyes === 'object';
112
113
  let parametersIfSerialized, error;
@@ -136,6 +137,7 @@ async function getStories({timeout = DEFAULT_TIMEOUT} = {timeout: DEFAULT_TIMEOU
136
137
  index,
137
138
  name,
138
139
  kind,
140
+ id,
139
141
  parameters: parametersIfSerialized,
140
142
  error,
141
143
  };
@@ -1,14 +1,14 @@
1
1
  const getClientAPI = require('./getClientAPI');
2
2
 
3
- function getStoryByIndex(index) {
3
+ async function getStoryByIndex(index) {
4
4
  let api;
5
5
  try {
6
6
  api = getClientAPI();
7
- const story = api.getStories()[index];
8
- if (!story) {
7
+ const stories = await api.getStories();
8
+ if (!stories[index]) {
9
9
  console.log('error cannot get story', index);
10
10
  }
11
- return story;
11
+ return stories[index];
12
12
  } catch (ex) {
13
13
  throw new Error(JSON.stringify({message: ex.message, version: api ? api.version : undefined}));
14
14
  }
@@ -1,11 +1,11 @@
1
1
  const getClientAPI = require('./getClientAPI');
2
2
 
3
- function renderStoryWithClientAPI(index) {
3
+ function renderStoryWithClientAPI(index, id) {
4
4
  return new Promise(resolve => {
5
5
  let api;
6
6
  try {
7
7
  api = getClientAPI();
8
- api.selectStory(index);
8
+ api.selectStory(index, id);
9
9
  api.onStoryRendered(resolve);
10
10
  } catch (ex) {
11
11
  resolve({message: ex.message, version: api ? api.version : undefined});
@@ -1,8 +1,8 @@
1
1
  const getStoryByIndex = require('./getStoryByIndex');
2
2
 
3
- function runRunAfterScript(index) {
3
+ async function runRunAfterScript(index) {
4
4
  try {
5
- const story = getStoryByIndex(index);
5
+ const story = await getStoryByIndex(index);
6
6
  if (!story) return;
7
7
  return story.parameters.eyes.runAfter({rootEl: document.getElementById('root'), story});
8
8
  } catch (ex) {
@@ -1,8 +1,8 @@
1
1
  const getStoryByIndex = require('./getStoryByIndex');
2
2
 
3
- function runRunBeforeScript(index) {
3
+ async function runRunBeforeScript(index) {
4
4
  try {
5
- const story = getStoryByIndex(index);
5
+ const story = await getStoryByIndex(index);
6
6
  if (!story) return;
7
7
  return story.parameters.eyes.runBefore({rootEl: document.getElementById('root'), story: story});
8
8
  } catch (ex) {
package/src/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
  const yargs = require('yargs');
3
3
  const {makeLogger} = require('@applitools/logger');
4
- const {configParams: externalConfigParams} = require('@applitools/visual-grid-client');
4
+ const {configParams: externalConfigParams} = require('./configParams');
5
5
  const VERSION = require('../package.json').version;
6
6
  const eyesStorybook = require('./eyesStorybook');
7
7
  const processResults = require('./processResults');
@@ -30,7 +30,6 @@ const {performance, timeItAsync} = makeTiming();
30
30
  .options(yargsOptions).argv;
31
31
 
32
32
  console.log(`Using @applitools/eyes-storybook version ${VERSION}.\n`);
33
-
34
33
  const config = generateConfig({argv, defaultConfig, externalConfigParams});
35
34
  const logger = makeLogger({level: config.showLogs ? 'info' : 'silent', label: 'eyes'});
36
35
  await validateAndPopulateConfig({config, logger, packagePath: process.cwd()});
@@ -62,7 +61,7 @@ const {performance, timeItAsync} = makeTiming();
62
61
  process.exit(config.exitcode ? exitCode : 0);
63
62
  }
64
63
  } catch (ex) {
65
- console.log(ex.message);
64
+ console.log(ex);
66
65
  process.exit(1);
67
66
  }
68
67
  })();
@@ -1,12 +1,13 @@
1
1
  'use strict';
2
- const {TypeUtils} = require('@applitools/eyes-sdk-core');
3
- const prettyValue = val => (!TypeUtils.isObject(val) ? val : JSON.stringify(val));
2
+ const utils = require('@applitools/utils');
3
+ const prettyValue = (key, val) =>
4
+ !utils.types.isObject(val, {name: key}) ? val : JSON.stringify(val);
4
5
 
5
6
  function configDigest(config) {
6
7
  const maxKeyLen = Object.keys(config).reduce((len, key) => Math.max(len, key.length), 0);
7
8
  return (
8
9
  Object.entries(config)
9
- .map(([key, value]) => `${key.padEnd(maxKeyLen + 1)}: ${prettyValue(value)}`)
10
+ .map(([key, value]) => `${key.padEnd(maxKeyLen + 1)}: ${prettyValue(key, value)}`)
10
11
  .join('\n') + '\n'
11
12
  );
12
13
  }
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ const configParams = [
4
+ 'appName',
5
+ 'testName',
6
+ 'displayName',
7
+ 'browser',
8
+ 'url',
9
+ 'apiKey',
10
+ 'showLogs',
11
+ 'batch',
12
+ 'batchId',
13
+ 'batchName',
14
+ 'batchSequenceName',
15
+ 'batchSequence',
16
+ 'properties',
17
+ 'baselineBranchName',
18
+ 'baselineBranch',
19
+ 'baselineEnvName',
20
+ 'baselineName',
21
+ 'envName',
22
+ 'ignoreCaret',
23
+ 'isDisabled',
24
+ 'matchLevel',
25
+ 'parentBranchName',
26
+ 'parentBranch',
27
+ 'branchName',
28
+ 'branch',
29
+ 'proxy',
30
+ 'autProxy',
31
+ 'saveDiffs',
32
+ 'saveFailedTests',
33
+ 'saveNewTests',
34
+ 'compareWithParentBranch',
35
+ 'ignoreBaseline',
36
+ 'serverUrl',
37
+ 'concurrency',
38
+ 'testConcurrency',
39
+ 'useDom',
40
+ 'enablePatterns',
41
+ 'ignoreDisplacements',
42
+ 'accessibilitySettings',
43
+ 'notifyOnCompletion',
44
+ 'batchNotify',
45
+ 'dontCloseBatches',
46
+ ];
47
+
48
+ module.exports = {configParams};
@@ -37,9 +37,18 @@ function refineErrorMessage({prefix, error}) {
37
37
  return `${prefix} ${error.message.replace('Evaluation failed: ', '')}`;
38
38
  }
39
39
 
40
+ function deprecationWarning({deprecatedThing, newThing, isDead}) {
41
+ const msg = isDead
42
+ ? `Notice: ${deprecatedThing} is no longer supported.`
43
+ : `Notice: ${deprecatedThing} has been renamed. Please use ${newThing} instead.\n`;
44
+
45
+ chalk.yellow(msg);
46
+ }
47
+
40
48
  module.exports = {
41
49
  missingApiKeyFailMsg,
42
50
  missingAppNameAndPackageJsonFailMsg,
43
51
  missingAppNameInPackageJsonFailMsg,
44
52
  refineErrorMessage,
53
+ deprecationWarning,
45
54
  };
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
  const puppeteer = require('puppeteer');
3
3
  const getStories = require('../dist/getStories');
4
- const {makeVisualGridClient} = require('@applitools/visual-grid-client');
5
4
  const {presult, delay} = require('@applitools/functional-commons');
6
5
  const chalk = require('chalk');
7
6
  const makeInitPage = require('./initPage');
@@ -16,12 +15,14 @@ const memoryLog = require('./memoryLog');
16
15
  const getIframeUrl = require('./getIframeUrl');
17
16
  const createPagePool = require('./pagePool');
18
17
  const getClientAPI = require('../dist/getClientAPI');
19
- const {takeDomSnapshots} = require('@applitools/eyes-sdk-core');
18
+ const {takeDomSnapshots} = require('@applitools/core');
20
19
  const {Driver} = require('@applitools/driver');
21
20
  const spec = require('@applitools/spec-driver-puppeteer');
22
21
  const {refineErrorMessage} = require('./errMessages');
23
22
  const {splitConfigsByBrowser} = require('./shouldRenderIE');
24
23
  const executeRenders = require('./executeRenders');
24
+ const {makeCore} = require('@applitools/core');
25
+ const {makeUFGClient} = require('@applitools/ufg-client');
25
26
 
26
27
  const CONCURRENT_PAGES = 3;
27
28
  const MAX_RETRIES = 10;
@@ -39,7 +40,15 @@ async function eyesStorybook({
39
40
  let transitioning = false;
40
41
  takeMemLoop();
41
42
  logger.log('eyesStorybook started');
42
- const {storybookUrl, waitBeforeCapture, readStoriesTimeout, reloadPagePerStory} = config;
43
+
44
+ const {
45
+ storybookUrl,
46
+ waitBeforeCapture,
47
+ readStoriesTimeout,
48
+ reloadPagePerStory,
49
+ proxy,
50
+ testConcurrency,
51
+ } = config;
43
52
 
44
53
  let iframeUrl;
45
54
  try {
@@ -48,24 +57,48 @@ async function eyesStorybook({
48
57
  logger.log(ex);
49
58
  throw new Error(`Storybook URL is not valid: ${storybookUrl}`);
50
59
  }
51
-
60
+ const agentId = `eyes-storybook/${require('../package.json').version}`;
52
61
  const browser = await puppeteer.launch(config.puppeteerOptions);
53
62
  logger.log('browser launched');
54
63
  const page = await browser.newPage();
55
- const userAgent = await page.evaluate('navigator.userAgent');
64
+ const core = await makeCore({
65
+ spec,
66
+ concurrency: testConcurrency,
67
+ logger,
68
+ agentId,
69
+ });
70
+ const manager = await core.makeManager({
71
+ spec,
72
+ concurrency: testConcurrency,
73
+ agentId,
74
+ logger,
75
+ core,
76
+ type: 'ufg',
77
+ });
56
78
 
57
- const {
58
- testWindow,
59
- closeBatch,
60
- globalState,
61
- getIosDevicesSizes,
62
- getEmulatedDevicesSizes,
63
- getResourceUrlsInCache,
64
- getSetRenderInfo,
65
- } = makeVisualGridClient({
66
- userAgent,
67
- ...config,
68
- logger: logger.extend({label: 'vgc'}),
79
+ const settings = {
80
+ proxy: config.proxy,
81
+ serverUrl: config.serverUrl,
82
+ apiKey: config.apiKey,
83
+ agentId,
84
+ };
85
+ const [error, account] = await presult(core.getAccountInfo({settings, logger}));
86
+
87
+ if (error && error.message && error.message.includes('Unauthorized(401)')) {
88
+ const failMsg = 'Incorrect API Key';
89
+ logger.log(failMsg);
90
+ await browser.close();
91
+ clearTimeout(memoryTimeout);
92
+ throw new Error(failMsg);
93
+ }
94
+ const client = await makeUFGClient({
95
+ config: {
96
+ ...account.ufg,
97
+ ...account,
98
+ proxy,
99
+ concurrency: testConcurrency,
100
+ },
101
+ logger,
69
102
  });
70
103
 
71
104
  const initPage = makeInitPage({
@@ -78,21 +111,24 @@ async function eyesStorybook({
78
111
  });
79
112
  const pagePool = createPagePool({initPage, logger});
80
113
 
81
- const doTakeDomSnapshots = async ({page, browser, layoutBreakpoints, waitBeforeCapture}) => {
114
+ const doTakeDomSnapshots = async ({page, renderers, layoutBreakpoints, waitBeforeCapture}) => {
82
115
  const driver = await new Driver({spec, driver: page, logger}).init();
83
- const skipResources = getResourceUrlsInCache();
116
+ const skipResources = client.getCachedResourceUrls();
84
117
  const result = await takeDomSnapshots({
85
118
  logger,
86
119
  driver,
87
- breakpoints: layoutBreakpoints !== undefined ? layoutBreakpoints : config.layoutBreakpoints,
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
- skipResources,
90
- showLogs: !!config.showLogs,
91
- disableBrowserFetching: !!config.disableBrowserFetching,
92
- getViewportSize: () => config.viewportSize,
93
- getIosDevicesSizes,
94
- getEmulatedDevicesSizes,
95
- waitBeforeCapture,
120
+ settings: {
121
+ layoutBreakpoints:
122
+ layoutBreakpoints !== undefined ? layoutBreakpoints : config.layoutBreakpoints,
123
+ renderers,
124
+ waitBeforeCapture,
125
+ skipResources,
126
+ disableBrowserFetching: !!config.disableBrowserFetchin,
127
+ },
128
+ provides: {
129
+ getChromeEmulationDevices: client.getChromeEmulationDevices,
130
+ getIOSDevices: client.getIOSDevices,
131
+ },
96
132
  });
97
133
  return result;
98
134
  };
@@ -105,7 +141,6 @@ async function eyesStorybook({
105
141
  },
106
142
  });
107
143
  try {
108
- await getSetRenderInfo();
109
144
  const [stories] = await Promise.all(
110
145
  [getStoriesWithSpinner()].concat(
111
146
  new Array(CONCURRENT_PAGES).fill().map(async () => {
@@ -128,13 +163,22 @@ async function eyesStorybook({
128
163
  takeDomSnapshots: doTakeDomSnapshots,
129
164
  waitBeforeCapture,
130
165
  });
131
-
166
+ const closeSettings = {
167
+ ...settings,
168
+ updateBaselineIfNew: config.saveNewTests,
169
+ updateBaselineIfDifferent: config.saveFailedTests,
170
+ };
132
171
  const renderStory = makeRenderStory({
133
172
  logger: logger.extend({label: 'renderStory'}),
134
- testWindow,
173
+ openEyes: manager.openEyes,
135
174
  performance,
136
175
  timeItAsync,
137
176
  reloadPagePerStory,
177
+ storyDataGap: config.storyDataGap,
178
+ concurrency: testConcurrency,
179
+ appName: config.appName,
180
+ closeSettings,
181
+ serverSettings: settings,
138
182
  });
139
183
 
140
184
  const renderStories = makeRenderStories({
@@ -144,13 +188,10 @@ async function eyesStorybook({
144
188
  storybookUrl,
145
189
  logger,
146
190
  stream: outputStream,
147
- waitForQueuedRenders: globalState.waitForQueuedRenders,
148
- storyDataGap: config.storyDataGap,
149
191
  pagePool,
150
192
  });
151
193
 
152
194
  logger.log('finished creating functions');
153
-
154
195
  const configs = config.fakeIE ? splitConfigsByBrowser(config) : [config];
155
196
  const [error, results] = await presult(
156
197
  executeRenders({
@@ -164,11 +205,12 @@ async function eyesStorybook({
164
205
  timeItAsync,
165
206
  }),
166
207
  );
208
+ const [errorCloseManager, testResultsSummary] = await presult(
209
+ manager.closeManager({throwErr: false}),
210
+ );
167
211
 
168
- const [closeBatchErr] = await presult(closeBatch());
169
-
170
- if (closeBatchErr) {
171
- logger.log('failed to close batch', closeBatchErr);
212
+ if (errorCloseManager) {
213
+ logger.log('failed to close manager', errorCloseManager);
172
214
  }
173
215
 
174
216
  if (error) {
@@ -176,7 +218,7 @@ async function eyesStorybook({
176
218
  logger.log(error);
177
219
  throw new Error(msg);
178
220
  } else {
179
- return results;
221
+ return {summary: testResultsSummary, results};
180
222
  }
181
223
  } finally {
182
224
  logger.log('total time: ', performance['renderStories']);
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
  const pick = require('lodash.pick');
3
3
  const utils = require('@applitools/utils');
4
- const {GeneralUtils} = require('@applitools/eyes-sdk-core');
5
4
  const {resolve} = require('path');
6
- const {deprecationWarning} = GeneralUtils;
5
+ const {deprecationWarning} = require('./errMessages');
7
6
  const uniq = require('./uniq');
7
+ const MAX_DATA_GAP = 60;
8
8
 
9
9
  function generateConfig({argv = {}, defaultConfig = {}, externalConfigParams = []}) {
10
10
  const defaultConfigParams = Object.keys(defaultConfig);
@@ -44,14 +44,51 @@ function generateConfig({argv = {}, defaultConfig = {}, externalConfigParams = [
44
44
  result.showLogs = true;
45
45
  }
46
46
 
47
- if (!result.testConcurrency && !result.concurrency) {
48
- result.testConcurrency = 5; // TODO require from core
47
+ result.testConcurrency = utils.types.isInteger(result.testConcurrency)
48
+ ? result.testConcurrency
49
+ : utils.types.isInteger(result.concurrency)
50
+ ? result.concurrency * 5
51
+ : 5;
52
+
53
+ result.serverUrl = result.serverUrl
54
+ ? result.serverUrl
55
+ : utils.general.getEnvValue('SERVER_URL')
56
+ ? utils.general.getEnvValue('SERVER_URL')
57
+ : 'https://eyesapi.applitools.com';
58
+
59
+ result.viewportSize = result.viewportSize ? result.viewportSize : {width: 1024, height: 600};
60
+
61
+ result.saveNewTests = result.saveNewTests === undefined ? true : result.saveNewTests;
62
+ result.keepBatchOpen = result.dontCloseBatches;
63
+ result.fully = result.fully === undefined ? true : false;
64
+
65
+ if (result.batchName) {
66
+ result.batch = {name: result.batchName, ...result.batch};
67
+ }
68
+
69
+ if (result.batchId) {
70
+ result.batch = {id: result.batchId, ...result.batch};
49
71
  }
50
72
 
51
73
  if (result.storyDataGap === undefined) {
52
- result.storyDataGap = result.testConcurrency;
74
+ result.storyDataGap = Math.max(
75
+ Math.min(result.testConcurrency * 2, MAX_DATA_GAP),
76
+ result.testConcurrency,
77
+ );
53
78
  }
79
+
80
+ if (!result.browser) {
81
+ result.renderers = [{name: 'chrome', width: 1024, height: 768}];
82
+ } else {
83
+ result.renderers = [];
84
+ if (!Array.isArray(result.browser)) {
85
+ result.browser = [result.browser];
86
+ }
87
+ result.renderers = result.browser.map(browser => {
88
+ return browser.deviceName ? {chromeEmulationInfo: browser} : browser;
89
+ });
90
+ }
91
+ delete result.browser;
54
92
  return result;
55
93
  }
56
-
57
94
  module.exports = generateConfig;
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
  const {presult, ptimeoutWithError} = require('@applitools/functional-commons');
3
- const {ArgumentGuard} = require('@applitools/eyes-sdk-core');
4
3
  const renderStoryWithClientAPI = require('../dist/renderStoryWithClientAPI');
5
4
  const runRunBeforeScript = require('../dist/runRunBeforeScript');
6
5
  const getStoryBaselineName = require('./getStoryBaselineName');
@@ -9,9 +8,10 @@ const runRunAfterScript = require('../dist/runRunAfterScript');
9
8
  const waitFor = require('./waitFor');
10
9
  const PAGE_EVALUATE_TIMEOUT = 120000;
11
10
  const DOM_SNAPSHOTS_TIMEOUT = 5 * 60 * 1000;
11
+ const utils = require('@applitools/utils');
12
12
 
13
13
  function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPagePerStory}) {
14
- return async function getStoryData({story, storyUrl, page, browser, waitBeforeStory}) {
14
+ return async function getStoryData({story, storyUrl, page, renderers, waitBeforeStory}) {
15
15
  const title = getStoryBaselineName(story);
16
16
  logger.log(`getting data from story`, title);
17
17
 
@@ -22,7 +22,7 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
22
22
  if (urlQueryParamsEquals(currentUrl, expectedQueryParams)) {
23
23
  try {
24
24
  const err = await ptimeoutWithError(
25
- page.evaluate(renderStoryWithClientAPI, story.index),
25
+ page.evaluate(renderStoryWithClientAPI, story.index, story.id),
26
26
  PAGE_EVALUATE_TIMEOUT,
27
27
  new Error('page evaluate timed out!'),
28
28
  );
@@ -45,11 +45,7 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
45
45
 
46
46
  const wait = waitBeforeStory || waitBeforeCapture;
47
47
  if (typeof wait === 'number') {
48
- ArgumentGuard.greaterThanOrEqualToZero(wait, 'waitBeforeCapture', true);
49
- }
50
- if (wait) {
51
- logger.log(`waiting before screenshot of ${title} ${wait}`);
52
- await waitFor(page, wait);
48
+ utils.guard.isGreaterThenOrEqual(wait, 0, {name: 'waitBeforeCapture'});
53
49
  }
54
50
 
55
51
  if (eyesParameters && eyesParameters.runBefore) {
@@ -59,10 +55,9 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
59
55
  }
60
56
 
61
57
  logger.log(`running takeDomSnapshot(s) for story ${title}`);
62
-
63
58
  const domSnapshotsPromise = takeDomSnapshots({
64
59
  page,
65
- browser,
60
+ renderers,
66
61
  layoutBreakpoints: eyesParameters ? eyesParameters.layoutBreakpoints : undefined,
67
62
  waitBeforeCapture: wait
68
63
  ? async () => {
@@ -1,33 +1,34 @@
1
1
  'use strict';
2
2
  const flatten = require('lodash.flatten');
3
3
  const chalk = require('chalk');
4
- const {TestResultsError, TestResultsFormatter} = require('@applitools/eyes-sdk-core');
5
4
  const utils = require('@applitools/utils');
6
5
  const uniq = require('./uniq');
7
6
  const concurrencyMsg = require('./concurrencyMsg');
7
+ const {formatters} = require('@applitools/core');
8
8
 
9
9
  function processResults({results = [], totalTime, testConcurrency, saveNewTests = true}) {
10
10
  let outputStr = '\n';
11
- const formatter = new TestResultsFormatter();
12
11
  const pluralize = utils.general.pluralize;
13
- let testResults = results.map(r => r.resultsOrErr);
14
- testResults = flatten(testResults).filter(r => r.constructor.name !== 'Error');
15
- const unresolved = testResults.filter(r => r.getIsDifferent());
16
- const passedOrNew = testResults.filter(r => !r.getIsDifferent());
17
- const newTests = testResults.filter(r => r.getIsNew());
12
+ let testResults = flatten(results.summary.results);
13
+ const unresolved = testResults.filter(r => r.result.isDifferent);
14
+ const passedOrNew = testResults.filter(r => r.result.status === 'Passed' || r.result.isNew);
15
+ const newTests = testResults.filter(r => r.result.isNew);
18
16
  const newTestsSize = newTests.length;
19
17
  const warnForUnsavedNewTests = !!(!saveNewTests && newTestsSize);
20
18
 
21
- let errors = results.map(({title, resultsOrErr}) =>
22
- Array.isArray(resultsOrErr)
23
- ? resultsOrErr.map(err => ({err, title}))
24
- : [{err: resultsOrErr, title}],
19
+ let errors = results.summary.results.map(result => [
20
+ {err: result.error, title: result.result.name},
21
+ ]);
22
+ errors = flatten(errors).filter(
23
+ ({err}) =>
24
+ err &&
25
+ !err.message.includes('detected differences') &&
26
+ !err.message.includes('Please approve the new baseline'),
25
27
  );
26
- errors = flatten(errors).filter(({err}) => err.constructor.name === 'Error');
27
28
 
28
29
  const hasResults = unresolved.length || passedOrNew.length;
29
30
  const seeDetailsStr =
30
- hasResults && `See details at ${(passedOrNew[0] || unresolved[0]).getAppUrls().getBatch()}`;
31
+ hasResults && `See details at ${(passedOrNew[0] || unresolved[0]).result.appUrls.batch}`;
31
32
 
32
33
  if (hasResults) {
33
34
  outputStr += `${seeDetailsStr}\n\n`;
@@ -82,7 +83,7 @@ function processResults({results = [], totalTime, testConcurrency, saveNewTests
82
83
  const countText =
83
84
  newTestsSize > 1
84
85
  ? `are ${newTestsSize} new tests`
85
- : `is a new test: '${newTests[0].getName()}'`;
86
+ : `is a new test: '${newTests[0].result.name}'`;
86
87
  outputStr += chalk.red(
87
88
  `\n'saveNewTests' was set to false and there ${countText}. Please approve ${pluralize(
88
89
  newTestsSize,
@@ -101,20 +102,9 @@ function processResults({results = [], totalTime, testConcurrency, saveNewTests
101
102
  // TODO require from core
102
103
  outputStr += `\n${concurrencyMsg}\n`;
103
104
  }
104
-
105
- passedOrNew.forEach(formatter.addTestResults.bind(formatter));
106
- unresolved.forEach(formatter.addTestResults.bind(formatter));
107
- errors.forEach(error => {
108
- formatter.addTestResults(
109
- new TestResultsError({
110
- name: error.title,
111
- error: error.err,
112
- }),
113
- );
114
- });
105
+ const formatter = formatters.toJsonOutput(results.summary);
115
106
  const exitCode =
116
107
  !warnForUnsavedNewTests && passedOrNew.length && !errors.length && !unresolved.length ? 0 : 1;
117
-
118
108
  return {
119
109
  outputStr,
120
110
  formatter,
@@ -124,16 +114,14 @@ function processResults({results = [], totalTime, testConcurrency, saveNewTests
124
114
 
125
115
  function testResultsOutput(results, warnForUnsavedNewTests) {
126
116
  let outputStr = '';
127
- const sortedTestResults = results.sort((a, b) => a.getName().localeCompare(b.getName()));
117
+ const sortedTestResults = results.sort((a, b) => a.result.name.localeCompare(b.result.name));
128
118
  sortedTestResults.forEach(result => {
129
- const storyTitle = `${result.getName()} [${result.getHostApp()}] [${result
130
- .getHostDisplaySize()
131
- .toString()}] - `;
119
+ const storyTitle = `${result.result.name} [${result.result.hostApp}] [${result.result.hostDisplaySize.width}x${result.result.hostDisplaySize.height}] - `;
132
120
 
133
- if (result.getIsNew()) {
121
+ if (result.result.isNew) {
134
122
  const newResColor = warnForUnsavedNewTests ? 'orange' : 'blue';
135
123
  outputStr += `${storyTitle}${chalk.keyword(newResColor)('New')}\n`;
136
- } else if (result.isPassed()) {
124
+ } else if (!result.result.isDifferent) {
137
125
  outputStr += `${storyTitle}${chalk.green('Passed')}\n`;
138
126
  } else {
139
127
  outputStr += `${storyTitle}${chalk.keyword('orange')(`Unresolved`)}\n`;
@@ -12,8 +12,6 @@ function makeRenderStories({
12
12
  storybookUrl,
13
13
  logger,
14
14
  stream,
15
- waitForQueuedRenders,
16
- storyDataGap,
17
15
  getClientAPI,
18
16
  maxPageTTL = 60000,
19
17
  }) {
@@ -39,7 +37,6 @@ function makeRenderStories({
39
37
 
40
38
  async function processStoryLoop() {
41
39
  if (currIndex === stories.length) return;
42
-
43
40
  const {page, pageId, markPageAsFree, removePage, getCreatedAt} = await pagePool.getFreePage();
44
41
  const livedTime = Date.now() - getCreatedAt();
45
42
  logger.log(`[prepareNewPage] got free page: ${pageId}, lived time: ${livedTime}`);
@@ -52,7 +49,7 @@ function makeRenderStories({
52
49
  return processStoryLoop();
53
50
  }
54
51
  logger.log(`[page ${pageId}] waiting for queued renders`);
55
- await waitForQueuedRenders(storyDataGap);
52
+ // await waitForQueuedRenders(storyDataGap);
56
53
  logger.log(`[page ${pageId}] done waiting for queued renders`);
57
54
  const storyPromise = processStory();
58
55
  allStoriesPromise = allStoriesPromise.then(() => storyPromise);
@@ -69,7 +66,7 @@ function makeRenderStories({
69
66
  getStoryData({
70
67
  story,
71
68
  storyUrl,
72
- browser: config.browser,
69
+ renderers: config.renderers,
73
70
  page,
74
71
  waitBeforeStory: waitBeforeCapture,
75
72
  }),
@@ -95,7 +92,7 @@ function makeRenderStories({
95
92
  getStoryData({
96
93
  story,
97
94
  storyUrl,
98
- browser: config.browser,
95
+ renderers: config.renderers,
99
96
  page: newPageObj.page,
100
97
  waitBeforeStory: waitBeforeCapture,
101
98
  }),
@@ -112,15 +109,12 @@ function makeRenderStories({
112
109
  logger.log(errMsg);
113
110
  throw new Error(errMsg);
114
111
  }
115
-
116
112
  const testResults = await renderStory({
117
- snapshot: storyData.snapshots,
118
- cookies: storyData.cookies,
113
+ snapshots: storyData,
119
114
  url: storyUrl,
120
115
  story,
121
116
  config,
122
117
  });
123
-
124
118
  return onDoneStory(testResults, story);
125
119
  } catch (ex) {
126
120
  return onDoneStory(ex, story);
@@ -130,10 +124,9 @@ function makeRenderStories({
130
124
 
131
125
  function didTestPass({resultsOrErr}) {
132
126
  return (
127
+ resultsOrErr.constructor &&
133
128
  resultsOrErr.constructor.name !== 'Error' &&
134
- resultsOrErr.every(
135
- r => r.constructor.name !== 'Error' && r.getStatus && r.getStatus() === 'Passed',
136
- )
129
+ resultsOrErr.every(r => !r.isDifferent && !r.isAborted && !r.isNew)
137
130
  );
138
131
  }
139
132
 
@@ -1,10 +1,21 @@
1
1
  'use strict';
2
2
  const getStoryTitle = require('./getStoryTitle');
3
3
  const getStoryBaselineName = require('./getStoryBaselineName');
4
- const {deprecationWarning} = require('@applitools/eyes-sdk-core').GeneralUtils;
4
+ const {deprecationWarning} = require('./errMessages');
5
+ const throat = require('throat');
5
6
 
6
- function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
7
- return function renderStory({config, story, snapshot, url}) {
7
+ function makeRenderStory({
8
+ logger,
9
+ openEyes,
10
+ performance,
11
+ timeItAsync,
12
+ storyDataGap,
13
+ appName,
14
+ closeSettings,
15
+ serverSettings,
16
+ }) {
17
+ const throttle = throat(storyDataGap);
18
+ return function renderStory({config, story, snapshots, url}) {
8
19
  const {name, kind, parameters, hasPlayFunction} = story;
9
20
  const baselineName = getStoryBaselineName({name, kind, parameters});
10
21
  const title = getStoryTitle({name, kind, parameters});
@@ -36,6 +47,19 @@ function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
36
47
  visualGridOptions,
37
48
  useDom,
38
49
  enablePatterns,
50
+ renderers,
51
+ keepBatchOpen,
52
+ batch,
53
+ branchName,
54
+ parentBranchName,
55
+ baselineBranchName,
56
+ compareWithParentBranch,
57
+ ignoreGitMergeBase,
58
+ baselineEnvName,
59
+ envName,
60
+ ignoreCaret,
61
+ matchLevel,
62
+ ignoreBaseline,
39
63
  } = eyesOptions;
40
64
 
41
65
  if (sizeMode) {
@@ -62,21 +86,30 @@ function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
62
86
  const openParams = {
63
87
  testName: baselineName,
64
88
  displayName: title,
65
- browser: config.browser,
66
89
  properties: storyProperties,
67
- accessibilitySettings: accessibilityValidation,
90
+ appName,
91
+ keepBatchOpen,
92
+ batch,
93
+ branchName,
94
+ parentBranchName,
95
+ baselineBranchName,
96
+ compareWithParentBranch,
97
+ ignoreGitBranching: ignoreGitMergeBase,
98
+ baselineEnvName,
99
+ environmentName: envName,
100
+ ignoreBaseline,
101
+ ...serverSettings,
68
102
  };
69
-
70
103
  const checkParams = {
71
104
  url,
72
- snapshot,
73
- ignore: ignoreRegionsBackCompat,
74
- floating: floatingRegions,
75
- layout: layoutRegions,
76
- strict: strictRegions,
77
- content: contentRegions,
78
- accessibility: accessibilityRegions,
79
- scriptHooks,
105
+ ignoreRegions: ignoreRegionsBackCompat,
106
+ floatingRegions: mapFloatingRegions(floatingRegions),
107
+ layoutRegions,
108
+ strictRegions,
109
+ contentRegions,
110
+ accessibilityRegions: mapAccessibilityRegions(accessibilityRegions),
111
+ renderers,
112
+ hooks: scriptHooks,
80
113
  sizeMode,
81
114
  target,
82
115
  fully,
@@ -84,14 +117,100 @@ function makeRenderStory({logger, testWindow, performance, timeItAsync}) {
84
117
  region,
85
118
  tag,
86
119
  sendDom,
87
- visualGridOptions,
120
+ ufgOptions: visualGridOptions,
88
121
  useDom,
89
122
  enablePatterns,
90
123
  ignoreDisplacements,
124
+ fully,
125
+ ignoreCaret,
126
+ matchLevel,
127
+ accessibilitySettings: accessibilityValidation
128
+ ? {
129
+ level: accessibilityValidation ? accessibilityValidation.level : undefined,
130
+ version: accessibilityValidation
131
+ ? accessibilityValidation.guidelinesVersion
132
+ : undefined,
133
+ }
134
+ : undefined,
91
135
  };
92
136
 
137
+ function mapAccessibilityRegions(accessabilityRegions) {
138
+ if (!accessabilityRegions) return;
139
+ if (!Array.isArray(accessabilityRegions)) accessabilityRegions = [accessabilityRegions];
140
+ return accessabilityRegions.map(region => {
141
+ const res = {
142
+ type: region.accessibilityType,
143
+ };
144
+ if (region.selector) {
145
+ res.region = region.selector;
146
+ } else if (region.region && isRegion(region.region)) {
147
+ res.region = {
148
+ y: region.region.top,
149
+ x: region.region.left,
150
+ width: region.region.width,
151
+ height: region.region.height,
152
+ };
153
+ } else {
154
+ return;
155
+ }
156
+ return res;
157
+ });
158
+ }
159
+
160
+ function mapFloatingRegions(floatingRegions) {
161
+ if (!floatingRegions) return;
162
+ if (!Array.isArray(floatingRegions)) floatingRegions = [floatingRegions];
163
+ return floatingRegions.map(region => {
164
+ let res = {
165
+ offset: {
166
+ bottom: region.maxDownOffset || 0,
167
+ left: region.maxLeftOffset || 0,
168
+ top: region.maxUpOffset || 0,
169
+ right: region.maxRightOffset || 0,
170
+ },
171
+ };
172
+ if (region.selector) {
173
+ res.region = region.selector;
174
+ } else if (region.region && isRegion(region.region)) {
175
+ res.region = {
176
+ y: region.region.top,
177
+ x: region.region.left,
178
+ width: region.region.width,
179
+ height: region.region.height,
180
+ };
181
+ } else {
182
+ return;
183
+ }
184
+ return res;
185
+ });
186
+ }
187
+
188
+ function isRegion(region) {
189
+ if (
190
+ region.hasOwnProperty('top') &&
191
+ region.hasOwnProperty('left') &&
192
+ region.hasOwnProperty('width') &&
193
+ region.hasOwnProperty('height')
194
+ ) {
195
+ return true;
196
+ }
197
+ }
198
+
93
199
  return timeItAsync(baselineName, async () => {
94
- return testWindow({openParams, checkParams, throwEx: false});
200
+ const {checkAndClose} = await openEyes({settings: openParams});
201
+ return new Promise((resolve, reject) => {
202
+ throttle(async () => {
203
+ try {
204
+ const checkResults = await checkAndClose({
205
+ settings: {...checkParams, ...closeSettings, throwEx: false},
206
+ target: snapshots,
207
+ });
208
+ resolve(checkResults);
209
+ } catch (ex) {
210
+ reject(ex);
211
+ }
212
+ });
213
+ });
95
214
  }).then(onDoneStory);
96
215
 
97
216
  function onDoneStory(results) {
@@ -1,7 +1,7 @@
1
1
  function splitConfigsByBrowser(config) {
2
- const browsers = validateBrowsers(config);
3
- if (browsers.length) {
4
- const result = browsers.reduce(
2
+ const renderers = validateBrowsers(config);
3
+ if (renderers.length) {
4
+ const result = renderers.reduce(
5
5
  ([nonIE, IE], browser) => {
6
6
  if (isIE(browser)) {
7
7
  IE.push(browser);
@@ -14,7 +14,7 @@ function splitConfigsByBrowser(config) {
14
14
  );
15
15
 
16
16
  return result.reduce(
17
- (acc, browser) => (browser.length > 0 ? acc.concat({...config, browser}) : acc),
17
+ (acc, browser) => (browser.length > 0 ? acc.concat({...config, renderers: browser}) : acc),
18
18
  [],
19
19
  );
20
20
  } else {
@@ -35,8 +35,8 @@ function isIE(browser) {
35
35
  }
36
36
 
37
37
  function validateBrowsers(config) {
38
- if (config.browser) {
39
- return Array.isArray(config.browser) ? config.browser : [config.browser];
38
+ if (config.renderers) {
39
+ return Array.isArray(config.renderers) ? config.renderers : [config.renderers];
40
40
  } else {
41
41
  return [];
42
42
  }
@@ -58,7 +58,7 @@ async function validateAndPopulateConfig({config, packagePath, logger}) {
58
58
  }
59
59
  }
60
60
 
61
- if (config.fakeIE && !config.browser.find(isIE)) {
61
+ if (config.fakeIE && !config.renderers.find(isIE)) {
62
62
  console.log(
63
63
  chalk.yellow(
64
64
  `\u26A0 fakeIE flag was set, but no IE browsers were found in the configuration`,