@applitools/eyes-storybook 3.27.2 → 3.27.5
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 +27 -0
- package/README.md +7 -5
- package/package.json +14 -13
- package/src/cli.js +1 -0
- package/src/getIframeUrl.js +6 -2
- package/src/getStoryData.js +10 -9
- package/src/getStoryUrl.js +12 -8
- package/src/processResults.js +40 -18
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 3.27.5 - 2022/3/29
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
- Preserve search parameters in Storybook URLs
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
## 3.27.4 - 2022/2/9
|
|
12
|
+
|
|
13
|
+
- updated to @applitools/driver@1.4.9 (from 1.4.7)
|
|
14
|
+
- updated to @applitools/eyes-sdk-core@13.0.0 (from 12.24.9)
|
|
15
|
+
- updated to @applitools/logger@1.0.9 (from 1.0.8)
|
|
16
|
+
- updated to @applitools/visual-grid-client@15.8.62 (from 15.8.55)
|
|
17
|
+
- support adding new test(s) and the value of saveNewTest is false will warn
|
|
18
|
+
- README.md update default value of 'exitcode' to 'true' (from 'false')
|
|
19
|
+
- updated to @applitools/driver@1.4.12 (from 1.4.9)
|
|
20
|
+
- updated to @applitools/eyes-sdk-core@13.0.2 (from 13.0.0)
|
|
21
|
+
- updated to @applitools/logger@1.0.10 (from 1.0.9)
|
|
22
|
+
- updated to @applitools/visual-grid-client@15.8.63 (from 15.8.62)
|
|
23
|
+
- updated to @applitools/utils@1.2.12 (from 1.2.11)
|
|
24
|
+
|
|
25
|
+
## 3.27.3 - 2022/1/26
|
|
26
|
+
|
|
27
|
+
- avoid unwanted page reloading due to unknown query parameters
|
|
28
|
+
- updated to @applitools/driver@1.4.9 (from 1.4.7)
|
|
29
|
+
- updated to @applitools/eyes-sdk-core@13.0.0 (from 12.24.9)
|
|
30
|
+
- updated to @applitools/logger@1.0.9 (from 1.0.8)
|
|
31
|
+
- updated to @applitools/visual-grid-client@15.8.62 (from 15.8.55)
|
|
5
32
|
|
|
6
33
|
## 3.27.2 - 2021/12/23
|
|
7
34
|
|
package/README.md
CHANGED
|
@@ -153,12 +153,15 @@ In addition to command-line arguments, it's possible to define the following con
|
|
|
153
153
|
| `storybookStaticDir` | undefined | Path to Storybook's static files folder (also available as command-line argument). |
|
|
154
154
|
| `showStorybookOutput` | undefined | Whether or not you want to see Storybook output (also available as command-line argument). |
|
|
155
155
|
| `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.|
|
|
156
|
-
| `exitcode` |
|
|
156
|
+
| `exitcode` | true | If tests failed close with non-zero exit code (also available as command-line argument). |
|
|
157
157
|
| `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).|
|
|
158
158
|
| `showLogs` | false | Whether or not you want to see logs of the Eyes-Storybook plugin. |
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
159
|
+
| `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. |
|
|
160
|
+
| `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). |
|
|
161
|
+
| `batch.name` | The name of the first test in the batch | Provides a name to the batch (for display purpose only). |
|
|
162
|
+
| `batch.sequenceName` | undefined | Name for managing batch statistics. |
|
|
163
|
+
| `batch.notifyOnCompletion` | false | If `true` batch completion notifications are sent. |
|
|
164
|
+
| `batch.properties` | undefined | Custom properties for the entire batch. The format is an array of objects with name/value properties. For example: `[{name: 'My prop', value:'My value'}]`. |
|
|
162
165
|
| `baselineEnvName` | undefined | The name of the environment of the baseline. |
|
|
163
166
|
| `envName` | undefined | A name for the environment in which the application under test is running. |
|
|
164
167
|
| `ignoreCaret` | false | Whether to ignore or the blinking caret or not when comparing images. |
|
|
@@ -180,7 +183,6 @@ In addition to command-line arguments, it's possible to define the following con
|
|
|
180
183
|
| `waitBeforeCapture` | undefined | Selector, function or timeout.<br/>If ```number``` then the argument is treated as time in milliseconds to wait before all screenshots.<br/>If ```string``` then the argument is treated as a selector for elements to wait for before all screenshots.<br/>If ```function```, then the argument is treated as a predicate to wait for before all screenshots.<br/><hr/>For per component configuration see [waitBeforeCapture.](#waitBeforeCapture)<br/>Note that we use Puppeteer's [page.waitForTimeout()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitfortimeoutmilliseconds), [page.waitForSelector()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforselectorselector-options), [page.waitForXPath()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforxpathxpath-options) and [page.waitForFunction()](https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pagewaitforfunctionpagefunction-options-args), checkout it's API for more details. |
|
|
181
184
|
| `include` | true | A predicate function, a string or a regular expression specifying which stories should be visually tested.<br/>Visual baselines will be created only for the components specified.<br/>The function receives an object with ```name```, ```kind```, ```storyTitle``` and ```parameters``` properties.<br/>For example (exclude all stories with a name that start with [SKIP]):<br/>```({name, kind, storyTitle, parameters}) => !/^\[SKIP\]/.test(name)```<br/>For more information, see [per component configuration - include](#include). |
|
|
182
185
|
| `variations` | undefined | Specifies additional variations for all or some of the stories. For example, RTL. For more information, see [per component configuration - variations](#variations).|
|
|
183
|
-
| `notifyOnCompletion` | false | If `true` batch completion notifications are sent. |
|
|
184
186
|
| `dontCloseBatches` | false | If true, batches are not closed for notifyOnCompletion.|
|
|
185
187
|
| `testConcurrency` | 5 | The maximum number of tests that can run concurrently. The default value is the allowed amount for free accounts. For paid accounts, set this number to the quota set for your account. |
|
|
186
188
|
| `readStoriesTimeout` | 60000 | The amount of time (in milliseconds) Eyes-Storybook waits for storybook to load. For old storybook versions 2 and 3, this is also the time it takes for Eyes-Storybook to acknowledge it is working on those versions. So it is recommended to make this value small (e.g. 3000) when working with Storybook version 2 or 3. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/eyes-storybook",
|
|
3
|
-
"version": "3.27.
|
|
3
|
+
"version": "3.27.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=8.6.0"
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"test": "yarn build && yarn test:mocha && yarn lint",
|
|
18
|
-
"test:mocha": "
|
|
19
|
-
"test:unit": "mocha --no-timeouts --trace-warnings 'test/unit/*.test.js'",
|
|
20
|
-
"test:it": "mocha --no-timeouts --trace-warnings 'test/it/*.test.js'",
|
|
18
|
+
"test:mocha": "yarn test:unit && yarn test:it && yarn test:e2e",
|
|
19
|
+
"test:unit": "STDOUT_LEVEL=0 mocha --no-timeouts --trace-warnings 'test/unit/*.test.js'",
|
|
20
|
+
"test:it": "STDOUT_LEVEL=1 mocha --no-timeouts --trace-warnings 'test/it/*.test.js'",
|
|
21
21
|
"test:e2e": "mocha --no-timeouts --trace-warnings 'test/e2e/*.test.js'",
|
|
22
22
|
"build": "rollup -c rollup.config.js",
|
|
23
23
|
"build:heavy": "node scripts/bitmap.js",
|
|
@@ -34,9 +34,10 @@
|
|
|
34
34
|
"changelog": "git changelog -x -p -f v$npm_package_version > History.md && git add ./History.md && git commit -am 'changelog'",
|
|
35
35
|
"changelog:init": "git config changelog.format \"* %s [[%h]($(echo $npm_package_repository_url|cut -d+ -f2|cut -d. -f1-2)/commit/%H)]\"",
|
|
36
36
|
"changelog:install": "sudo apt-get install git-extras",
|
|
37
|
+
"gh:publish": "gh workflow run publish-storybook.yml --ref $(git rev-parse --abbrev-ref HEAD)",
|
|
37
38
|
"postinstall": "node src/postinstall",
|
|
38
|
-
"preversion": "bongo preversion",
|
|
39
|
-
"version": "bongo version",
|
|
39
|
+
"preversion": "bongo preversion --verifyPendingChanges",
|
|
40
|
+
"version": "bongo version --withPendingChanges",
|
|
40
41
|
"postversion": "bongo postversion --skip-release-notification",
|
|
41
42
|
"deps": "bongo deps",
|
|
42
43
|
"prepublish:setup": "echo 'setup is a no-op. Move along, nothing to see here.'"
|
|
@@ -58,14 +59,15 @@
|
|
|
58
59
|
"directory": "packages/eyes-storybook"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|
|
61
|
-
"@applitools/driver": "1.
|
|
62
|
-
"@applitools/eyes-sdk-core": "
|
|
62
|
+
"@applitools/driver": "1.5.5",
|
|
63
|
+
"@applitools/eyes-sdk-core": "13.1.2",
|
|
63
64
|
"@applitools/functional-commons": "1.6.0",
|
|
64
|
-
"@applitools/logger": "1.0.
|
|
65
|
+
"@applitools/logger": "1.0.11",
|
|
65
66
|
"@applitools/monitoring-commons": "1.0.19",
|
|
66
67
|
"@applitools/spec-driver-puppeteer": "1.1.0",
|
|
67
68
|
"@applitools/test-server": "1.0.8",
|
|
68
|
-
"@applitools/
|
|
69
|
+
"@applitools/utils": "1.2.13",
|
|
70
|
+
"@applitools/visual-grid-client": "15.10.1",
|
|
69
71
|
"boxen": "4.2.0",
|
|
70
72
|
"chalk": "3.0.0",
|
|
71
73
|
"detect-port": "1.3.0",
|
|
@@ -77,11 +79,10 @@
|
|
|
77
79
|
"yargs": "15.4.1"
|
|
78
80
|
},
|
|
79
81
|
"devDependencies": {
|
|
80
|
-
"@applitools/scripts": "^1.0
|
|
81
|
-
"@applitools/sdk-release-kit": "
|
|
82
|
+
"@applitools/scripts": "^1.1.0",
|
|
83
|
+
"@applitools/sdk-release-kit": "1.2.1",
|
|
82
84
|
"@applitools/sdk-shared": "0.9.11",
|
|
83
85
|
"@applitools/snaptdout": "^1.0.1",
|
|
84
|
-
"@applitools/utils": "1.2.5",
|
|
85
86
|
"@storybook/react": "^6.4.0",
|
|
86
87
|
"@testing-library/dom": "^5.6.1",
|
|
87
88
|
"babel-core": "^6.26.3",
|
package/src/cli.js
CHANGED
package/src/getIframeUrl.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
const {URL} = require('url');
|
|
3
3
|
|
|
4
4
|
function getIframeUrl(baseUrl) {
|
|
5
|
-
const {origin, pathname} = new URL(baseUrl);
|
|
5
|
+
const {origin, pathname, search} = new URL(baseUrl);
|
|
6
|
+
const searchParam = search && search.replace(/^\?/, '&');
|
|
6
7
|
|
|
7
8
|
let baseUrlFixed = `${origin}${pathname.replace(/\/[^\/]+\.html/, '')}`;
|
|
8
9
|
|
|
@@ -10,7 +11,10 @@ function getIframeUrl(baseUrl) {
|
|
|
10
11
|
baseUrlFixed += '/';
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
const url = new URL(
|
|
14
|
+
const url = new URL(
|
|
15
|
+
`iframe.html?eyes-storybook=true${searchParam ? searchParam : ''}`,
|
|
16
|
+
baseUrlFixed,
|
|
17
|
+
);
|
|
14
18
|
return url.href;
|
|
15
19
|
}
|
|
16
20
|
|
package/src/getStoryData.js
CHANGED
|
@@ -82,19 +82,20 @@ function makeGetStoryData({logger, takeDomSnapshots, waitBeforeCapture, reloadPa
|
|
|
82
82
|
return false;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
const currentQueryParams = url.searchParams.get('eyes-query-params');
|
|
86
|
+
if (!currentQueryParams && !expectedQueryParams) return true;
|
|
87
|
+
if (!currentQueryParams || !expectedQueryParams) return false;
|
|
88
|
+
|
|
86
89
|
const expectedQueryParamNames = Object.keys(expectedQueryParams);
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
const currentQueryParamNames = currentQueryParams.split(',');
|
|
91
|
+
|
|
92
|
+
if (currentQueryParamNames.length !== expectedQueryParamNames.length) return false;
|
|
93
|
+
|
|
94
|
+
for (const queryParamName of currentQueryParamNames) {
|
|
95
|
+
if (url.searchParams.get(queryParamName) !== expectedQueryParams[queryParamName]) {
|
|
91
96
|
return false;
|
|
92
97
|
}
|
|
93
|
-
actualQueryParamNames.push(name);
|
|
94
98
|
}
|
|
95
|
-
|
|
96
|
-
if (actualQueryParamNames.length !== expectedQueryParamNames.length) return false;
|
|
97
|
-
|
|
98
99
|
return true;
|
|
99
100
|
}
|
|
100
101
|
|
package/src/getStoryUrl.js
CHANGED
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
const getIframeUrl = require('./getIframeUrl');
|
|
3
3
|
|
|
4
4
|
function getStoryUrl({name, kind, parameters}, baseUrl) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
'',
|
|
9
|
-
);
|
|
5
|
+
let storyUrl = getIframeUrl(baseUrl);
|
|
6
|
+
storyUrl += `&selectedKind=${encodeURIComponent(kind)}`;
|
|
7
|
+
storyUrl += `&selectedStory=${encodeURIComponent(name)}`;
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const queryParams = parameters && parameters.eyes && parameters.eyes.queryParams;
|
|
10
|
+
if (queryParams) {
|
|
11
|
+
storyUrl += `&eyes-query-params=${Object.keys(queryParams).join(',')}`;
|
|
12
|
+
for (const [name, value] of Object.entries(queryParams)) {
|
|
13
|
+
storyUrl += `&${name}=${encodeURIComponent(value)}`;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return storyUrl;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
module.exports = getStoryUrl;
|
package/src/processResults.js
CHANGED
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
const flatten = require('lodash.flatten');
|
|
3
3
|
const chalk = require('./chalkify');
|
|
4
4
|
const {TestResultsError, TestResultsFormatter} = require('@applitools/eyes-sdk-core');
|
|
5
|
+
const utils = require('@applitools/utils');
|
|
5
6
|
const uniq = require('./uniq');
|
|
6
7
|
const concurrencyMsg = require('./concurrencyMsg');
|
|
7
8
|
|
|
8
|
-
function processResults({results = [], totalTime, testConcurrency}) {
|
|
9
|
+
function processResults({results = [], totalTime, testConcurrency, saveNewTests = true}) {
|
|
9
10
|
let outputStr = '\n';
|
|
10
11
|
const formatter = new TestResultsFormatter();
|
|
11
|
-
|
|
12
|
+
const pluralize = utils.general.pluralize;
|
|
12
13
|
let testResults = results.map(r => r.resultsOrErr);
|
|
13
14
|
testResults = flatten(testResults).filter(r => r.constructor.name !== 'Error');
|
|
14
15
|
const unresolved = testResults.filter(r => r.getIsDifferent());
|
|
15
16
|
const passedOrNew = testResults.filter(r => !r.getIsDifferent());
|
|
17
|
+
const newTests = testResults.filter(r => r.getIsNew());
|
|
18
|
+
const newTestsSize = newTests.length;
|
|
19
|
+
const warnForUnsavedNewTests = !!(!saveNewTests && newTestsSize);
|
|
16
20
|
|
|
17
21
|
let errors = results.map(({title, resultsOrErr}) =>
|
|
18
22
|
Array.isArray(resultsOrErr)
|
|
@@ -31,10 +35,10 @@ function processResults({results = [], totalTime, testConcurrency}) {
|
|
|
31
35
|
|
|
32
36
|
outputStr += '[EYES: TEST RESULTS]:\n\n';
|
|
33
37
|
if (passedOrNew.length > 0) {
|
|
34
|
-
outputStr += testResultsOutput(passedOrNew);
|
|
38
|
+
outputStr += testResultsOutput(passedOrNew, warnForUnsavedNewTests);
|
|
35
39
|
}
|
|
36
40
|
if (unresolved.length > 0) {
|
|
37
|
-
outputStr += testResultsOutput(unresolved);
|
|
41
|
+
outputStr += testResultsOutput(unresolved, warnForUnsavedNewTests);
|
|
38
42
|
}
|
|
39
43
|
if (errors.length) {
|
|
40
44
|
const sortedErrors = errors.sort((a, b) => a.title.localeCompare(b.title));
|
|
@@ -52,23 +56,38 @@ function processResults({results = [], totalTime, testConcurrency}) {
|
|
|
52
56
|
|
|
53
57
|
if (errors.length && !unresolved.length) {
|
|
54
58
|
outputStr += chalk.red(
|
|
55
|
-
`\nA total of ${errors.length} stor${
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
`\nA total of ${errors.length} stor${pluralize(errors, [
|
|
60
|
+
'ies',
|
|
61
|
+
'y',
|
|
62
|
+
])} failed for unexpected error${pluralize(errors)}.`,
|
|
58
63
|
);
|
|
59
64
|
} else if (unresolved.length && !errors.length) {
|
|
60
65
|
outputStr += chalk.keyword('orange')(
|
|
61
|
-
`\nA total of ${unresolved.length} difference${
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
`\nA total of ${unresolved.length} difference${pluralize(unresolved, [
|
|
67
|
+
's were',
|
|
68
|
+
' was',
|
|
69
|
+
])} found.`,
|
|
64
70
|
);
|
|
65
71
|
} else if (unresolved.length || errors.length) {
|
|
66
72
|
outputStr += chalk.red(
|
|
67
|
-
`\nA total of ${unresolved.length} difference${
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
`\nA total of ${unresolved.length} difference${pluralize(unresolved, [
|
|
74
|
+
's were',
|
|
75
|
+
' was',
|
|
76
|
+
])} found and ${errors.length} stor${pluralize(errors, [
|
|
77
|
+
'ies',
|
|
78
|
+
'y',
|
|
79
|
+
])} failed for ${pluralize(errors, ['', 'an '])}unexpected error${pluralize(errors)}.`,
|
|
80
|
+
);
|
|
81
|
+
} else if (warnForUnsavedNewTests) {
|
|
82
|
+
const countText =
|
|
83
|
+
newTestsSize > 1
|
|
84
|
+
? `are ${newTestsSize} new tests`
|
|
85
|
+
: `is a new test: '${newTests[0].getName()}'`;
|
|
86
|
+
outputStr += chalk.red(
|
|
87
|
+
`\n'saveNewTests' was set to false and there ${countText}. Please approve ${pluralize(
|
|
88
|
+
newTestsSize,
|
|
89
|
+
['their', 'its'],
|
|
90
|
+
)} baseline${pluralize(newTestsSize)} in Eyes dashboard.\n`,
|
|
72
91
|
);
|
|
73
92
|
} else if (passedOrNew.length) {
|
|
74
93
|
outputStr += chalk.green(`\nNo differences were found!`);
|
|
@@ -93,7 +112,9 @@ function processResults({results = [], totalTime, testConcurrency}) {
|
|
|
93
112
|
}),
|
|
94
113
|
);
|
|
95
114
|
});
|
|
96
|
-
const exitCode =
|
|
115
|
+
const exitCode =
|
|
116
|
+
!warnForUnsavedNewTests && passedOrNew.length && !errors.length && !unresolved.length ? 0 : 1;
|
|
117
|
+
|
|
97
118
|
return {
|
|
98
119
|
outputStr,
|
|
99
120
|
formatter,
|
|
@@ -101,7 +122,7 @@ function processResults({results = [], totalTime, testConcurrency}) {
|
|
|
101
122
|
};
|
|
102
123
|
}
|
|
103
124
|
|
|
104
|
-
function testResultsOutput(results) {
|
|
125
|
+
function testResultsOutput(results, warnForUnsavedNewTests) {
|
|
105
126
|
let outputStr = '';
|
|
106
127
|
const sortedTestResults = results.sort((a, b) => a.getName().localeCompare(b.getName()));
|
|
107
128
|
sortedTestResults.forEach(result => {
|
|
@@ -110,7 +131,8 @@ function testResultsOutput(results) {
|
|
|
110
131
|
.toString()}] - `;
|
|
111
132
|
|
|
112
133
|
if (result.getIsNew()) {
|
|
113
|
-
|
|
134
|
+
const newResColor = warnForUnsavedNewTests ? 'orange' : 'blue';
|
|
135
|
+
outputStr += `${storyTitle}${chalk.keyword(newResColor)('New')}\n`;
|
|
114
136
|
} else if (result.isPassed()) {
|
|
115
137
|
outputStr += `${storyTitle}${chalk.green('Passed')}\n`;
|
|
116
138
|
} else {
|