@applitools/eyes-storybook 3.56.0 → 3.57.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 +70 -0
- package/dist/index.d.ts +39 -0
- package/package.json +14 -11
- package/src/eyes-setup.js +75 -78
- package/src/generateConfig.js +22 -6
- package/src/index.ts +35 -0
- package/src/utils/config-validator.js +116 -0
- package/src/validateAndPopulateConfig.js +6 -1
- package/src/types/types.ts +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.57.0](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.56.0...js/eyes-storybook@3.57.0) (2025-08-05)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* improve configuration handling ([#3130](https://github.com/Applitools-Dev/sdk/issues/3130)) ([def7be1](https://github.com/Applitools-Dev/sdk/commit/def7be1dd07460f49142cddfe55203baa884e6c3))
|
|
9
|
+
* release java ([7bc39e6](https://github.com/Applitools-Dev/sdk/commit/7bc39e679eab27a19322ca4b121177da7437c106))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Dependencies
|
|
13
|
+
|
|
14
|
+
* @applitools/utils bumped to 1.11.0
|
|
15
|
+
#### Features
|
|
16
|
+
|
|
17
|
+
* improve configuration handling ([#3130](https://github.com/Applitools-Dev/sdk/issues/3130)) ([def7be1](https://github.com/Applitools-Dev/sdk/commit/def7be1dd07460f49142cddfe55203baa884e6c3))
|
|
18
|
+
* make utils.general.guid crypto secured ([#3137](https://github.com/Applitools-Dev/sdk/issues/3137)) ([775df08](https://github.com/Applitools-Dev/sdk/commit/775df08307e41402a6603812205bc857bd3f936e))
|
|
19
|
+
* @applitools/eyes bumped to 1.36.0
|
|
20
|
+
#### Features
|
|
21
|
+
|
|
22
|
+
* improve configuration handling ([#3130](https://github.com/Applitools-Dev/sdk/issues/3130)) ([def7be1](https://github.com/Applitools-Dev/sdk/commit/def7be1dd07460f49142cddfe55203baa884e6c3))
|
|
23
|
+
* release java ([7bc39e6](https://github.com/Applitools-Dev/sdk/commit/7bc39e679eab27a19322ca4b121177da7437c106))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
* @applitools/snaptdout bumped to 1.1.0
|
|
28
|
+
#### Features
|
|
29
|
+
|
|
30
|
+
* release java ([7bc39e6](https://github.com/Applitools-Dev/sdk/commit/7bc39e679eab27a19322ca4b121177da7437c106))
|
|
31
|
+
* @applitools/test-server bumped to 1.3.0
|
|
32
|
+
#### Features
|
|
33
|
+
|
|
34
|
+
* release java ([7bc39e6](https://github.com/Applitools-Dev/sdk/commit/7bc39e679eab27a19322ca4b121177da7437c106))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
* @applitools/logger bumped to 2.2.1
|
|
39
|
+
|
|
40
|
+
* @applitools/dom-snapshot bumped to 4.13.1
|
|
41
|
+
|
|
42
|
+
* @applitools/socket bumped to 1.3.1
|
|
43
|
+
|
|
44
|
+
* @applitools/req bumped to 1.8.1
|
|
45
|
+
|
|
46
|
+
* @applitools/image bumped to 1.2.1
|
|
47
|
+
|
|
48
|
+
* @applitools/dom-capture bumped to 11.6.1
|
|
49
|
+
|
|
50
|
+
* @applitools/driver bumped to 1.23.1
|
|
51
|
+
|
|
52
|
+
* @applitools/spec-driver-webdriver bumped to 1.4.1
|
|
53
|
+
|
|
54
|
+
* @applitools/spec-driver-selenium bumped to 1.7.1
|
|
55
|
+
|
|
56
|
+
* @applitools/spec-driver-puppeteer bumped to 1.6.1
|
|
57
|
+
|
|
58
|
+
* @applitools/screenshoter bumped to 3.12.1
|
|
59
|
+
|
|
60
|
+
* @applitools/nml-client bumped to 1.11.1
|
|
61
|
+
|
|
62
|
+
* @applitools/tunnel-client bumped to 1.10.2
|
|
63
|
+
|
|
64
|
+
* @applitools/ufg-client bumped to 1.17.1
|
|
65
|
+
|
|
66
|
+
* @applitools/core-base bumped to 1.27.1
|
|
67
|
+
|
|
68
|
+
* @applitools/ec-client bumped to 1.12.2
|
|
69
|
+
|
|
70
|
+
* @applitools/core bumped to 4.44.2
|
|
71
|
+
|
|
72
|
+
|
|
3
73
|
## [3.56.0](https://github.com/Applitools-Dev/sdk/compare/js/eyes-storybook@3.55.9...js/eyes-storybook@3.56.0) (2025-07-23)
|
|
4
74
|
|
|
5
75
|
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Configuration, DesktopBrowserInfo, ChromeEmulationInfo, IOSDeviceInfo, IOSMultiDeviceInfo } from '@applitools/eyes';
|
|
2
|
+
/**
|
|
3
|
+
* https://applitools.com/tutorials/sdks/storybook/config
|
|
4
|
+
*/
|
|
5
|
+
export type ApplitoolsConfig = Omit<Configuration, 'waitBeforeScreenshots'> & {
|
|
6
|
+
storybookUrl?: string;
|
|
7
|
+
storybookPort?: number;
|
|
8
|
+
storybookHost?: string;
|
|
9
|
+
storybookConfigDir?: string;
|
|
10
|
+
storybookStaticDir?: string;
|
|
11
|
+
showStorybookOutput?: boolean;
|
|
12
|
+
runInDocker?: boolean;
|
|
13
|
+
include?: ((story: {
|
|
14
|
+
name: string;
|
|
15
|
+
kind: string;
|
|
16
|
+
storyTitle?: string;
|
|
17
|
+
parameters?: any;
|
|
18
|
+
}) => boolean) | string | RegExp;
|
|
19
|
+
variations?: Record<string, any>;
|
|
20
|
+
readStoriesTimeout?: number;
|
|
21
|
+
puppeteerOptions?: Record<string, any>;
|
|
22
|
+
puppeteerExtraHTTPHeaders?: Record<string, string>;
|
|
23
|
+
navigationWaitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
|
|
24
|
+
browserCacheRequests?: boolean;
|
|
25
|
+
browser?: (DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)[];
|
|
26
|
+
envName?: string;
|
|
27
|
+
testConcurrency?: number;
|
|
28
|
+
showLogs?: boolean;
|
|
29
|
+
exitcode?: boolean;
|
|
30
|
+
ignoreRegions?: any[];
|
|
31
|
+
floatingRegions?: any[];
|
|
32
|
+
layoutRegions?: any[];
|
|
33
|
+
strictRegions?: any[];
|
|
34
|
+
contentRegions?: any[];
|
|
35
|
+
accessibilityRegions?: any[];
|
|
36
|
+
jsonFilePath?: string;
|
|
37
|
+
tapFilePath?: string;
|
|
38
|
+
xmlFilePath?: string;
|
|
39
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-storybook",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.57.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"applitools",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"homepage": "https://applitools.com/tutorials/sdks/storybook",
|
|
15
15
|
"license": "SEE LICENSE IN LICENSE",
|
|
16
16
|
"author": "Applitools Team <team@applitools.com>",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
17
18
|
"bin": {
|
|
18
19
|
"eyes-setup": "./bin/eyes-setup.js",
|
|
19
20
|
"eyes-storybook": "./bin/eyes-storybook.js"
|
|
@@ -25,7 +26,8 @@
|
|
|
25
26
|
],
|
|
26
27
|
"scripts": {
|
|
27
28
|
"lint": "run --top-level eslint '**/*.js'",
|
|
28
|
-
"build": "
|
|
29
|
+
"build:types": "tsc --project tsconfig.types.json",
|
|
30
|
+
"build": "rollup -c rollup.config.js && yarn build:types",
|
|
29
31
|
"build:heavy": "node scripts/bitmap.js",
|
|
30
32
|
"test": "yarn build && yarn test:mocha",
|
|
31
33
|
"test:mocha": "run --top-level mocha 'test/{unit,it,e2e}/*.test.js'",
|
|
@@ -56,15 +58,15 @@
|
|
|
56
58
|
"up:framework": "cd test/fixtures/storybook-versions/${APPLITOOLS_FRAMEWORK_VERSION} && npm ci"
|
|
57
59
|
},
|
|
58
60
|
"dependencies": {
|
|
59
|
-
"@applitools/core": "4.
|
|
60
|
-
"@applitools/driver": "1.
|
|
61
|
-
"@applitools/eyes": "1.
|
|
61
|
+
"@applitools/core": "4.44.2",
|
|
62
|
+
"@applitools/driver": "1.23.1",
|
|
63
|
+
"@applitools/eyes": "1.36.0",
|
|
62
64
|
"@applitools/functional-commons": "1.6.0",
|
|
63
|
-
"@applitools/logger": "2.1
|
|
65
|
+
"@applitools/logger": "2.2.1",
|
|
64
66
|
"@applitools/monitoring-commons": "1.0.19",
|
|
65
|
-
"@applitools/spec-driver-puppeteer": "1.
|
|
66
|
-
"@applitools/ufg-client": "1.
|
|
67
|
-
"@applitools/utils": "1.
|
|
67
|
+
"@applitools/spec-driver-puppeteer": "1.6.1",
|
|
68
|
+
"@applitools/ufg-client": "1.17.1",
|
|
69
|
+
"@applitools/utils": "1.11.0",
|
|
68
70
|
"@inquirer/prompts": "7.0.1",
|
|
69
71
|
"boxen": "4.2.0",
|
|
70
72
|
"chalk": "3.0.0",
|
|
@@ -79,8 +81,8 @@
|
|
|
79
81
|
},
|
|
80
82
|
"devDependencies": {
|
|
81
83
|
"@applitools/bongo": "^5.10.0",
|
|
82
|
-
"@applitools/snaptdout": "^1.
|
|
83
|
-
"@applitools/test-server": "^1.
|
|
84
|
+
"@applitools/snaptdout": "^1.1.0",
|
|
85
|
+
"@applitools/test-server": "^1.3.0",
|
|
84
86
|
"@applitools/test-utils": "^1.5.17",
|
|
85
87
|
"@storybook/addon-interactions": "^6.4.18",
|
|
86
88
|
"@storybook/react": "^6.5.16",
|
|
@@ -96,6 +98,7 @@
|
|
|
96
98
|
"react-dom": "^16.12.0",
|
|
97
99
|
"rollup": "^1.28.0",
|
|
98
100
|
"rollup-plugin-commonjs": "^10.1.0",
|
|
101
|
+
"typescript": "^5.3.3",
|
|
99
102
|
"ua-parser-js": "^0.7.21"
|
|
100
103
|
},
|
|
101
104
|
"engines": {
|
package/src/eyes-setup.js
CHANGED
|
@@ -40,50 +40,59 @@ function handleError(asyncFunc) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
async function init(args) {
|
|
43
|
-
let shouldUpdate = true;
|
|
44
|
-
let fileName;
|
|
45
|
-
|
|
46
43
|
log(chalk.yellow('Setting up Eyes-Storybook for your project:'));
|
|
47
44
|
|
|
48
|
-
let config = await loadExistingConfig();
|
|
49
|
-
if (config) {
|
|
50
|
-
shouldUpdate = false;
|
|
51
|
-
// this show a warning if the apiKey is actually 'process.env.APPLITOOLS_API_KEY' in the config file since we load it
|
|
52
|
-
// if (config.apiKey !== 'process.env.APPLITOOLS_API_KEY') {
|
|
53
|
-
// console.log(config.apiKey)
|
|
54
|
-
// log(
|
|
55
|
-
// chalk.yellow(
|
|
56
|
-
// `Detected 'apiKey' is not obscured. It is recommended to set this via environment variable APPLITOOLS_API_KEY.`,
|
|
57
|
-
// ),
|
|
58
|
-
// );
|
|
59
|
-
// }
|
|
60
|
-
}
|
|
45
|
+
let {config, fileName, isCorrupted} = await loadExistingConfig();
|
|
61
46
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
shouldUseEnvServerUrl = false,
|
|
66
|
-
warnForApiKey = false;
|
|
67
|
-
if (shouldUpdate && utils.general.getEnvValue('API_KEY')) {
|
|
68
|
-
shouldUseEnvApiKey = await confirm({
|
|
47
|
+
if (isCorrupted) {
|
|
48
|
+
log(chalk.yellow(`\nWarning: Your configuration file '${fileName}' appears to be corrupted.`));
|
|
49
|
+
const shouldOverwrite = await confirm({
|
|
69
50
|
message:
|
|
70
|
-
'
|
|
51
|
+
'Would you like to create a new one? This will replace the corrupted file (Default Yes):',
|
|
71
52
|
default: true,
|
|
72
53
|
});
|
|
73
|
-
|
|
74
|
-
|
|
54
|
+
|
|
55
|
+
if (!shouldOverwrite) {
|
|
56
|
+
log('Aborting setup. Please fix your configuration file manually or remove it.');
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
// By letting this block finish, the script proceeds as if no config was found
|
|
75
60
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
61
|
+
|
|
62
|
+
// If no config exists or is corrupted, run the interactive setup
|
|
63
|
+
let apiKey,
|
|
64
|
+
serverUrl,
|
|
65
|
+
warnForApiKey = false;
|
|
66
|
+
|
|
67
|
+
let shouldUpdate = !config;
|
|
68
|
+
if (shouldUpdate) {
|
|
69
|
+
let shouldUseEnvApiKey = false;
|
|
70
|
+
if (utils.general.getEnvValue('API_KEY')) {
|
|
71
|
+
shouldUseEnvApiKey = await confirm({
|
|
72
|
+
message:
|
|
73
|
+
'Detected APPLITOOLS_API_KEY environment variable. Would you like it to be used? (default Yes):',
|
|
80
74
|
default: true,
|
|
81
75
|
});
|
|
82
|
-
|
|
76
|
+
if (shouldUseEnvApiKey) {
|
|
77
|
+
apiKey = 'process.env.APPLITOOLS_API_KEY';
|
|
78
|
+
}
|
|
79
|
+
warnForApiKey = !shouldUseEnvApiKey; // Warn if the user has an env var but doesn't use it
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let shouldUseEnvServerUrl = false;
|
|
83
|
+
for (const url of ['EYES_SERVER_URL', 'SERVER_URL']) {
|
|
84
|
+
if (utils.general.getEnvValue(url)) {
|
|
85
|
+
shouldUseEnvServerUrl = await confirm({
|
|
86
|
+
message: `Detected APPLITOOLS_${url} environment variable. Would you like it to be used? (default Yes):`,
|
|
87
|
+
default: true,
|
|
88
|
+
});
|
|
89
|
+
if (shouldUseEnvServerUrl) {
|
|
90
|
+
serverUrl = `process.env.APPLITOOLS_${url}`;
|
|
91
|
+
break; // Use the first one found
|
|
92
|
+
}
|
|
93
|
+
}
|
|
83
94
|
}
|
|
84
|
-
}
|
|
85
95
|
|
|
86
|
-
if (shouldUpdate) {
|
|
87
96
|
if (!shouldUseEnvApiKey) {
|
|
88
97
|
apiKey =
|
|
89
98
|
args.apiKey ??
|
|
@@ -91,8 +100,9 @@ async function init(args) {
|
|
|
91
100
|
message:
|
|
92
101
|
'Enter your API key (https://applitools.com/docs/topics/overview/obtain-api-key.html):',
|
|
93
102
|
}));
|
|
94
|
-
warnForApiKey = apiKey !== ''; //
|
|
103
|
+
warnForApiKey = apiKey !== ''; // Warn if the user provided any API key directly
|
|
95
104
|
}
|
|
105
|
+
|
|
96
106
|
if (!shouldUseEnvServerUrl) {
|
|
97
107
|
serverUrl =
|
|
98
108
|
args.serverUrl ??
|
|
@@ -102,7 +112,7 @@ async function init(args) {
|
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
config = {
|
|
105
|
-
...config,
|
|
115
|
+
...(config || {}),
|
|
106
116
|
appName: 'My Storybook App',
|
|
107
117
|
batchName: 'My Storybook',
|
|
108
118
|
showLogs: false,
|
|
@@ -114,6 +124,8 @@ async function init(args) {
|
|
|
114
124
|
|
|
115
125
|
printPostlude();
|
|
116
126
|
|
|
127
|
+
// --- Helper Functions ---
|
|
128
|
+
|
|
117
129
|
async function loadExistingConfig() {
|
|
118
130
|
const configFiles = [
|
|
119
131
|
'applitools.config.js',
|
|
@@ -123,21 +135,24 @@ async function init(args) {
|
|
|
123
135
|
];
|
|
124
136
|
|
|
125
137
|
for (const file of configFiles) {
|
|
126
|
-
fileName = file;
|
|
127
138
|
try {
|
|
128
|
-
await fs.access(file);
|
|
129
139
|
const fileUrl = pathToFileURL(file).href;
|
|
130
|
-
const module = await import(fileUrl);
|
|
131
|
-
|
|
140
|
+
const module = await import(`${fileUrl}?t=${Date.now()}`); // Append timestamp to bypass cache
|
|
141
|
+
|
|
142
|
+
return {config: module.default || module, fileName: file, isCorrupted: false};
|
|
132
143
|
} catch (err) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
144
|
+
if (err.code === 'ERR_MODULE_NOT_FOUND') {
|
|
145
|
+
// This file doesn't exist, so we continue searching for the one that does.
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return {config: null, fileName: file, isCorrupted: true};
|
|
136
150
|
}
|
|
137
151
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return
|
|
152
|
+
|
|
153
|
+
// No file was found in any of the possible locations.
|
|
154
|
+
// We return a default filename for a new file to be created.
|
|
155
|
+
return {config: null, fileName: 'applitools.config.js', isCorrupted: false};
|
|
141
156
|
}
|
|
142
157
|
|
|
143
158
|
function generateConfigContent() {
|
|
@@ -170,11 +185,9 @@ async function init(args) {
|
|
|
170
185
|
configLines.push(`serverUrl: ${serverUrl},`);
|
|
171
186
|
} else if (serverUrl) {
|
|
172
187
|
configLines.push(`serverUrl: '${serverUrl}',`);
|
|
173
|
-
} else {
|
|
174
|
-
configLines.push(`// serverUrl: '',`);
|
|
175
188
|
}
|
|
176
189
|
|
|
177
|
-
// Handle other config lines
|
|
190
|
+
// Handle other config lines by prioritizing env vars over defaults
|
|
178
191
|
const otherKeys = [
|
|
179
192
|
'appName',
|
|
180
193
|
'batchName',
|
|
@@ -184,12 +197,22 @@ async function init(args) {
|
|
|
184
197
|
'proxy',
|
|
185
198
|
'notifyOnCompletion',
|
|
186
199
|
'concurrentTabs',
|
|
200
|
+
'navigationWaitUntil',
|
|
201
|
+
'waitBeforeCapture',
|
|
187
202
|
];
|
|
188
203
|
|
|
189
204
|
for (const key of otherKeys) {
|
|
190
|
-
const
|
|
191
|
-
if
|
|
192
|
-
|
|
205
|
+
const envVar = envConfigMap[key];
|
|
206
|
+
// Check if an environment variable for this key is set
|
|
207
|
+
if (envVar && utils.general.getEnvValue(envVar.replace('APPLITOOLS_', ''))) {
|
|
208
|
+
configLines.push(`${key}: process.env.${envVar},`);
|
|
209
|
+
} else if (Object.prototype.hasOwnProperty.call(config, key)) {
|
|
210
|
+
// Otherwise, use the default value from the config object
|
|
211
|
+
const value = config[key];
|
|
212
|
+
if (value !== undefined) {
|
|
213
|
+
const line = typeof value === 'string' ? `${key}: '${value}',` : `${key}: ${value},`;
|
|
214
|
+
configLines.push(line);
|
|
215
|
+
}
|
|
193
216
|
}
|
|
194
217
|
}
|
|
195
218
|
|
|
@@ -206,32 +229,6 @@ module.exports = {
|
|
|
206
229
|
// ]
|
|
207
230
|
};
|
|
208
231
|
`;
|
|
209
|
-
|
|
210
|
-
function getConfigLine(key, override = undefined) {
|
|
211
|
-
const envVar = envConfigMap[key];
|
|
212
|
-
if (override) {
|
|
213
|
-
return config[key];
|
|
214
|
-
}
|
|
215
|
-
if (utils.types.isArray(envVar)) {
|
|
216
|
-
for (const v of envVar) {
|
|
217
|
-
if (utils.general.getEnvValue(v.replace('APPLITOOLS_', ''))) {
|
|
218
|
-
return `${key}: process.env.${v},`;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
} else if (envVar && utils.general.getEnvValue(envVar.replace('APPLITOOLS_', ''))) {
|
|
222
|
-
return `${key}: process.env.${envVar},`;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Check if the key exists in the config object before using its value.
|
|
226
|
-
// Using Object.prototype.hasOwnProperty.call is a safe way to check.
|
|
227
|
-
if (Object.prototype.hasOwnProperty.call(config, key)) {
|
|
228
|
-
const value = config[key];
|
|
229
|
-
// Format the value based on its type.
|
|
230
|
-
return typeof value === 'string' ? `${key}: '${value}',` : `${key}: ${value},`;
|
|
231
|
-
} else {
|
|
232
|
-
return '';
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
232
|
}
|
|
236
233
|
|
|
237
234
|
function printPostlude() {
|
|
@@ -256,7 +253,7 @@ module.exports = {
|
|
|
256
253
|
if (warnForApiKey) {
|
|
257
254
|
log(
|
|
258
255
|
chalk.yellow(
|
|
259
|
-
'
|
|
256
|
+
'\nWarning: Consider setting your API key via the APPLITOOLS_API_KEY environment variable.',
|
|
260
257
|
),
|
|
261
258
|
);
|
|
262
259
|
}
|
package/src/generateConfig.js
CHANGED
|
@@ -10,12 +10,7 @@ function generateConfig({argv = {}, defaultConfig = {}, externalConfigParams = [
|
|
|
10
10
|
const defaultConfigParams = Object.keys(defaultConfig);
|
|
11
11
|
const configPaths = argv.conf ? [resolve(process.cwd(), argv.conf)] : undefined;
|
|
12
12
|
const configParams = uniq(defaultConfigParams.concat(externalConfigParams));
|
|
13
|
-
const config =
|
|
14
|
-
paths: configPaths,
|
|
15
|
-
params: configParams,
|
|
16
|
-
strict: true,
|
|
17
|
-
traverse: false,
|
|
18
|
-
});
|
|
13
|
+
const config = getAndParseConfig({configPaths, configParams});
|
|
19
14
|
const argvConfig = lodash.pick(argv, configParams);
|
|
20
15
|
const result = Object.assign({}, defaultConfig, config, argvConfig);
|
|
21
16
|
|
|
@@ -86,6 +81,27 @@ function generateConfig({argv = {}, defaultConfig = {}, externalConfigParams = [
|
|
|
86
81
|
return result;
|
|
87
82
|
}
|
|
88
83
|
|
|
84
|
+
function getAndParseConfig({configPaths, configParams}) {
|
|
85
|
+
try {
|
|
86
|
+
return utils.config.getConfig({
|
|
87
|
+
paths: configPaths,
|
|
88
|
+
params: configParams,
|
|
89
|
+
strict: true,
|
|
90
|
+
traverse: false,
|
|
91
|
+
});
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (error.message.includes('Could not find configuration file')) {
|
|
94
|
+
return utils.config.populateConfigParams({config: {}, params: configParams});
|
|
95
|
+
}
|
|
96
|
+
const documentationUrl = 'https://applitools.com/tutorials/sdks/storybook/config#properties';
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Your configuration file is invalid. Please review our documentation for valid configuration settings: ${documentationUrl}.
|
|
99
|
+
Additionally, you can generate a new configuration by running 'npx eyes-setup'.
|
|
100
|
+
\n\nError details: ${error.message}`.trim(),
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
89
105
|
function transformConfig(result) {
|
|
90
106
|
transformLayoutBreakpoints(result);
|
|
91
107
|
transformBrowser(result);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type {Configuration, DesktopBrowserInfo, ChromeEmulationInfo, IOSDeviceInfo, IOSMultiDeviceInfo} from '@applitools/eyes'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* https://applitools.com/tutorials/sdks/storybook/config
|
|
5
|
+
*/
|
|
6
|
+
export type ApplitoolsConfig = Omit<Configuration, 'waitBeforeScreenshots'> & {
|
|
7
|
+
storybookUrl?: string;
|
|
8
|
+
storybookPort?: number;
|
|
9
|
+
storybookHost?: string;
|
|
10
|
+
storybookConfigDir?: string;
|
|
11
|
+
storybookStaticDir?: string;
|
|
12
|
+
showStorybookOutput?: boolean;
|
|
13
|
+
runInDocker?: boolean;
|
|
14
|
+
include?: ((story: { name: string; kind: string; storyTitle?: string; parameters?: any }) => boolean) | string | RegExp;
|
|
15
|
+
variations?: Record<string, any>;
|
|
16
|
+
readStoriesTimeout?: number;
|
|
17
|
+
puppeteerOptions?: Record<string, any>;
|
|
18
|
+
puppeteerExtraHTTPHeaders?: Record<string, string>;
|
|
19
|
+
navigationWaitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
|
|
20
|
+
browserCacheRequests?: boolean;
|
|
21
|
+
browser?: (DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)[];
|
|
22
|
+
envName?: string;
|
|
23
|
+
testConcurrency?: number;
|
|
24
|
+
showLogs?: boolean;
|
|
25
|
+
exitcode?: boolean;
|
|
26
|
+
ignoreRegions?: any[];
|
|
27
|
+
floatingRegions?: any[];
|
|
28
|
+
layoutRegions?: any[];
|
|
29
|
+
strictRegions?: any[];
|
|
30
|
+
contentRegions?: any[];
|
|
31
|
+
accessibilityRegions?: any[];
|
|
32
|
+
jsonFilePath?: string;
|
|
33
|
+
tapFilePath?: string;
|
|
34
|
+
xmlFilePath?: string;
|
|
35
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const {Configuration} = require('@applitools/eyes');
|
|
4
|
+
|
|
5
|
+
// Get all keys directly from the base Configuration class
|
|
6
|
+
const dynamicBaseKeys = [
|
|
7
|
+
...Object.getOwnPropertyNames(Object.getPrototypeOf(new Configuration())),
|
|
8
|
+
].filter(
|
|
9
|
+
prop =>
|
|
10
|
+
!prop.startsWith('get') &&
|
|
11
|
+
!prop.startsWith('set') &&
|
|
12
|
+
!prop.startsWith('to') &&
|
|
13
|
+
!prop.startsWith('_') &&
|
|
14
|
+
prop !== 'constructor',
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// known aliases that are not on the Configuration prototype
|
|
18
|
+
const knownAliases = [
|
|
19
|
+
'envName',
|
|
20
|
+
'testConcurrency',
|
|
21
|
+
'concurrency',
|
|
22
|
+
'eyesServerUrl',
|
|
23
|
+
'batchId',
|
|
24
|
+
'batchName',
|
|
25
|
+
'batchSequenceName',
|
|
26
|
+
'keepBatchOpen',
|
|
27
|
+
'environments',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const applitoolsBaseKeys = [...dynamicBaseKeys, ...knownAliases];
|
|
31
|
+
|
|
32
|
+
// A list of all keys specific to the eyes-storybook package.
|
|
33
|
+
const storybookSpecificKeys = [
|
|
34
|
+
'storybookPort',
|
|
35
|
+
'storybookHost',
|
|
36
|
+
'storybookConfigDir',
|
|
37
|
+
'storybookUrl',
|
|
38
|
+
'storybookStaticDir',
|
|
39
|
+
'showStorybookOutput',
|
|
40
|
+
'exitcode',
|
|
41
|
+
'include',
|
|
42
|
+
'variations',
|
|
43
|
+
'runInDocker',
|
|
44
|
+
'readStoriesTimeout',
|
|
45
|
+
'reloadPagePerStory',
|
|
46
|
+
'startStorybookServerTimeout',
|
|
47
|
+
|
|
48
|
+
// Browser & Puppeteer Control
|
|
49
|
+
'browser',
|
|
50
|
+
'puppeteerOptions',
|
|
51
|
+
'puppeteerExtraHTTPHeaders',
|
|
52
|
+
'navigationWaitUntil',
|
|
53
|
+
'networkBlockPatterns',
|
|
54
|
+
'browserRequestsTimeout',
|
|
55
|
+
'browserHeadersOverride',
|
|
56
|
+
'browserCacheRequests',
|
|
57
|
+
|
|
58
|
+
// Region Matching
|
|
59
|
+
'ignoreRegions',
|
|
60
|
+
'floatingRegions',
|
|
61
|
+
'layoutRegions',
|
|
62
|
+
'strictRegions',
|
|
63
|
+
'contentRegions',
|
|
64
|
+
'accessibilityRegions',
|
|
65
|
+
|
|
66
|
+
// Reporting
|
|
67
|
+
'tapFilePath',
|
|
68
|
+
'xmlFilePath',
|
|
69
|
+
'jsonFilePath',
|
|
70
|
+
|
|
71
|
+
// Legacy & Internal
|
|
72
|
+
'waitBeforeScreenshot', // backward compatibility
|
|
73
|
+
'waitBeforeScreenshots', // backward compatibility
|
|
74
|
+
'waitBeforeCapture',
|
|
75
|
+
'fakeIE',
|
|
76
|
+
'storyConfiguration',
|
|
77
|
+
'storyDataGap',
|
|
78
|
+
'packagePath',
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
// Combine all known keys into a single Set for efficient O(1) lookups.
|
|
82
|
+
const knownKeys = new Set([...storybookSpecificKeys, ...applitoolsBaseKeys]);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Checks the user's config object for any keys that are not recognized
|
|
86
|
+
* and logs a warning to the console if any are found.
|
|
87
|
+
* @param {object} config - The user's configuration object.
|
|
88
|
+
* @param {object} logger - The logger instance.
|
|
89
|
+
*/
|
|
90
|
+
function logUnrecognizedKeys(config, logger) {
|
|
91
|
+
const unrecognizedKeys = Object.keys(config).filter(key => !knownKeys.has(key));
|
|
92
|
+
|
|
93
|
+
if (unrecognizedKeys.length > 0) {
|
|
94
|
+
// uses a warning sign emoji - ⚠️
|
|
95
|
+
console.log(
|
|
96
|
+
chalk.yellow(
|
|
97
|
+
`\n\u26A0 The following configuration keys are unrecognized and will be ignored:`,
|
|
98
|
+
),
|
|
99
|
+
);
|
|
100
|
+
unrecognizedKeys.forEach(key => {
|
|
101
|
+
console.log(chalk.yellow(` - ${key}`));
|
|
102
|
+
});
|
|
103
|
+
logger.log('\n');
|
|
104
|
+
|
|
105
|
+
const docsUrl = 'https://applitools.com/tutorials/sdks/storybook/config#properties';
|
|
106
|
+
console.log(
|
|
107
|
+
chalk.bold(`Please review our documentation for valid configuration settings: ${docsUrl}`),
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = {
|
|
113
|
+
logUnrecognizedKeys,
|
|
114
|
+
// Exporting the set is optional but can be useful for other utilities
|
|
115
|
+
knownKeys,
|
|
116
|
+
};
|
|
@@ -13,9 +13,11 @@ const startStorybookServer = require('./startStorybookServer');
|
|
|
13
13
|
const {isIE} = require('./shouldRenderIE');
|
|
14
14
|
const {makeLogger} = require('@applitools/logger');
|
|
15
15
|
const determineStorybookVersion = require('./utils/determineStorybookVersion');
|
|
16
|
+
const {logUnrecognizedKeys} = require('./utils/config-validator');
|
|
17
|
+
const utils = require('@applitools/utils');
|
|
16
18
|
|
|
17
19
|
async function validateAndPopulateConfig({config, packagePath = '', logger = makeLogger()}) {
|
|
18
|
-
if (!config.apiKey) {
|
|
20
|
+
if (!config.apiKey && !utils.general.getEnvValue('API_KEY')) {
|
|
19
21
|
throw new Error(missingApiKeyFailMsg);
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -77,5 +79,8 @@ async function validateAndPopulateConfig({config, packagePath = '', logger = mak
|
|
|
77
79
|
),
|
|
78
80
|
);
|
|
79
81
|
}
|
|
82
|
+
|
|
83
|
+
logUnrecognizedKeys(config, logger);
|
|
80
84
|
}
|
|
85
|
+
|
|
81
86
|
module.exports = validateAndPopulateConfig;
|
package/src/types/types.ts
DELETED