@applitools/eyes-storybook 3.60.0 → 3.61.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 +37 -0
- package/dist/index.d.ts +1 -1
- package/package.json +4 -3
- package/src/cli.js +9 -16
- package/src/errMessages.js +3 -10
- package/src/eyesStorybook.js +20 -4
- package/src/eyesStorybookEventEmitter.js +35 -0
- package/src/getConfigAndLogger.js +24 -0
- package/src/index.ts +1 -0
- package/src/main.js +7 -0
- package/src/renderStories.js +29 -5
- package/src/renderStory.js +21 -1
- package/src/transformSettings.js +0 -1
- package/src/validateAndPopulateConfig.js +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.61.0](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.60.0...js/eyes-storybook@3.61.0) (2025-10-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* storybook addon ([#3104](https://github.com/Applitools-Dev/sdk/issues/3104)) ([16e09cb](https://github.com/Applitools-Dev/sdk/commit/16e09cba8928c3a24b9e0d9d41e0936fbaec2773))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* @applitools/screenshoter bumped to 3.12.6
|
|
14
|
+
#### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* wait after scroll | FLD-3594 ([#3252](https://github.com/Applitools-Dev/sdk/issues/3252)) ([e452422](https://github.com/Applitools-Dev/sdk/commit/e4524229b64e40d9b9596a92bfa94daf5824286a))
|
|
17
|
+
* @applitools/core-base bumped to 1.28.1
|
|
18
|
+
#### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* unexpected concurrency values from server | AD-11465 ([#3248](https://github.com/Applitools-Dev/sdk/issues/3248)) ([0dd28c7](https://github.com/Applitools-Dev/sdk/commit/0dd28c7b297d5ad3aabc6b87e427e3e09a993825))
|
|
21
|
+
* @applitools/nml-client bumped to 1.11.7
|
|
22
|
+
|
|
23
|
+
* @applitools/ec-client bumped to 1.12.9
|
|
24
|
+
|
|
25
|
+
* @applitools/core bumped to 4.49.0
|
|
26
|
+
#### Features
|
|
27
|
+
|
|
28
|
+
* storybook addon ([#3104](https://github.com/Applitools-Dev/sdk/issues/3104)) ([16e09cb](https://github.com/Applitools-Dev/sdk/commit/16e09cba8928c3a24b9e0d9d41e0936fbaec2773))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
#### Bug Fixes
|
|
32
|
+
|
|
33
|
+
* duplicate concurrency warnings ([#3255](https://github.com/Applitools-Dev/sdk/issues/3255)) ([ef2f94a](https://github.com/Applitools-Dev/sdk/commit/ef2f94ab4137c78396583f166344285beeb49be7))
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
* @applitools/eyes bumped to 1.36.9
|
|
38
|
+
|
|
39
|
+
|
|
3
40
|
## [3.60.0](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.59.1...js/eyes-storybook@3.60.0) (2025-09-22)
|
|
4
41
|
|
|
5
42
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ConfigurationPlain, DesktopBrowserInfo, ChromeEmulationInfo, IOSDeviceInfo, IOSMultiDeviceInfo } from '@applitools/eyes';
|
|
2
|
-
type irrelevantToStorybook = 'waitBeforeScreenshots' | 'agentId' | 'captureStatusBar' | 'concurrentSessions' | 'connectionTimeout' | 'debugScreenshots' | 'defaultMatchSettings' | 'disableNMLUrlCache' | 'forceFullPageScreenshot' | 'hideCaret' | 'hideScrollbars' | 'hostApp' | 'hostAppInfo' | 'hostOS' | 'hostOSInfo' | 'ignoreBaseline' | 'ignoreCaret' | 'latestCommitInfo' | 'isDisabled' | 'matchTimeout' | 'mobileOptions' | 'removeSession' | 'rotation' | 'scaleRatio' | 'scrollRootElement' | 'sessionType' | 'stitchMode' | 'stitchOverlap' | 'viewportSize';
|
|
2
|
+
type irrelevantToStorybook = 'waitBeforeScreenshots' | 'agentId' | 'captureStatusBar' | 'concurrentSessions' | 'connectionTimeout' | 'debugScreenshots' | 'defaultMatchSettings' | 'disableNMLUrlCache' | 'forceFullPageScreenshot' | 'hideCaret' | 'hideScrollbars' | 'hostApp' | 'hostAppInfo' | 'hostOS' | 'hostOSInfo' | 'ignoreBaseline' | 'ignoreCaret' | 'latestCommitInfo' | 'isDisabled' | 'matchTimeout' | 'mobileOptions' | 'removeSession' | 'rotation' | 'scaleRatio' | 'scrollRootElement' | 'sessionType' | 'stitchMode' | 'stitchOverlap' | 'viewportSize' | 'isAddon';
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for Applitools Eyes Storybook integration.
|
|
5
5
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-storybook",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.61.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"applitools",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"eyes-setup": "./bin/eyes-setup.js",
|
|
20
20
|
"eyes-storybook": "./bin/eyes-storybook.js"
|
|
21
21
|
},
|
|
22
|
+
"main": "./src/main.js",
|
|
22
23
|
"files": [
|
|
23
24
|
"src",
|
|
24
25
|
"bin",
|
|
@@ -58,9 +59,9 @@
|
|
|
58
59
|
"up:framework": "cd test/fixtures/storybook-versions/${APPLITOOLS_FRAMEWORK_VERSION} && npm ci"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|
|
61
|
-
"@applitools/core": "4.
|
|
62
|
+
"@applitools/core": "4.49.0",
|
|
62
63
|
"@applitools/driver": "1.23.5",
|
|
63
|
-
"@applitools/eyes": "1.36.
|
|
64
|
+
"@applitools/eyes": "1.36.9",
|
|
64
65
|
"@applitools/functional-commons": "1.6.0",
|
|
65
66
|
"@applitools/logger": "2.2.4",
|
|
66
67
|
"@applitools/monitoring-commons": "1.0.19",
|
package/src/cli.js
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const yargs = require('yargs');
|
|
3
|
-
const {makeLogger} = require('@applitools/logger');
|
|
4
|
-
const {configParams: externalConfigParams} = require('./configParams');
|
|
5
3
|
const VERSION = require('../package.json').version;
|
|
6
|
-
const eyesStorybook = require('./eyesStorybook');
|
|
7
4
|
const processResults = require('./processResults');
|
|
8
|
-
const validateAndPopulateConfig = require('./validateAndPopulateConfig');
|
|
9
5
|
const yargsOptions = require('./yargsOptions');
|
|
10
|
-
const {generateConfig} = require('./generateConfig');
|
|
11
|
-
const defaultConfig = require('./defaultConfig');
|
|
12
|
-
const configDigest = require('./configDigest');
|
|
13
6
|
const {makeTiming} = require('@applitools/monitoring-commons');
|
|
14
7
|
const handleJsonFile = require('./handleJsonFile');
|
|
15
8
|
const handleTapFile = require('./handleTapFile');
|
|
16
9
|
const handleXmlFile = require('./handleXmlFile');
|
|
10
|
+
const {getConfigAndLogger} = require('./getConfigAndLogger');
|
|
17
11
|
const {presult} = require('@applitools/functional-commons');
|
|
18
12
|
const chalk = require('chalk');
|
|
19
13
|
const utils = require('@applitools/utils');
|
|
14
|
+
const {EyesError} = require('@applitools/eyes');
|
|
15
|
+
const eyesStorybook = require('./eyesStorybook');
|
|
20
16
|
const {performance, timeItAsync} = makeTiming();
|
|
21
17
|
|
|
22
18
|
(async function () {
|
|
@@ -31,7 +27,7 @@ const {performance, timeItAsync} = makeTiming();
|
|
|
31
27
|
.options(yargsOptions).argv;
|
|
32
28
|
|
|
33
29
|
console.log(`Using @applitools/eyes-storybook version ${VERSION}.\n`);
|
|
34
|
-
const config =
|
|
30
|
+
const {config, logger} = await getConfigAndLogger(argv);
|
|
35
31
|
|
|
36
32
|
if (config.shard) {
|
|
37
33
|
console.log(`Running with shard: ${config.shard.current}/${config.shard.total}`);
|
|
@@ -41,13 +37,6 @@ const {performance, timeItAsync} = makeTiming();
|
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
const logger = makeLogger({level: config.showLogs ? 'info' : 'silent', label: 'eyes'});
|
|
45
|
-
await validateAndPopulateConfig({
|
|
46
|
-
config,
|
|
47
|
-
logger,
|
|
48
|
-
packagePath: process.cwd(),
|
|
49
|
-
});
|
|
50
|
-
logger.log(`Running with the following config:\n${configDigest(config)}`);
|
|
51
40
|
const [err, results] = await presult(
|
|
52
41
|
timeItAsync('eyesStorybook', () => eyesStorybook({config, logger, performance, timeItAsync})),
|
|
53
42
|
);
|
|
@@ -78,7 +67,11 @@ const {performance, timeItAsync} = makeTiming();
|
|
|
78
67
|
process.exit(exitCode);
|
|
79
68
|
}
|
|
80
69
|
} catch (ex) {
|
|
81
|
-
|
|
70
|
+
if (utils.types.instanceOf(ex, EyesError)) {
|
|
71
|
+
console.log(ex.message);
|
|
72
|
+
} else {
|
|
73
|
+
console.log(ex);
|
|
74
|
+
}
|
|
82
75
|
process.exit(1);
|
|
83
76
|
}
|
|
84
77
|
})();
|
package/src/errMessages.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
const chalk = require('chalk');
|
|
3
2
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
${chalk.green(`To fix:
|
|
7
|
-
1. Register for Applitools developer account at www.applitools.com/devreg
|
|
8
|
-
2. Get API key from menu
|
|
9
|
-
3. Set APPLITOOLS_API_KEY environment variable
|
|
10
|
-
Mac/Linux: export APPLITOOLS_API_KEY=Your_API_Key_Here
|
|
11
|
-
Windows: set APPLITOOLS_API_KEY=Your_API_Key_Here`)}`;
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const {MissingApiKeyError} = require('@applitools/core');
|
|
12
5
|
|
|
13
6
|
const missingAppNameAndPackageJsonFailMsg = `
|
|
14
7
|
${chalk.red(
|
|
@@ -47,9 +40,9 @@ function deprecationWarning({deprecatedThing, newThing, isDead}) {
|
|
|
47
40
|
}
|
|
48
41
|
|
|
49
42
|
module.exports = {
|
|
50
|
-
missingApiKeyFailMsg,
|
|
51
43
|
missingAppNameAndPackageJsonFailMsg,
|
|
52
44
|
missingAppNameInPackageJsonFailMsg,
|
|
53
45
|
refineErrorMessage,
|
|
54
46
|
deprecationWarning,
|
|
47
|
+
MissingApiKeyError,
|
|
55
48
|
};
|
package/src/eyesStorybook.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const puppeteer = require('puppeteer');
|
|
3
|
+
const configDigest = require('./configDigest');
|
|
3
4
|
const getStories = require('../dist/getStories');
|
|
4
5
|
const {presult} = require('@applitools/functional-commons');
|
|
5
6
|
const {executeWithRetry} = require('./utils/executeWithRetry');
|
|
@@ -31,7 +32,11 @@ async function eyesStorybook({
|
|
|
31
32
|
performance,
|
|
32
33
|
timeItAsync,
|
|
33
34
|
outputStream = process.stderr,
|
|
35
|
+
eventEmitter,
|
|
36
|
+
signal = new AbortController().signal,
|
|
34
37
|
}) {
|
|
38
|
+
logger.log(`Running with the following config:\n${configDigest(config)}`);
|
|
39
|
+
|
|
35
40
|
let renderIE = false;
|
|
36
41
|
let transitioning = false;
|
|
37
42
|
logger.log('eyesStorybook started');
|
|
@@ -51,7 +56,6 @@ async function eyesStorybook({
|
|
|
51
56
|
logger.log(ex);
|
|
52
57
|
throw new Error(`Storybook URL is not valid: ${storybookUrl}`);
|
|
53
58
|
}
|
|
54
|
-
const agentId = `eyes-storybook/${require('../package.json').version}`;
|
|
55
59
|
process.env.PUPPETEER_DISABLE_HEADLESS_WARNING = true;
|
|
56
60
|
const browser = await puppeteer.launch(config.puppeteerOptions);
|
|
57
61
|
logger.log('browser launched');
|
|
@@ -74,7 +78,7 @@ async function eyesStorybook({
|
|
|
74
78
|
});
|
|
75
79
|
|
|
76
80
|
const environment = extractEnvironment();
|
|
77
|
-
const core = await makeCore({spec, agentId, environment, logger});
|
|
81
|
+
const core = await makeCore({spec, agentId: config.agentId, environment, logger});
|
|
78
82
|
const manager = await core.makeManager({
|
|
79
83
|
type: 'ufg',
|
|
80
84
|
settings: {concurrency: config.testConcurrency, useServerConcurrency: true},
|
|
@@ -85,7 +89,7 @@ async function eyesStorybook({
|
|
|
85
89
|
settings: {
|
|
86
90
|
eyesServerUrl: config.eyesServerUrl,
|
|
87
91
|
apiKey: config.apiKey,
|
|
88
|
-
agentId,
|
|
92
|
+
agentId: config.agentId,
|
|
89
93
|
proxy: config.proxy,
|
|
90
94
|
useDnsCache: config.useDnsCache,
|
|
91
95
|
},
|
|
@@ -182,6 +186,7 @@ async function eyesStorybook({
|
|
|
182
186
|
concurrency: account.serverConcurrency.componentConcurrency,
|
|
183
187
|
appName: config.appName,
|
|
184
188
|
serverSettings: account.eyesServer,
|
|
189
|
+
signal,
|
|
185
190
|
});
|
|
186
191
|
|
|
187
192
|
const renderStories = makeRenderStories({
|
|
@@ -192,6 +197,8 @@ async function eyesStorybook({
|
|
|
192
197
|
logger,
|
|
193
198
|
stream: outputStream,
|
|
194
199
|
pagePool,
|
|
200
|
+
eventEmitter,
|
|
201
|
+
signal,
|
|
195
202
|
});
|
|
196
203
|
|
|
197
204
|
logger.log('finished creating functions');
|
|
@@ -209,6 +216,15 @@ async function eyesStorybook({
|
|
|
209
216
|
timeItAsync,
|
|
210
217
|
}),
|
|
211
218
|
);
|
|
219
|
+
if (signal.aborted) {
|
|
220
|
+
if (error) {
|
|
221
|
+
const msg = refineErrorMessage({prefix: 'Error in executeRenders:', error});
|
|
222
|
+
logger.log('Error in executeRenders:', error);
|
|
223
|
+
throw new Error(msg);
|
|
224
|
+
} else {
|
|
225
|
+
return {results}; // processResults (which is not used in the addon) doesn't support missing the summary. But it's not a real concern right now.
|
|
226
|
+
}
|
|
227
|
+
}
|
|
212
228
|
const [errorInGetResults, testResultsSummary] = await presult(
|
|
213
229
|
manager.getResults({throwErr: false}),
|
|
214
230
|
);
|
|
@@ -219,7 +235,7 @@ async function eyesStorybook({
|
|
|
219
235
|
|
|
220
236
|
if (error) {
|
|
221
237
|
const msg = refineErrorMessage({prefix: 'Error in executeRenders:', error});
|
|
222
|
-
logger.log(error);
|
|
238
|
+
logger.log('Error in executeRenders:', error);
|
|
223
239
|
throw new Error(msg);
|
|
224
240
|
} else {
|
|
225
241
|
return {summary: testResultsSummary, results};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const eyesStorybookOrig = require('./eyesStorybook');
|
|
4
|
+
const {EventEmitter} = require('node:events');
|
|
5
|
+
|
|
6
|
+
function eyesStorybookEventEmitter({
|
|
7
|
+
eyesStorybook = eyesStorybookOrig,
|
|
8
|
+
config,
|
|
9
|
+
logger,
|
|
10
|
+
performance,
|
|
11
|
+
timeItAsync,
|
|
12
|
+
signal,
|
|
13
|
+
}) {
|
|
14
|
+
const eventEmitter = new EventEmitter();
|
|
15
|
+
const startedAt = Date.now();
|
|
16
|
+
|
|
17
|
+
eyesStorybook({config, logger, performance, timeItAsync, eventEmitter, signal})
|
|
18
|
+
.then(({results}) => {
|
|
19
|
+
eventEmitter.emit('result', {
|
|
20
|
+
startedAt,
|
|
21
|
+
duration: performance['renderStories'],
|
|
22
|
+
storyResults: results.map(({story, resultsOrErr}) => ({
|
|
23
|
+
story: {id: story.id, queryParams: story.config.queryParams},
|
|
24
|
+
[Array.isArray(resultsOrErr) ? 'results' : 'error']: resultsOrErr,
|
|
25
|
+
})),
|
|
26
|
+
});
|
|
27
|
+
})
|
|
28
|
+
.catch(err => {
|
|
29
|
+
eventEmitter.emit('error', err);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return eventEmitter;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {eyesStorybookEventEmitter};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {generateConfig} = require('./generateConfig');
|
|
4
|
+
const defaultConfig = require('./defaultConfig');
|
|
5
|
+
const validateAndPopulateConfig = require('./validateAndPopulateConfig');
|
|
6
|
+
const {makeLogger} = require('@applitools/logger');
|
|
7
|
+
const {configParams: externalConfigParams} = require('./configParams');
|
|
8
|
+
|
|
9
|
+
async function getConfigAndLogger(argv = {}) {
|
|
10
|
+
const config = generateConfig({argv, defaultConfig, externalConfigParams});
|
|
11
|
+
const logger = makeLogger({
|
|
12
|
+
handler: argv.logHandler,
|
|
13
|
+
level: argv.logHandler ? 'all' : config.showLogs ? 'info' : 'silent', // if logHandler is passed, let's pass it all the logs. Otherwise, respect the config
|
|
14
|
+
label: 'eyes',
|
|
15
|
+
});
|
|
16
|
+
await validateAndPopulateConfig({
|
|
17
|
+
config,
|
|
18
|
+
logger,
|
|
19
|
+
packagePath: process.cwd(),
|
|
20
|
+
});
|
|
21
|
+
return {config, logger};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {getConfigAndLogger};
|
package/src/index.ts
CHANGED
package/src/main.js
ADDED
package/src/renderStories.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const getStoryUrl = require('./getStoryUrl');
|
|
3
3
|
const getStoryBaselineName = require('./getStoryBaselineName');
|
|
4
4
|
const ora = require('ora');
|
|
5
|
+
const {EventEmitter} = require('node:events');
|
|
5
6
|
const {presult} = require('@applitools/functional-commons');
|
|
6
7
|
|
|
7
8
|
function makeRenderStories({
|
|
@@ -13,19 +14,23 @@ function makeRenderStories({
|
|
|
13
14
|
stream,
|
|
14
15
|
sanityCheckForPage,
|
|
15
16
|
maxPageTTL = 60000,
|
|
17
|
+
eventEmitter = new EventEmitter(),
|
|
18
|
+
signal = new AbortController().signal,
|
|
16
19
|
}) {
|
|
17
20
|
let newPageIdToAdd;
|
|
18
21
|
|
|
19
22
|
return async function renderStories(stories, isIE) {
|
|
20
23
|
let doneStories = 0;
|
|
24
|
+
const totalStories = stories.length;
|
|
21
25
|
const allTestResults = [];
|
|
22
26
|
let allStoriesPromise = Promise.resolve();
|
|
23
27
|
let currIndex = 0;
|
|
24
28
|
|
|
25
29
|
const spinner = ora({
|
|
26
|
-
text: updateSpinnerText(0,
|
|
30
|
+
text: updateSpinnerText(0, totalStories),
|
|
27
31
|
stream,
|
|
28
32
|
});
|
|
33
|
+
eventEmitter.emit('progress', {doneStories, totalStories});
|
|
29
34
|
spinner.start();
|
|
30
35
|
prepareNewPage();
|
|
31
36
|
|
|
@@ -35,7 +40,16 @@ function makeRenderStories({
|
|
|
35
40
|
return allTestResults;
|
|
36
41
|
|
|
37
42
|
async function processStoryLoop() {
|
|
38
|
-
if (currIndex ===
|
|
43
|
+
if (currIndex === totalStories) return;
|
|
44
|
+
|
|
45
|
+
if (signal.aborted) {
|
|
46
|
+
const story = stories[currIndex++];
|
|
47
|
+
const title = getStoryBaselineName(story);
|
|
48
|
+
logger.log('aborting story before processing', title);
|
|
49
|
+
onDoneStory(new Error(`${title} aborted before processing ${signal.reason}`), story);
|
|
50
|
+
return processStoryLoop();
|
|
51
|
+
}
|
|
52
|
+
|
|
39
53
|
const {page, pageId, markPageAsFree, removePage, getCreatedAt} = await pagePool.getFreePage();
|
|
40
54
|
const livedTime = Date.now() - getCreatedAt();
|
|
41
55
|
logger.log(`[prepareNewPage] got free page: ${pageId}, lived time: ${livedTime}`);
|
|
@@ -103,6 +117,12 @@ function makeRenderStories({
|
|
|
103
117
|
const errMsg = `[page ${pageId}] Failed to get story data for "${title}". ${error}`;
|
|
104
118
|
logger.log(errMsg);
|
|
105
119
|
}
|
|
120
|
+
|
|
121
|
+
if (signal.aborted) {
|
|
122
|
+
logger.log('aborting story before open', title);
|
|
123
|
+
return onDoneStory(new Error(`${title} aborted before open ${signal.reason}`), story);
|
|
124
|
+
}
|
|
125
|
+
|
|
106
126
|
const testResults = await renderStory({
|
|
107
127
|
snapshots: storyData,
|
|
108
128
|
url: storyUrl,
|
|
@@ -132,10 +152,14 @@ function makeRenderStories({
|
|
|
132
152
|
}
|
|
133
153
|
|
|
134
154
|
function onDoneStory(resultsOrErr, story) {
|
|
135
|
-
spinner.text = updateSpinnerText(++doneStories,
|
|
155
|
+
spinner.text = updateSpinnerText(++doneStories, totalStories, story.config);
|
|
136
156
|
const title = getStoryBaselineName(story);
|
|
137
|
-
|
|
138
|
-
|
|
157
|
+
const result = {title, resultsOrErr, story};
|
|
158
|
+
allTestResults.push(result);
|
|
159
|
+
|
|
160
|
+
eventEmitter.emit('progress', {doneStories, totalStories});
|
|
161
|
+
|
|
162
|
+
return result;
|
|
139
163
|
}
|
|
140
164
|
|
|
141
165
|
async function prepareNewPage() {
|
package/src/renderStory.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
|
|
2
3
|
const throat = require('throat');
|
|
4
|
+
const {EyesError} = require('@applitools/eyes');
|
|
3
5
|
const {storyToCheckSettings, storyToOpenSettings} = require('./transformSettings');
|
|
4
6
|
|
|
5
7
|
function makeRenderStory({
|
|
@@ -11,6 +13,7 @@ function makeRenderStory({
|
|
|
11
13
|
appName,
|
|
12
14
|
serverSettings,
|
|
13
15
|
concurrency,
|
|
16
|
+
signal = new AbortController().signal,
|
|
14
17
|
}) {
|
|
15
18
|
const throttle = throat(storyDataGap);
|
|
16
19
|
return function renderStory({story, snapshots, url}) {
|
|
@@ -24,7 +27,12 @@ function makeRenderStory({
|
|
|
24
27
|
|
|
25
28
|
return timeItAsync(baselineName, async () => {
|
|
26
29
|
const eyes = await openEyes({settings: openParams});
|
|
27
|
-
return new Promise((resolve, reject) => {
|
|
30
|
+
return new Promise(async (resolve, reject) => {
|
|
31
|
+
if (signal.aborted) {
|
|
32
|
+
return await abortStory();
|
|
33
|
+
} else {
|
|
34
|
+
signal.addEventListener('abort', abortStory);
|
|
35
|
+
}
|
|
28
36
|
throttle(async () => {
|
|
29
37
|
try {
|
|
30
38
|
if (snapshots) {
|
|
@@ -44,6 +52,18 @@ function makeRenderStory({
|
|
|
44
52
|
reject(err);
|
|
45
53
|
}
|
|
46
54
|
});
|
|
55
|
+
|
|
56
|
+
async function abortStory() {
|
|
57
|
+
logger.log('received abort signal for story', title);
|
|
58
|
+
|
|
59
|
+
// Inside core-base this will cause internal operations to be aborted
|
|
60
|
+
await eyes.abort({settings: {environments: checkParams.environments}});
|
|
61
|
+
|
|
62
|
+
// This will intentionally cause not to wait for results.
|
|
63
|
+
// Therefore there will be a "hanging" promise.
|
|
64
|
+
// But for the purpose of the addon, which is a long living process, it doesn't matter that we didn't stop the operation inside core.
|
|
65
|
+
reject(new EyesError(`${title} aborted after open ${signal.reason}`));
|
|
66
|
+
}
|
|
47
67
|
});
|
|
48
68
|
}).then(onDoneStory);
|
|
49
69
|
|
package/src/transformSettings.js
CHANGED
|
@@ -4,7 +4,7 @@ const fs = require('fs');
|
|
|
4
4
|
const detect = require('detect-port');
|
|
5
5
|
const {version: packageVersion} = require('../package.json');
|
|
6
6
|
const {
|
|
7
|
-
|
|
7
|
+
MissingApiKeyError,
|
|
8
8
|
missingAppNameAndPackageJsonFailMsg,
|
|
9
9
|
missingAppNameInPackageJsonFailMsg,
|
|
10
10
|
startStorybookFailMsg,
|
|
@@ -18,7 +18,7 @@ const utils = require('@applitools/utils');
|
|
|
18
18
|
|
|
19
19
|
async function validateAndPopulateConfig({config, packagePath = '', logger = makeLogger()}) {
|
|
20
20
|
if (!config.apiKey && !utils.general.getEnvValue('API_KEY')) {
|
|
21
|
-
throw new
|
|
21
|
+
throw new MissingApiKeyError();
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const packageJsonPath = `${packagePath}/package.json`;
|
|
@@ -62,7 +62,8 @@ async function validateAndPopulateConfig({config, packagePath = '', logger = mak
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
config.
|
|
65
|
+
const agentName = config.isAddon ? 'eyes-storybook-addon' : 'eyes-storybook';
|
|
66
|
+
config.agentId = `${agentName}/${packageVersion}`;
|
|
66
67
|
|
|
67
68
|
if (config.runInDocker) {
|
|
68
69
|
config.puppeteerOptions = config.puppeteerOptions || {};
|