@applitools/eyes-storybook 3.53.5 → 3.53.7
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 +80 -0
- package/dist/getClientAPI.js +18 -4
- package/dist/getStories.js +20 -38
- package/dist/renderStoryWithClientAPI.js +18 -4
- package/dist/runRunAfterScript.js +18 -4
- package/dist/runRunBeforeScript.js +18 -4
- package/package.json +6 -7
- package/src/browser/getClientAPI.js +18 -4
- package/src/browser/getStories.js +2 -34
- package/src/configParams.js +1 -0
- package/src/eyesStorybook.js +43 -19
- package/src/getStoryData.js +15 -15
- package/src/initPage.js +3 -1
- package/src/pagePool.js +1 -0
- package/src/renderStories.js +10 -23
- package/src/utils/executeWithRetry.js +22 -0
- package/src/postinstall.js +0 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,85 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.53.7](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.53.6...js/eyes-storybook@3.53.7) (2025-02-10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* remove deprecated postinstall script ([#2729](https://github.com/Applitools-Dev/sdk/issues/2729)) ([28075c1](https://github.com/Applitools-Dev/sdk/commit/28075c10342c1e169040ac8b720f5c273bc9bf31))
|
|
9
|
+
* respect readStoriesTimeout ([#2776](https://github.com/Applitools-Dev/sdk/issues/2776)) ([8c841f4](https://github.com/Applitools-Dev/sdk/commit/8c841f492641759f056af889dbac68e711782b26))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Dependencies
|
|
13
|
+
|
|
14
|
+
* @applitools/ufg-client bumped to 1.16.4
|
|
15
|
+
#### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* environment without type in ios should be considered web ([#2779](https://github.com/Applitools-Dev/sdk/issues/2779)) ([1a0dc18](https://github.com/Applitools-Dev/sdk/commit/1a0dc186d782ee8dacccf4ea9d10b513416b7492))
|
|
18
|
+
* specifying chrome version in UFG chrome emulations ([#2773](https://github.com/Applitools-Dev/sdk/issues/2773)) ([e86af5d](https://github.com/Applitools-Dev/sdk/commit/e86af5d8d616fb54a6cbe0a23db691d0b190b0f6))
|
|
19
|
+
* @applitools/core bumped to 4.31.2
|
|
20
|
+
#### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* environment without type in ios should be considered web ([#2779](https://github.com/Applitools-Dev/sdk/issues/2779)) ([1a0dc18](https://github.com/Applitools-Dev/sdk/commit/1a0dc186d782ee8dacccf4ea9d10b513416b7492))
|
|
23
|
+
* move log line for closing batch in offline cli ([#2768](https://github.com/Applitools-Dev/sdk/issues/2768)) ([bfb51a9](https://github.com/Applitools-Dev/sdk/commit/bfb51a94d8e7d51020aac62dd78038fdeb819a68))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
* @applitools/eyes bumped to 1.32.1
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## [3.53.6](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.53.5...js/eyes-storybook@3.53.6) (2025-01-30)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Bug Fixes
|
|
34
|
+
|
|
35
|
+
* storybook exception and add logs ([#2760](https://github.com/Applitools-Dev/sdk/issues/2760)) ([357193a](https://github.com/Applitools-Dev/sdk/commit/357193ad0f18eae729b4064d14d781e2401c70f7))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Dependencies
|
|
39
|
+
|
|
40
|
+
* @applitools/dom-snapshot bumped to 4.11.15
|
|
41
|
+
|
|
42
|
+
* @applitools/driver bumped to 1.20.4
|
|
43
|
+
#### Bug Fixes
|
|
44
|
+
|
|
45
|
+
* handle device screen info extraction gracefully ([#2757](https://github.com/Applitools-Dev/sdk/issues/2757)) ([92d0118](https://github.com/Applitools-Dev/sdk/commit/92d0118137b77e49d780092d110973df8ed8b40c))
|
|
46
|
+
* @applitools/eyes bumped to 1.32.0
|
|
47
|
+
#### Features
|
|
48
|
+
|
|
49
|
+
* remove iPhoneX from list of available UFG Safari devices ([#2756](https://github.com/Applitools-Dev/sdk/issues/2756)) ([e24d054](https://github.com/Applitools-Dev/sdk/commit/e24d054328df900fbc4988fdbf8213aadffa9a37))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
* @applitools/spec-driver-webdriver bumped to 1.1.25
|
|
54
|
+
|
|
55
|
+
* @applitools/spec-driver-selenium bumped to 1.5.95
|
|
56
|
+
|
|
57
|
+
* @applitools/spec-driver-puppeteer bumped to 1.4.24
|
|
58
|
+
|
|
59
|
+
* @applitools/screenshoter bumped to 3.10.5
|
|
60
|
+
|
|
61
|
+
* @applitools/nml-client bumped to 1.8.24
|
|
62
|
+
|
|
63
|
+
* @applitools/ufg-client bumped to 1.16.3
|
|
64
|
+
#### Bug Fixes
|
|
65
|
+
|
|
66
|
+
* unthrottle renders in offline mode ([#2754](https://github.com/Applitools-Dev/sdk/issues/2754)) ([b65d816](https://github.com/Applitools-Dev/sdk/commit/b65d81610504ae725b7b52611282a1bb28a049fe))
|
|
67
|
+
* @applitools/ec-client bumped to 1.10.3
|
|
68
|
+
|
|
69
|
+
* @applitools/core bumped to 4.31.0
|
|
70
|
+
#### Features
|
|
71
|
+
|
|
72
|
+
* remove iPhoneX from list of available UFG Safari devices ([#2756](https://github.com/Applitools-Dev/sdk/issues/2756)) ([e24d054](https://github.com/Applitools-Dev/sdk/commit/e24d054328df900fbc4988fdbf8213aadffa9a37))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
#### Bug Fixes
|
|
76
|
+
|
|
77
|
+
* handle device screen info extraction gracefully ([#2757](https://github.com/Applitools-Dev/sdk/issues/2757)) ([92d0118](https://github.com/Applitools-Dev/sdk/commit/92d0118137b77e49d780092d110973df8ed8b40c))
|
|
78
|
+
* unthrottle renders in offline mode ([#2754](https://github.com/Applitools-Dev/sdk/issues/2754)) ([b65d816](https://github.com/Applitools-Dev/sdk/commit/b65d81610504ae725b7b52611282a1bb28a049fe))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
3
83
|
## [3.53.5](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.53.4...js/eyes-storybook@3.53.5) (2025-01-23)
|
|
4
84
|
|
|
5
85
|
|
package/dist/getClientAPI.js
CHANGED
|
@@ -38,7 +38,16 @@ function __getClientAPI(...args) {
|
|
|
38
38
|
) {
|
|
39
39
|
return API_VERSIONS.v4;
|
|
40
40
|
} else {
|
|
41
|
-
|
|
41
|
+
const storybookVariablesOnWindow = Object.keys(frameWindow).filter(key =>
|
|
42
|
+
key.includes('STORYBOOK'),
|
|
43
|
+
);
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Cannot get client API: couldn't detect storybook version.${
|
|
46
|
+
storybookVariablesOnWindow.length
|
|
47
|
+
? ` Found the following storybook variables: ${storybookVariablesOnWindow.join(', ')}`
|
|
48
|
+
: ' - no STORYBOOK variables found in global scope'
|
|
49
|
+
}`,
|
|
50
|
+
);
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
function onStoryRendered(callback) {
|
|
@@ -181,13 +190,18 @@ function __getClientAPI(...args) {
|
|
|
181
190
|
throw new Error('Cannot get client API: no frameWindow');
|
|
182
191
|
}
|
|
183
192
|
|
|
184
|
-
async function getClientAPIWithRetries() {
|
|
193
|
+
async function getClientAPIWithRetries({timeout = 5000} = {}) {
|
|
185
194
|
let error = 'Unknown error';
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
const RETRY_INTERVAL = 100;
|
|
196
|
+
const totalAttempts = timeout / RETRY_INTERVAL;
|
|
197
|
+
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
198
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
|
|
188
199
|
try {
|
|
189
200
|
return getClientAPI();
|
|
190
201
|
} catch (e) {
|
|
202
|
+
if (!(attempt % 10)) {
|
|
203
|
+
console.log(`Error in getClientAPI: ${e.message}, attempt ${attempt}/${totalAttempts}`);
|
|
204
|
+
}
|
|
191
205
|
error = e;
|
|
192
206
|
}
|
|
193
207
|
}
|
package/dist/getStories.js
CHANGED
|
@@ -38,7 +38,16 @@ function __getStories(...args) {
|
|
|
38
38
|
) {
|
|
39
39
|
return API_VERSIONS.v4;
|
|
40
40
|
} else {
|
|
41
|
-
|
|
41
|
+
const storybookVariablesOnWindow = Object.keys(frameWindow).filter(key =>
|
|
42
|
+
key.includes('STORYBOOK'),
|
|
43
|
+
);
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Cannot get client API: couldn't detect storybook version.${
|
|
46
|
+
storybookVariablesOnWindow.length
|
|
47
|
+
? ` Found the following storybook variables: ${storybookVariablesOnWindow.join(', ')}`
|
|
48
|
+
: ' - no STORYBOOK variables found in global scope'
|
|
49
|
+
}`,
|
|
50
|
+
);
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
function onStoryRendered(callback) {
|
|
@@ -181,13 +190,18 @@ function __getStories(...args) {
|
|
|
181
190
|
throw new Error('Cannot get client API: no frameWindow');
|
|
182
191
|
}
|
|
183
192
|
|
|
184
|
-
async function getClientAPIWithRetries() {
|
|
193
|
+
async function getClientAPIWithRetries({timeout = 5000} = {}) {
|
|
185
194
|
let error = 'Unknown error';
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
const RETRY_INTERVAL = 100;
|
|
196
|
+
const totalAttempts = timeout / RETRY_INTERVAL;
|
|
197
|
+
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
198
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
|
|
188
199
|
try {
|
|
189
200
|
return getClientAPI();
|
|
190
201
|
} catch (e) {
|
|
202
|
+
if (!(attempt % 10)) {
|
|
203
|
+
console.log(`Error in getClientAPI: ${e.message}, attempt ${attempt}/${totalAttempts}`);
|
|
204
|
+
}
|
|
191
205
|
error = e;
|
|
192
206
|
}
|
|
193
207
|
}
|
|
@@ -196,9 +210,7 @@ function __getStories(...args) {
|
|
|
196
210
|
|
|
197
211
|
var getClientAPI_1 = getClientAPIWithRetries;
|
|
198
212
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
async function getStories({timeout = DEFAULT_TIMEOUT} = {timeout: DEFAULT_TIMEOUT}) {
|
|
213
|
+
async function getStories() {
|
|
202
214
|
const Stories = {
|
|
203
215
|
_getStoriesV2: () => {
|
|
204
216
|
let categories = getCategoriesV2();
|
|
@@ -283,7 +295,7 @@ function __getStories(...args) {
|
|
|
283
295
|
},
|
|
284
296
|
};
|
|
285
297
|
|
|
286
|
-
const clientApi = await
|
|
298
|
+
const clientApi = await getClientAPI_1().catch(() => null);
|
|
287
299
|
|
|
288
300
|
if (clientApi) {
|
|
289
301
|
console.log(`getting stories from storybook via API. ${clientApi.version}`);
|
|
@@ -362,36 +374,6 @@ function __getStories(...args) {
|
|
|
362
374
|
s => s.innerText === 'loading story',
|
|
363
375
|
);
|
|
364
376
|
}
|
|
365
|
-
|
|
366
|
-
function waitForClientAPI() {
|
|
367
|
-
return ptimeoutWithValue(_waitForClientAPI, timeout, undefined);
|
|
368
|
-
|
|
369
|
-
async function _waitForClientAPI() {
|
|
370
|
-
try {
|
|
371
|
-
return getClientAPI_1();
|
|
372
|
-
} catch (ex) {
|
|
373
|
-
await delay(100);
|
|
374
|
-
return _waitForClientAPI();
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
async function delay(time) {
|
|
380
|
-
return new Promise(res => {
|
|
381
|
-
setTimeout(res, time);
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
async function ptimeoutWithValue(getPromise, delay, value) {
|
|
386
|
-
let _res, _rej;
|
|
387
|
-
const result = new Promise((res, rej) => ((_res = res), (_rej = rej)));
|
|
388
|
-
const cancel = setTimeout(() => _res(value), delay);
|
|
389
|
-
getPromise()
|
|
390
|
-
.then(v => _res(v))
|
|
391
|
-
.catch(e => _rej(e))
|
|
392
|
-
.finally(() => clearTimeout(cancel));
|
|
393
|
-
return result;
|
|
394
|
-
}
|
|
395
377
|
}
|
|
396
378
|
|
|
397
379
|
var getStories_1 = getStories;
|
|
@@ -38,7 +38,16 @@ function __renderStoryWithClientAPI(...args) {
|
|
|
38
38
|
) {
|
|
39
39
|
return API_VERSIONS.v4;
|
|
40
40
|
} else {
|
|
41
|
-
|
|
41
|
+
const storybookVariablesOnWindow = Object.keys(frameWindow).filter(key =>
|
|
42
|
+
key.includes('STORYBOOK'),
|
|
43
|
+
);
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Cannot get client API: couldn't detect storybook version.${
|
|
46
|
+
storybookVariablesOnWindow.length
|
|
47
|
+
? ` Found the following storybook variables: ${storybookVariablesOnWindow.join(', ')}`
|
|
48
|
+
: ' - no STORYBOOK variables found in global scope'
|
|
49
|
+
}`,
|
|
50
|
+
);
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
function onStoryRendered(callback) {
|
|
@@ -181,13 +190,18 @@ function __renderStoryWithClientAPI(...args) {
|
|
|
181
190
|
throw new Error('Cannot get client API: no frameWindow');
|
|
182
191
|
}
|
|
183
192
|
|
|
184
|
-
async function getClientAPIWithRetries() {
|
|
193
|
+
async function getClientAPIWithRetries({timeout = 5000} = {}) {
|
|
185
194
|
let error = 'Unknown error';
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
const RETRY_INTERVAL = 100;
|
|
196
|
+
const totalAttempts = timeout / RETRY_INTERVAL;
|
|
197
|
+
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
198
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
|
|
188
199
|
try {
|
|
189
200
|
return getClientAPI();
|
|
190
201
|
} catch (e) {
|
|
202
|
+
if (!(attempt % 10)) {
|
|
203
|
+
console.log(`Error in getClientAPI: ${e.message}, attempt ${attempt}/${totalAttempts}`);
|
|
204
|
+
}
|
|
191
205
|
error = e;
|
|
192
206
|
}
|
|
193
207
|
}
|
|
@@ -38,7 +38,16 @@ function __runRunAfterScript(...args) {
|
|
|
38
38
|
) {
|
|
39
39
|
return API_VERSIONS.v4;
|
|
40
40
|
} else {
|
|
41
|
-
|
|
41
|
+
const storybookVariablesOnWindow = Object.keys(frameWindow).filter(key =>
|
|
42
|
+
key.includes('STORYBOOK'),
|
|
43
|
+
);
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Cannot get client API: couldn't detect storybook version.${
|
|
46
|
+
storybookVariablesOnWindow.length
|
|
47
|
+
? ` Found the following storybook variables: ${storybookVariablesOnWindow.join(', ')}`
|
|
48
|
+
: ' - no STORYBOOK variables found in global scope'
|
|
49
|
+
}`,
|
|
50
|
+
);
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
function onStoryRendered(callback) {
|
|
@@ -181,13 +190,18 @@ function __runRunAfterScript(...args) {
|
|
|
181
190
|
throw new Error('Cannot get client API: no frameWindow');
|
|
182
191
|
}
|
|
183
192
|
|
|
184
|
-
async function getClientAPIWithRetries() {
|
|
193
|
+
async function getClientAPIWithRetries({timeout = 5000} = {}) {
|
|
185
194
|
let error = 'Unknown error';
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
const RETRY_INTERVAL = 100;
|
|
196
|
+
const totalAttempts = timeout / RETRY_INTERVAL;
|
|
197
|
+
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
198
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
|
|
188
199
|
try {
|
|
189
200
|
return getClientAPI();
|
|
190
201
|
} catch (e) {
|
|
202
|
+
if (!(attempt % 10)) {
|
|
203
|
+
console.log(`Error in getClientAPI: ${e.message}, attempt ${attempt}/${totalAttempts}`);
|
|
204
|
+
}
|
|
191
205
|
error = e;
|
|
192
206
|
}
|
|
193
207
|
}
|
|
@@ -38,7 +38,16 @@ function __runRunBeforeScript(...args) {
|
|
|
38
38
|
) {
|
|
39
39
|
return API_VERSIONS.v4;
|
|
40
40
|
} else {
|
|
41
|
-
|
|
41
|
+
const storybookVariablesOnWindow = Object.keys(frameWindow).filter(key =>
|
|
42
|
+
key.includes('STORYBOOK'),
|
|
43
|
+
);
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Cannot get client API: couldn't detect storybook version.${
|
|
46
|
+
storybookVariablesOnWindow.length
|
|
47
|
+
? ` Found the following storybook variables: ${storybookVariablesOnWindow.join(', ')}`
|
|
48
|
+
: ' - no STORYBOOK variables found in global scope'
|
|
49
|
+
}`,
|
|
50
|
+
);
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
function onStoryRendered(callback) {
|
|
@@ -181,13 +190,18 @@ function __runRunBeforeScript(...args) {
|
|
|
181
190
|
throw new Error('Cannot get client API: no frameWindow');
|
|
182
191
|
}
|
|
183
192
|
|
|
184
|
-
async function getClientAPIWithRetries() {
|
|
193
|
+
async function getClientAPIWithRetries({timeout = 5000} = {}) {
|
|
185
194
|
let error = 'Unknown error';
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
const RETRY_INTERVAL = 100;
|
|
196
|
+
const totalAttempts = timeout / RETRY_INTERVAL;
|
|
197
|
+
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
198
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
|
|
188
199
|
try {
|
|
189
200
|
return getClientAPI();
|
|
190
201
|
} catch (e) {
|
|
202
|
+
if (!(attempt % 10)) {
|
|
203
|
+
console.log(`Error in getClientAPI: ${e.message}, attempt ${attempt}/${totalAttempts}`);
|
|
204
|
+
}
|
|
191
205
|
error = e;
|
|
192
206
|
}
|
|
193
207
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-storybook",
|
|
3
|
-
"version": "3.53.
|
|
3
|
+
"version": "3.53.7",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"applitools",
|
|
@@ -50,18 +50,17 @@
|
|
|
50
50
|
"changelog": "git changelog -x -p -f v$npm_package_version > History.md && git add ./History.md && git commit -am 'changelog'",
|
|
51
51
|
"changelog:init": "git config changelog.format \"* %s [[%h]($(echo $npm_package_repository_url|cut -d+ -f2|cut -d. -f1-2)/commit/%H)]\"",
|
|
52
52
|
"changelog:install": "sudo apt-get install git-extras",
|
|
53
|
-
"postinstall": "node src/postinstall",
|
|
54
53
|
"up:framework": "cd test/fixtures/storybook-versions/${APPLITOOLS_FRAMEWORK_VERSION} && npm ci"
|
|
55
54
|
},
|
|
56
55
|
"dependencies": {
|
|
57
|
-
"@applitools/core": "4.
|
|
58
|
-
"@applitools/driver": "1.20.
|
|
59
|
-
"@applitools/eyes": "1.
|
|
56
|
+
"@applitools/core": "4.31.2",
|
|
57
|
+
"@applitools/driver": "1.20.4",
|
|
58
|
+
"@applitools/eyes": "1.32.1",
|
|
60
59
|
"@applitools/functional-commons": "1.6.0",
|
|
61
60
|
"@applitools/logger": "2.1.0",
|
|
62
61
|
"@applitools/monitoring-commons": "1.0.19",
|
|
63
|
-
"@applitools/spec-driver-puppeteer": "1.4.
|
|
64
|
-
"@applitools/ufg-client": "1.16.
|
|
62
|
+
"@applitools/spec-driver-puppeteer": "1.4.24",
|
|
63
|
+
"@applitools/ufg-client": "1.16.4",
|
|
65
64
|
"@applitools/utils": "1.7.7",
|
|
66
65
|
"boxen": "4.2.0",
|
|
67
66
|
"chalk": "3.0.0",
|
|
@@ -35,7 +35,16 @@ function getClientAPI() {
|
|
|
35
35
|
) {
|
|
36
36
|
return API_VERSIONS.v4;
|
|
37
37
|
} else {
|
|
38
|
-
|
|
38
|
+
const storybookVariablesOnWindow = Object.keys(frameWindow).filter(key =>
|
|
39
|
+
key.includes('STORYBOOK'),
|
|
40
|
+
);
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Cannot get client API: couldn't detect storybook version.${
|
|
43
|
+
storybookVariablesOnWindow.length
|
|
44
|
+
? ` Found the following storybook variables: ${storybookVariablesOnWindow.join(', ')}`
|
|
45
|
+
: ' - no STORYBOOK variables found in global scope'
|
|
46
|
+
}`,
|
|
47
|
+
);
|
|
39
48
|
}
|
|
40
49
|
}
|
|
41
50
|
function onStoryRendered(callback) {
|
|
@@ -178,13 +187,18 @@ function getFrameWindow() {
|
|
|
178
187
|
throw new Error('Cannot get client API: no frameWindow');
|
|
179
188
|
}
|
|
180
189
|
|
|
181
|
-
async function getClientAPIWithRetries() {
|
|
190
|
+
async function getClientAPIWithRetries({timeout = 5000} = {}) {
|
|
182
191
|
let error = 'Unknown error';
|
|
183
|
-
|
|
184
|
-
|
|
192
|
+
const RETRY_INTERVAL = 100;
|
|
193
|
+
const totalAttempts = timeout / RETRY_INTERVAL;
|
|
194
|
+
for (let attempt = 1; attempt <= totalAttempts; attempt++) {
|
|
195
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
|
|
185
196
|
try {
|
|
186
197
|
return getClientAPI();
|
|
187
198
|
} catch (e) {
|
|
199
|
+
if (!(attempt % 10)) {
|
|
200
|
+
console.log(`Error in getClientAPI: ${e.message}, attempt ${attempt}/${totalAttempts}`);
|
|
201
|
+
}
|
|
188
202
|
error = e;
|
|
189
203
|
}
|
|
190
204
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
const getClientAPI = require('./getClientAPI');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
async function getStories({timeout = DEFAULT_TIMEOUT} = {timeout: DEFAULT_TIMEOUT}) {
|
|
3
|
+
async function getStories() {
|
|
6
4
|
const Stories = {
|
|
7
5
|
_getStoriesV2: () => {
|
|
8
6
|
let categories = getCategoriesV2();
|
|
@@ -87,7 +85,7 @@ async function getStories({timeout = DEFAULT_TIMEOUT} = {timeout: DEFAULT_TIMEOU
|
|
|
87
85
|
},
|
|
88
86
|
};
|
|
89
87
|
|
|
90
|
-
const clientApi = await
|
|
88
|
+
const clientApi = await getClientAPI().catch(() => null);
|
|
91
89
|
|
|
92
90
|
if (clientApi) {
|
|
93
91
|
console.log(`getting stories from storybook via API. ${clientApi.version}`);
|
|
@@ -166,36 +164,6 @@ async function getStories({timeout = DEFAULT_TIMEOUT} = {timeout: DEFAULT_TIMEOU
|
|
|
166
164
|
s => s.innerText === 'loading story',
|
|
167
165
|
);
|
|
168
166
|
}
|
|
169
|
-
|
|
170
|
-
function waitForClientAPI() {
|
|
171
|
-
return ptimeoutWithValue(_waitForClientAPI, timeout, undefined);
|
|
172
|
-
|
|
173
|
-
async function _waitForClientAPI() {
|
|
174
|
-
try {
|
|
175
|
-
return getClientAPI();
|
|
176
|
-
} catch (ex) {
|
|
177
|
-
await delay(100);
|
|
178
|
-
return _waitForClientAPI();
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function delay(time) {
|
|
184
|
-
return new Promise(res => {
|
|
185
|
-
setTimeout(res, time);
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async function ptimeoutWithValue(getPromise, delay, value) {
|
|
190
|
-
let _res, _rej;
|
|
191
|
-
const result = new Promise((res, rej) => ((_res = res), (_rej = rej)));
|
|
192
|
-
const cancel = setTimeout(() => _res(value), delay);
|
|
193
|
-
getPromise()
|
|
194
|
-
.then(v => _res(v))
|
|
195
|
-
.catch(e => _rej(e))
|
|
196
|
-
.finally(() => clearTimeout(cancel));
|
|
197
|
-
return result;
|
|
198
|
-
}
|
|
199
167
|
}
|
|
200
168
|
|
|
201
169
|
module.exports = getStories;
|
package/src/configParams.js
CHANGED
package/src/eyesStorybook.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const puppeteer = require('puppeteer');
|
|
3
3
|
const getStories = require('../dist/getStories');
|
|
4
|
-
const {presult
|
|
4
|
+
const {presult} = require('@applitools/functional-commons');
|
|
5
|
+
const {executeWithRetry} = require('./utils/executeWithRetry');
|
|
5
6
|
const chalk = require('chalk');
|
|
6
7
|
const makeInitPage = require('./initPage');
|
|
7
8
|
const makeRenderStory = require('./renderStory');
|
|
@@ -23,9 +24,6 @@ const {extractEnvironment} = require('./extractEnvironment');
|
|
|
23
24
|
const {makeCore} = require('@applitools/core');
|
|
24
25
|
const makeGetStoriesWithConfig = require('./getStoriesWithConfig');
|
|
25
26
|
|
|
26
|
-
const MAX_RETRIES = 30;
|
|
27
|
-
const RETRY_INTERVAL = 1000;
|
|
28
|
-
|
|
29
27
|
async function eyesStorybook({
|
|
30
28
|
config,
|
|
31
29
|
logger,
|
|
@@ -166,7 +164,7 @@ async function eyesStorybook({
|
|
|
166
164
|
const renderStories = makeRenderStories({
|
|
167
165
|
getStoryData,
|
|
168
166
|
renderStory,
|
|
169
|
-
|
|
167
|
+
sanityCheckForPage,
|
|
170
168
|
storybookUrl,
|
|
171
169
|
logger,
|
|
172
170
|
stream: outputStream,
|
|
@@ -234,10 +232,10 @@ async function eyesStorybook({
|
|
|
234
232
|
throw new Error();
|
|
235
233
|
}
|
|
236
234
|
|
|
237
|
-
const [getStoriesErr, stories] = await readStoriesWithRetry(
|
|
235
|
+
const [getStoriesErr, stories] = await presult(readStoriesWithRetry());
|
|
238
236
|
|
|
239
237
|
if (getStoriesErr) {
|
|
240
|
-
logger.log('Error
|
|
238
|
+
logger.log('Error when reading stories:', getStoriesErr);
|
|
241
239
|
const failMsg = refineErrorMessage({
|
|
242
240
|
prefix: 'Error when reading stories:',
|
|
243
241
|
error: getStoriesErr,
|
|
@@ -283,20 +281,46 @@ async function eyesStorybook({
|
|
|
283
281
|
return transitioning;
|
|
284
282
|
}
|
|
285
283
|
|
|
286
|
-
async function readStoriesWithRetry(
|
|
287
|
-
|
|
288
|
-
|
|
284
|
+
async function readStoriesWithRetry() {
|
|
285
|
+
return executeWithRetry(
|
|
286
|
+
_readStoriesWithRetry,
|
|
287
|
+
{
|
|
288
|
+
timeout: readStoriesTimeout,
|
|
289
|
+
delayBetweenRetries: 1000,
|
|
290
|
+
initialErrMessage: `Could not get stories since readStoriesTimeout is too short (${readStoriesTimeout}ms)`,
|
|
291
|
+
},
|
|
292
|
+
readStoriesTimeout,
|
|
289
293
|
);
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
294
|
+
|
|
295
|
+
async function _readStoriesWithRetry() {
|
|
296
|
+
try {
|
|
297
|
+
const stories = await page.evaluate(getStories);
|
|
298
|
+
if (stories.length > 0) {
|
|
299
|
+
return stories;
|
|
300
|
+
} else {
|
|
301
|
+
throw new Error('Got 0 stories');
|
|
302
|
+
}
|
|
303
|
+
} catch (err) {
|
|
304
|
+
logger.log('Error in _readStoriesWithRetry:', err, ', retrying...');
|
|
305
|
+
throw err;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function sanityCheckForPage(page) {
|
|
311
|
+
return executeWithRetry(_sanityCheckForPage, {
|
|
312
|
+
timeout: readStoriesTimeout,
|
|
313
|
+
delayBetweenRetries: 1000,
|
|
314
|
+
initialErrMessage: `Could not get client API in sanity check since readStoriesTimeout is too short (${readStoriesTimeout}ms)`,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
async function _sanityCheckForPage() {
|
|
318
|
+
try {
|
|
319
|
+
await page.evaluate(getClientAPI);
|
|
320
|
+
} catch (err) {
|
|
321
|
+
logger.log('Error in getClientAPI during sanity check:', err, ', retrying...');
|
|
322
|
+
throw err;
|
|
297
323
|
}
|
|
298
|
-
await delay(RETRY_INTERVAL);
|
|
299
|
-
return await readStoriesWithRetry(remainingRetries - 1);
|
|
300
324
|
}
|
|
301
325
|
}
|
|
302
326
|
}
|
package/src/getStoryData.js
CHANGED
|
@@ -13,9 +13,9 @@ const DOM_SNAPSHOTS_TIMEOUT = 5 * 60 * 1000;
|
|
|
13
13
|
const utils = require('@applitools/utils');
|
|
14
14
|
|
|
15
15
|
function makeGetStoryData({logger, takeDomSnapshots, reloadPagePerStory, navigationWaitUntil}) {
|
|
16
|
-
return async function getStoryData({story, storyUrl, page}) {
|
|
16
|
+
return async function getStoryData({story, storyUrl, page, pageId = 'mock'}) {
|
|
17
17
|
const title = getStoryBaselineName(story);
|
|
18
|
-
logger.log(`getting data from story`, title);
|
|
18
|
+
logger.log(`[page ${pageId}] getting data from story`, title);
|
|
19
19
|
|
|
20
20
|
const eyesParameters = story.parameters && story.parameters.eyes;
|
|
21
21
|
if (story.isApi && !reloadPagePerStory) {
|
|
@@ -26,9 +26,9 @@ function makeGetStoryData({logger, takeDomSnapshots, reloadPagePerStory, navigat
|
|
|
26
26
|
const err = await ptimeoutWithError(
|
|
27
27
|
page.evaluate(renderStoryWithClientAPI, story.index, story.id),
|
|
28
28
|
PAGE_EVALUATE_TIMEOUT,
|
|
29
|
-
new Error(
|
|
29
|
+
new Error(`[page ${pageId}] page evaluate timed out!`),
|
|
30
30
|
);
|
|
31
|
-
logger.log(`[
|
|
31
|
+
logger.log(`[page ${pageId}] done with page evaluate for story ${title}`);
|
|
32
32
|
err && handleRenderStoryError(err);
|
|
33
33
|
} catch (ex) {
|
|
34
34
|
if (ex.message && !ex.message.includes('Eyes could not render stories properly'))
|
|
@@ -53,17 +53,17 @@ function makeGetStoryData({logger, takeDomSnapshots, reloadPagePerStory, navigat
|
|
|
53
53
|
|
|
54
54
|
if (eyesParameters && eyesParameters.runBefore) {
|
|
55
55
|
await page.evaluate(runRunBeforeScript, story.index).catch(err => {
|
|
56
|
-
logger.log(`error during runBefore: ${err}`); // it might be good to aggregate these errors and output them at the end of the run
|
|
56
|
+
logger.log(`[page ${pageId}] error during runBefore: ${err}`); // it might be good to aggregate these errors and output them at the end of the run
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
logger.log(`running takeDomSnapshot(s) for story ${title}`);
|
|
60
|
+
logger.log(`[page ${pageId}] running takeDomSnapshot(s) for story ${title}`);
|
|
61
61
|
const domSnapshotsPromise = takeDomSnapshots({
|
|
62
62
|
page,
|
|
63
63
|
...storyToCheckSettings({story}),
|
|
64
64
|
waitBeforeCapture: wait
|
|
65
65
|
? async () => {
|
|
66
|
-
logger.log(`waiting before screenshot of ${title} ${wait}`);
|
|
66
|
+
logger.log(`[page ${pageId}] waiting before screenshot of ${title} ${wait}`);
|
|
67
67
|
await waitFor(page, wait);
|
|
68
68
|
}
|
|
69
69
|
: undefined,
|
|
@@ -72,27 +72,27 @@ function makeGetStoryData({logger, takeDomSnapshots, reloadPagePerStory, navigat
|
|
|
72
72
|
const result = await ptimeoutWithError(
|
|
73
73
|
domSnapshotsPromise,
|
|
74
74
|
DOM_SNAPSHOTS_TIMEOUT,
|
|
75
|
-
new Error(`timeout reached when trying to take DOM for story ${title}`),
|
|
75
|
+
new Error(`[page ${pageId}] timeout reached when trying to take DOM for story ${title}`),
|
|
76
76
|
);
|
|
77
77
|
|
|
78
|
-
logger.log(`done getting DOM for story ${title}`);
|
|
78
|
+
logger.log(`[page ${pageId}] done getting DOM for story ${title}`);
|
|
79
79
|
|
|
80
80
|
if (eyesParameters && eyesParameters.runAfter) {
|
|
81
81
|
await page.evaluate(runRunAfterScript, story.index).catch(err => {
|
|
82
|
-
logger.log(`error during runAfter: ${err}`);
|
|
82
|
+
logger.log(`[page ${pageId}] error during runAfter: ${err}`);
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
logger.log(`done getting data from story`, title);
|
|
86
|
+
logger.log(`[page ${pageId}] done getting data from story`, title);
|
|
87
87
|
return result;
|
|
88
88
|
|
|
89
89
|
async function renderStoryLegacy() {
|
|
90
|
-
logger.log(`getting data from story ${storyUrl}`);
|
|
90
|
+
logger.log(`[page ${pageId}] getting data from story ${storyUrl}`);
|
|
91
91
|
const [err] = await presult(
|
|
92
92
|
page.goto(storyUrl, {timeout: PAGE_EVALUATE_TIMEOUT, waitUntil: navigationWaitUntil}),
|
|
93
93
|
);
|
|
94
94
|
if (err) {
|
|
95
|
-
logger.log(`error navigating to story ${storyUrl}`, err);
|
|
95
|
+
logger.log(`[page ${pageId}] error navigating to story ${storyUrl}`, err);
|
|
96
96
|
throw err;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -101,7 +101,7 @@ function makeGetStoryData({logger, takeDomSnapshots, reloadPagePerStory, navigat
|
|
|
101
101
|
try {
|
|
102
102
|
url = new URL(url);
|
|
103
103
|
} catch (err) {
|
|
104
|
-
logger.error(
|
|
104
|
+
logger.error(`[page ${pageId}] Error during parsing page url`, err);
|
|
105
105
|
return false;
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -124,7 +124,7 @@ function makeGetStoryData({logger, takeDomSnapshots, reloadPagePerStory, navigat
|
|
|
124
124
|
|
|
125
125
|
// TODO (amit): handle this error in the caller (probably renderStories)
|
|
126
126
|
function handleRenderStoryError(error) {
|
|
127
|
-
logger.log(error.message);
|
|
127
|
+
logger.log(`[page ${pageId}] ${error.message}`);
|
|
128
128
|
const versionMsg = error.version
|
|
129
129
|
? ` The detected version of storybook is ${error.version}.`
|
|
130
130
|
: '';
|
package/src/initPage.js
CHANGED
|
@@ -16,7 +16,9 @@ function makeInitPage({iframeUrl, config, browser, logger, getTransitiongIntoIE,
|
|
|
16
16
|
browserLog({
|
|
17
17
|
page,
|
|
18
18
|
onLog: text => {
|
|
19
|
-
if (
|
|
19
|
+
if (config.showBrowserLogs) {
|
|
20
|
+
logger.log(`tab ${pageId}: ${text}`);
|
|
21
|
+
} else if (text.match(/\[dom-snapshot\]/)) {
|
|
20
22
|
logger.log(`tab ${pageId}: ${text}`);
|
|
21
23
|
}
|
|
22
24
|
},
|
package/src/pagePool.js
CHANGED
package/src/renderStories.js
CHANGED
|
@@ -4,9 +4,6 @@ const getStoryBaselineName = require('./getStoryBaselineName');
|
|
|
4
4
|
const ora = require('ora');
|
|
5
5
|
const {presult} = require('@applitools/functional-commons');
|
|
6
6
|
|
|
7
|
-
const MAX_RETRIES = 30;
|
|
8
|
-
const RETRY_INTERVAL = 1000;
|
|
9
|
-
|
|
10
7
|
function makeRenderStories({
|
|
11
8
|
getStoryData,
|
|
12
9
|
pagePool,
|
|
@@ -14,7 +11,7 @@ function makeRenderStories({
|
|
|
14
11
|
storybookUrl,
|
|
15
12
|
logger,
|
|
16
13
|
stream,
|
|
17
|
-
|
|
14
|
+
sanityCheckForPage,
|
|
18
15
|
maxPageTTL = 60000,
|
|
19
16
|
}) {
|
|
20
17
|
let newPageIdToAdd;
|
|
@@ -67,6 +64,7 @@ function makeRenderStories({
|
|
|
67
64
|
story,
|
|
68
65
|
storyUrl,
|
|
69
66
|
page,
|
|
67
|
+
pageId,
|
|
70
68
|
}),
|
|
71
69
|
);
|
|
72
70
|
|
|
@@ -91,6 +89,7 @@ function makeRenderStories({
|
|
|
91
89
|
story,
|
|
92
90
|
storyUrl,
|
|
93
91
|
page: newPageObj.page,
|
|
92
|
+
pageId: newPageObj.pageId,
|
|
94
93
|
}),
|
|
95
94
|
);
|
|
96
95
|
error = newError;
|
|
@@ -152,31 +151,19 @@ function makeRenderStories({
|
|
|
152
151
|
|
|
153
152
|
const {pageId, page} = pageObj;
|
|
154
153
|
logger.log(`[prepareNewPage] new page is ready: ${pageId}`);
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
try {
|
|
155
|
+
await sanityCheckForPage(page);
|
|
156
|
+
logger.log(`[prepareNewPage] setting new page for replacement: ${pageId}`);
|
|
157
|
+
newPageIdToAdd = pageId;
|
|
158
|
+
} catch (errorInSanity) {
|
|
157
159
|
logger.log(
|
|
158
|
-
`[prepareNewPage] new page ${pageId} is corrupted. preparing new page
|
|
160
|
+
`[prepareNewPage] new page ${pageId} is corrupted. preparing new page.`,
|
|
161
|
+
errorInSanity,
|
|
159
162
|
);
|
|
160
163
|
prepareNewPage();
|
|
161
|
-
return;
|
|
162
164
|
}
|
|
163
|
-
|
|
164
|
-
logger.log(`[prepareNewPage] setting new page for replacement: ${pageId}`);
|
|
165
|
-
|
|
166
|
-
newPageIdToAdd = pageId;
|
|
167
165
|
}
|
|
168
166
|
};
|
|
169
|
-
|
|
170
|
-
async function getClientAPIWithRetry(page, remainingRetries) {
|
|
171
|
-
const [err] = await presult(page.evaluate(getClientAPI));
|
|
172
|
-
if (!err || remainingRetries == 0) {
|
|
173
|
-
return [err];
|
|
174
|
-
} else if (err) {
|
|
175
|
-
logger.log('Error in getClientAPI:', err, `retrying... ${remainingRetries - 1} are left`);
|
|
176
|
-
await delay(RETRY_INTERVAL);
|
|
177
|
-
return await getClientAPIWithRetry(page, remainingRetries - 1);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
167
|
}
|
|
181
168
|
|
|
182
169
|
module.exports = makeRenderStories;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const {delay, ptimeoutWithFunction} = require('@applitools/functional-commons');
|
|
2
|
+
|
|
3
|
+
async function executeWithRetry(fn, {timeout, initialErrMessage, delayBetweenRetries}) {
|
|
4
|
+
let err = new Error(initialErrMessage);
|
|
5
|
+
|
|
6
|
+
return ptimeoutWithFunction(_executeWithRetry, timeout, () => Promise.reject(err));
|
|
7
|
+
|
|
8
|
+
async function _executeWithRetry(hasAborted) {
|
|
9
|
+
try {
|
|
10
|
+
return await fn();
|
|
11
|
+
} catch (fnErr) {
|
|
12
|
+
err = fnErr;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!hasAborted()) {
|
|
16
|
+
await delay(delayBetweenRetries);
|
|
17
|
+
return await _executeWithRetry(hasAborted);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {executeWithRetry};
|
package/src/postinstall.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
const boxen = require('boxen');
|
|
3
|
-
console.log(
|
|
4
|
-
boxen(
|
|
5
|
-
`This is version 3 of ${chalk.cyan('@applitools/eyes-storybook')}.
|
|
6
|
-
This version includes a wide variety of performance improvements and features.
|
|
7
|
-
We recommend checking out the release notes:
|
|
8
|
-
${chalk.yellow('https://github.com/applitools/eyes-storybook/blob/v3.0.1/docs/release-notes-v3.md')}
|
|
9
|
-
|
|
10
|
-
If you experience a difference in behavior between v2 and v3, it's possible to opt out of the optimization
|
|
11
|
-
by configuring ${chalk.cyan('reloadPagePerStory')} to ${chalk.cyan(
|
|
12
|
-
'true',
|
|
13
|
-
)}. And, do read the release notes - they explain it perfectly :-)`,
|
|
14
|
-
{padding: 1, borderColor: 'cyan', align: 'center'},
|
|
15
|
-
),
|
|
16
|
-
);
|