creevey 0.9.0-beta.2 → 0.9.0-beta.4
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 +35 -0
- package/README.md +9 -1
- package/addon/README.md +3 -0
- package/addon/package.json +4 -0
- package/docs/config.md +29 -26
- package/jest.config.js +6 -0
- package/lib/cjs/client/addon/Manager.js +122 -270
- package/lib/cjs/client/addon/components/Addon.js +17 -38
- package/lib/cjs/client/addon/components/Icons.js +11 -7
- package/lib/cjs/client/addon/components/Panel.js +17 -13
- package/lib/cjs/client/addon/components/TestSelect.js +11 -9
- package/lib/cjs/client/addon/components/Tools.js +21 -40
- package/lib/cjs/client/addon/decorator.js +1 -1
- package/lib/cjs/client/addon/index.js +31 -0
- package/lib/cjs/client/addon/preset.ie11.js +74 -0
- package/lib/cjs/client/addon/preset.js +14 -33
- package/lib/cjs/client/addon/register.js +46 -70
- package/lib/cjs/client/addon/utils.js +6 -2
- package/lib/cjs/client/addon/withCreevey.js +161 -342
- package/lib/cjs/client/shared/components/ImagesView/BlendView.js +23 -21
- package/lib/cjs/client/shared/components/ImagesView/ImagesView.js +22 -18
- package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +42 -64
- package/lib/cjs/client/shared/components/ImagesView/SlideView.js +35 -48
- package/lib/cjs/client/shared/components/ImagesView/SwapView.js +24 -43
- package/lib/cjs/client/shared/components/ImagesView/index.js +9 -9
- package/lib/cjs/client/shared/components/PageFooter/PageFooter.js +12 -8
- package/lib/cjs/client/shared/components/PageFooter/Paging.js +14 -18
- package/lib/cjs/client/shared/components/PageHeader/ImagePreview.js +22 -18
- package/lib/cjs/client/shared/components/PageHeader/PageHeader.js +42 -67
- package/lib/cjs/client/shared/components/ResultsPage.js +39 -69
- package/lib/cjs/client/shared/creeveyClientApi.js +55 -82
- package/lib/cjs/client/shared/helpers.js +139 -210
- package/lib/cjs/client/shared/viewMode.js +5 -5
- package/lib/cjs/client/web/142.js +2 -0
- package/lib/cjs/client/web/142.js.LICENSE.txt +12 -0
- package/lib/cjs/client/web/32.js +1 -0
- package/lib/cjs/client/web/551.js +1 -0
- package/lib/cjs/client/web/566.js +2 -0
- package/lib/cjs/client/web/566.js.LICENSE.txt +31 -0
- package/lib/cjs/client/web/691.js +2 -0
- package/lib/cjs/client/web/691.js.LICENSE.txt +8 -0
- package/lib/cjs/client/web/725.js +1 -0
- package/lib/cjs/client/web/main.js +2 -38
- package/lib/cjs/client/web/main.js.LICENSE.txt +49 -0
- package/lib/cjs/creevey.js +3 -5
- package/lib/cjs/index.js +4 -4
- package/lib/cjs/server/config.js +2 -4
- package/lib/cjs/server/docker.js +3 -7
- package/lib/cjs/server/extract.js +1 -5
- package/lib/cjs/server/index.js +1 -1
- package/lib/cjs/server/loaders/babel/creevey-plugin.js +1 -3
- package/lib/cjs/server/loaders/babel/helpers.js +13 -23
- package/lib/cjs/server/loaders/babel/register.js +2 -4
- package/lib/cjs/server/loaders/webpack/compile.js +34 -51
- package/lib/cjs/server/loaders/webpack/creevey-loader.js +20 -22
- package/lib/cjs/server/loaders/webpack/dummy-hmr.js +2 -7
- package/lib/cjs/server/loaders/webpack/mdx-loader.js +2 -2
- package/lib/cjs/server/loaders/webpack/start.js +1 -1
- package/lib/cjs/server/logger.js +2 -1
- package/lib/cjs/server/master/index.js +2 -2
- package/lib/cjs/server/master/pool.js +9 -18
- package/lib/cjs/server/master/runner.js +53 -66
- package/lib/cjs/server/master/server.js +5 -3
- package/lib/cjs/server/messages.js +8 -10
- package/lib/cjs/server/selenium/browser.js +22 -46
- package/lib/cjs/server/selenium/selenoid.js +5 -7
- package/lib/cjs/server/stories.js +16 -33
- package/lib/cjs/server/storybook/entry.js +7 -22
- package/lib/cjs/server/storybook/helpers.js +20 -27
- package/lib/cjs/server/storybook/providers/browser.js +5 -9
- package/lib/cjs/server/storybook/providers/nodejs.js +7 -9
- package/lib/cjs/server/update.js +1 -5
- package/lib/cjs/server/utils.js +27 -36
- package/lib/cjs/server/worker/reporter.js +8 -20
- package/lib/cjs/server/worker/worker.js +6 -16
- package/lib/cjs/shared/index.js +101 -0
- package/lib/cjs/shared/serializeRegExp.js +42 -0
- package/lib/cjs/types.js +6 -6
- package/lib/esm/client/addon/Manager.js +122 -270
- package/lib/esm/client/addon/components/Addon.js +15 -34
- package/lib/esm/client/addon/components/Icons.js +10 -6
- package/lib/esm/client/addon/components/Panel.js +17 -13
- package/lib/esm/client/addon/components/TestSelect.js +11 -9
- package/lib/esm/client/addon/components/Tools.js +19 -36
- package/lib/esm/client/addon/decorator.js +1 -1
- package/lib/esm/client/addon/index.js +2 -0
- package/lib/esm/client/addon/preset.ie11.js +59 -0
- package/lib/esm/client/addon/preset.js +12 -27
- package/lib/esm/client/addon/register.js +42 -66
- package/lib/esm/client/addon/utils.js +3 -2
- package/lib/esm/client/addon/withCreevey.js +155 -341
- package/lib/esm/client/shared/components/ImagesView/BlendView.js +21 -17
- package/lib/esm/client/shared/components/ImagesView/ImagesView.js +21 -17
- package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +40 -60
- package/lib/esm/client/shared/components/ImagesView/SlideView.js +33 -44
- package/lib/esm/client/shared/components/ImagesView/SwapView.js +22 -39
- package/lib/esm/client/shared/components/PageFooter/PageFooter.js +12 -8
- package/lib/esm/client/shared/components/PageFooter/Paging.js +14 -18
- package/lib/esm/client/shared/components/PageHeader/ImagePreview.js +22 -18
- package/lib/esm/client/shared/components/PageHeader/PageHeader.js +37 -60
- package/lib/esm/client/shared/components/ResultsPage.js +36 -64
- package/lib/esm/client/shared/creeveyClientApi.js +57 -84
- package/lib/esm/client/shared/helpers.js +123 -194
- package/lib/esm/client/shared/viewMode.js +4 -4
- package/lib/esm/creevey.js +3 -5
- package/lib/esm/index.js +1 -3
- package/lib/esm/server/config.js +2 -4
- package/lib/esm/server/docker.js +2 -2
- package/lib/esm/server/extract.js +1 -3
- package/lib/esm/server/index.js +1 -1
- package/lib/esm/server/loaders/babel/creevey-plugin.js +1 -3
- package/lib/esm/server/loaders/babel/helpers.js +12 -22
- package/lib/esm/server/loaders/babel/register.js +3 -5
- package/lib/esm/server/loaders/webpack/compile.js +35 -52
- package/lib/esm/server/loaders/webpack/creevey-loader.js +9 -10
- package/lib/esm/server/loaders/webpack/dummy-hmr.js +2 -6
- package/lib/esm/server/loaders/webpack/mdx-loader.js +2 -2
- package/lib/esm/server/loaders/webpack/start.js +1 -1
- package/lib/esm/server/master/index.js +2 -2
- package/lib/esm/server/master/pool.js +7 -18
- package/lib/esm/server/master/runner.js +53 -66
- package/lib/esm/server/master/server.js +5 -3
- package/lib/esm/server/messages.js +3 -5
- package/lib/esm/server/selenium/browser.js +19 -43
- package/lib/esm/server/selenium/selenoid.js +4 -6
- package/lib/esm/server/stories.js +16 -32
- package/lib/esm/server/storybook/entry.js +5 -22
- package/lib/esm/server/storybook/helpers.js +11 -20
- package/lib/esm/server/storybook/providers/browser.js +4 -5
- package/lib/esm/server/storybook/providers/nodejs.js +7 -8
- package/lib/esm/server/update.js +1 -5
- package/lib/esm/server/utils.js +18 -31
- package/lib/esm/server/worker/reporter.js +8 -20
- package/lib/esm/server/worker/worker.js +6 -16
- package/lib/esm/shared/index.js +78 -0
- package/lib/esm/shared/serializeRegExp.js +24 -0
- package/lib/types/cli.d.ts +1 -1
- package/lib/types/client/addon/Manager.d.ts +37 -37
- package/lib/types/client/addon/components/Addon.d.ts +8 -8
- package/lib/types/client/addon/components/Icons.d.ts +7 -7
- package/lib/types/client/addon/components/Panel.d.ts +9 -9
- package/lib/types/client/addon/components/TestSelect.d.ts +8 -9
- package/lib/types/client/addon/components/Tools.d.ts +6 -6
- package/lib/types/client/addon/decorator.d.ts +1 -1
- package/lib/types/client/addon/index.d.ts +2 -0
- package/lib/types/client/addon/preset.d.ts +23 -24
- package/lib/types/client/addon/preset.ie11.d.ts +10 -0
- package/lib/types/client/addon/readyForCapture.d.ts +6 -6
- package/lib/types/client/addon/register.d.ts +3 -3
- package/lib/types/client/addon/utils.d.ts +3 -2
- package/lib/types/client/addon/withCreevey.d.ts +24 -24
- package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/ImagesView.d.ts +24 -25
- package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/index.d.ts +5 -5
- package/lib/types/client/shared/components/PageFooter/PageFooter.d.ts +8 -9
- package/lib/types/client/shared/components/PageFooter/Paging.d.ts +7 -8
- package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +12 -12
- package/lib/types/client/shared/components/PageHeader/PageHeader.d.ts +16 -17
- package/lib/types/client/shared/components/ResultsPage.d.ts +18 -18
- package/lib/types/client/shared/creeveyClientApi.d.ts +9 -9
- package/lib/types/client/shared/helpers.d.ts +46 -46
- package/lib/types/client/shared/viewMode.d.ts +4 -4
- package/lib/types/client/web/CreeveyApp.d.ts +11 -12
- package/lib/types/client/web/CreeveyContext.d.ts +11 -11
- package/lib/types/client/web/CreeveyLoader.d.ts +2 -3
- package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +19 -19
- package/lib/types/client/web/CreeveyView/SideBar/Search.d.ts +6 -6
- package/lib/types/client/web/CreeveyView/SideBar/SideBar.d.ts +14 -14
- package/lib/types/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +12 -13
- package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +33 -33
- package/lib/types/client/web/CreeveyView/SideBar/TestLink.d.ts +7 -8
- package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +10 -10
- package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +9 -9
- package/lib/types/client/web/CreeveyView/SideBar/Toggle.d.ts +6 -6
- package/lib/types/client/web/CreeveyView/SideBar/index.d.ts +1 -1
- package/lib/types/client/web/KeyboardEventsContext.d.ts +13 -13
- package/lib/types/client/web/index.d.ts +4 -4
- package/lib/types/creevey.d.ts +1 -1
- package/lib/types/index.d.ts +0 -1
- package/lib/types/server/config.d.ts +4 -4
- package/lib/types/server/docker.d.ts +7 -7
- package/lib/types/server/extract.d.ts +2 -2
- package/lib/types/server/index.d.ts +2 -2
- package/lib/types/server/loaders/babel/creevey-plugin.d.ts +1 -1
- package/lib/types/server/loaders/babel/helpers.d.ts +19 -19
- package/lib/types/server/loaders/babel/register.d.ts +5 -5
- package/lib/types/server/loaders/hooks/mdx.d.ts +1 -1
- package/lib/types/server/loaders/hooks/svelte.d.ts +1 -1
- package/lib/types/server/loaders/webpack/compile.d.ts +2 -2
- package/lib/types/server/loaders/webpack/creevey-loader.d.ts +4 -2
- package/lib/types/server/loaders/webpack/dummy-hmr.d.ts +10 -10
- package/lib/types/server/loaders/webpack/mdx-loader.d.ts +6 -6
- package/lib/types/server/loaders/webpack/start.d.ts +1 -1
- package/lib/types/server/logger.d.ts +10 -6
- package/lib/types/server/master/api.d.ts +7 -7
- package/lib/types/server/master/index.d.ts +3 -3
- package/lib/types/server/master/master.d.ts +7 -7
- package/lib/types/server/master/pool.d.ts +31 -31
- package/lib/types/server/master/runner.d.ts +26 -26
- package/lib/types/server/master/server.d.ts +2 -2
- package/lib/types/server/messages.d.ts +27 -27
- package/lib/types/server/selenium/browser.d.ts +17 -17
- package/lib/types/server/selenium/index.d.ts +2 -2
- package/lib/types/server/selenium/selenoid.d.ts +3 -3
- package/lib/types/server/stories.d.ts +8 -8
- package/lib/types/server/storybook/entry.d.ts +17 -18
- package/lib/types/server/storybook/helpers.d.ts +24 -24
- package/lib/types/server/storybook/providers/browser.d.ts +4 -4
- package/lib/types/server/storybook/providers/hybrid.d.ts +4 -4
- package/lib/types/server/storybook/providers/nodejs.d.ts +9 -9
- package/lib/types/server/testsFiles/parser.d.ts +12 -12
- package/lib/types/server/testsFiles/register.d.ts +2 -2
- package/lib/types/server/update.d.ts +2 -2
- package/lib/types/server/utils.d.ts +24 -20
- package/lib/types/server/worker/chai-image.d.ts +6 -6
- package/lib/types/server/worker/helpers.d.ts +8 -8
- package/lib/types/server/worker/index.d.ts +1 -1
- package/lib/types/server/worker/reporter.d.ts +8 -8
- package/lib/types/server/worker/worker.d.ts +4 -4
- package/lib/types/{shared.d.ts → shared/index.d.ts} +7 -16
- package/lib/types/shared/serializeRegExp.d.ts +9 -0
- package/lib/types/types.d.ts +489 -489
- package/package.json +114 -102
- package/preset/ie11.js +5 -0
- package/{preset.js → preset/index.js} +2 -2
- package/types/mdx.d.ts +3 -2
- package/lib/cjs/client/web/1.js +0 -13
- package/lib/cjs/client/web/2.js +0 -1
- package/lib/cjs/shared.js +0 -124
- package/lib/esm/shared.js +0 -93
- package/storybook-static/stories.json +0 -21
package/lib/esm/server/utils.js
CHANGED
@@ -20,38 +20,29 @@ export function shouldSkip(browser, meta, skipOptions, test) {
|
|
20
20
|
return skipOptions;
|
21
21
|
}
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
if (reason) return reason;
|
27
|
-
}
|
28
|
-
|
29
|
-
return false;
|
23
|
+
for (const skipKey in skipOptions) {
|
24
|
+
const reason = shouldSkipByOption(browser, meta, skipOptions[skipKey], skipKey, test);
|
25
|
+
if (reason) return reason;
|
30
26
|
}
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
return false;
|
29
|
+
}
|
30
|
+
export function shouldSkipByOption(browser, meta, skipOption, reason, test) {
|
31
|
+
if (Array.isArray(skipOption)) {
|
32
|
+
for (const skip of skipOption) {
|
33
|
+
const result = shouldSkipByOption(browser, meta, skip, reason, test);
|
34
|
+
if (result) return result;
|
38
35
|
}
|
39
36
|
|
40
|
-
|
41
|
-
reason: skipKey,
|
42
|
-
...skipOptions[skipKey]
|
43
|
-
}, test);
|
44
|
-
if (reason) return reason;
|
37
|
+
return false;
|
45
38
|
}
|
46
39
|
|
47
|
-
if (!hasSkipOptionKeys) return false;
|
48
40
|
const {
|
49
41
|
in: browsers,
|
50
42
|
kinds,
|
51
43
|
stories,
|
52
|
-
tests
|
53
|
-
|
54
|
-
} = skipOptions;
|
44
|
+
tests
|
45
|
+
} = skipOption;
|
55
46
|
const {
|
56
47
|
kind,
|
57
48
|
story
|
@@ -64,7 +55,7 @@ export function shouldSkip(browser, meta, skipOptions, test) {
|
|
64
55
|
}
|
65
56
|
export async function shutdownWorkers() {
|
66
57
|
isShuttingDown.current = true;
|
67
|
-
await Promise.all(Object.values(cluster.workers).filter(isDefined).filter(worker => worker.isConnected()).map(worker => new Promise(resolve => {
|
58
|
+
await Promise.all(Object.values(cluster.workers ?? {}).filter(isDefined).filter(worker => worker.isConnected()).map(worker => new Promise(resolve => {
|
68
59
|
const timeout = setTimeout(() => worker.kill(), 10000);
|
69
60
|
worker.on('exit', () => {
|
70
61
|
clearTimeout(timeout);
|
@@ -96,27 +87,23 @@ export function testsToImages(tests) {
|
|
96
87
|
storyPath,
|
97
88
|
results
|
98
89
|
}) => {
|
99
|
-
var _results$slice
|
90
|
+
var _results$slice$;
|
100
91
|
|
101
|
-
return Object.keys((
|
92
|
+
return Object.keys((results === null || results === void 0 ? void 0 : (_results$slice$ = results.slice(-1)[0]) === null || _results$slice$ === void 0 ? void 0 : _results$slice$.images) ?? {}).map(image => `${[...storyPath, testName, browser, browser == image ? undefined : image].filter(isDefined).join('/')}.png`);
|
102
93
|
})));
|
103
94
|
} // https://tuhrig.de/how-to-know-you-are-inside-a-docker-container/
|
104
95
|
|
105
96
|
export const isInsideDocker = existsSync('/proc/1/cgroup') && /docker/.test(readFileSync('/proc/1/cgroup', 'utf8'));
|
106
97
|
export const downloadBinary = (downloadUrl, destination) => new Promise((resolve, reject) => get(downloadUrl, response => {
|
107
|
-
var _response$statusCode2;
|
108
|
-
|
109
98
|
if (response.statusCode == 302) {
|
110
|
-
var _response$statusCode;
|
111
|
-
|
112
99
|
const {
|
113
100
|
location
|
114
101
|
} = response.headers;
|
115
|
-
if (!location) return reject(new Error(`Couldn't download selenoid. Status code: ${
|
102
|
+
if (!location) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
|
116
103
|
return resolve(downloadBinary(location, destination));
|
117
104
|
}
|
118
105
|
|
119
|
-
if (response.statusCode != 200) return reject(new Error(`Couldn't download selenoid. Status code: ${
|
106
|
+
if (response.statusCode != 200) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
|
120
107
|
const fileStream = createWriteStream(destination);
|
121
108
|
response.pipe(fileStream);
|
122
109
|
fileStream.on('finish', () => {
|
@@ -1,5 +1,3 @@
|
|
1
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
2
|
-
|
3
1
|
import chalk from 'chalk';
|
4
2
|
import { reporters } from 'mocha';
|
5
3
|
import prefix from 'loglevel-plugin-prefix';
|
@@ -26,31 +24,18 @@ export class CreeveyReporter extends reporters.Base {
|
|
26
24
|
});
|
27
25
|
runner.on('test', test => testLogger.warn(chalk.cyan(test.titlePath().join('/'))));
|
28
26
|
runner.on('pass', test => testLogger.info(chalk.cyan(test.titlePath().join('/'))));
|
29
|
-
runner.on('fail', (test, error) => testLogger.error(chalk.cyan(test.titlePath().join('/')), '\n ', getErrors(error, (error, imageName) => `${chalk.bold(imageName
|
30
|
-
var _error$stack;
|
31
|
-
|
32
|
-
return `${(_error$stack = error.stack) !== null && _error$stack !== void 0 ? _error$stack : error.message}`;
|
33
|
-
}).join('\n ')));
|
27
|
+
runner.on('fail', (test, error) => testLogger.error(chalk.cyan(test.titlePath().join('/')), '\n ', getErrors(error, (error, imageName) => `${chalk.bold(imageName ?? topLevelSuite)}:${error}`, error => `${error.stack ?? error.message}`).join('\n ')));
|
34
28
|
}
|
35
29
|
|
36
30
|
}
|
37
31
|
export class TeamcityReporter extends reporters.Base {
|
38
32
|
constructor(runner, options) {
|
39
33
|
super(runner);
|
40
|
-
|
41
|
-
_defineProperty(this, "escape", str => {
|
42
|
-
if (!str) return '';
|
43
|
-
return str.toString() // eslint-disable-next-line no-control-regex
|
44
|
-
.replace(/\x1B.*?m/g, '').replace(/\|/g, '||').replace(/\n/g, '|n').replace(/\r/g, '|r').replace(/\[/g, '|[').replace(/\]/g, '|]').replace(/\u0085/g, '|x').replace(/\u2028/g, '|l').replace(/\u2029/g, '|p').replace(/'/g, "|'");
|
45
|
-
});
|
46
|
-
|
47
34
|
const topLevelSuite = this.escape(options.reporterOptions.topLevelSuite);
|
48
35
|
const reporterOptions = options.reporterOptions;
|
49
36
|
runner.on('suite', suite => suite.root ? console.log(`##teamcity[testSuiteStarted name='${topLevelSuite}' flowId='${process.pid}']`) : console.log(`##teamcity[testSuiteStarted name='${this.escape(suite.title)}' flowId='${process.pid}']`));
|
50
37
|
runner.on('test', test => console.log(`##teamcity[testStarted name='${this.escape(test.title)}' flowId='${process.pid}']`));
|
51
38
|
runner.on('fail', (test, error) => {
|
52
|
-
var _error$stack2;
|
53
|
-
|
54
39
|
Object.entries(reporterOptions.images).forEach(([name, image]) => {
|
55
40
|
if (!image) return;
|
56
41
|
const filePath = test.titlePath().concat(name == topLevelSuite ? [] : [topLevelSuite]).map(this.escape).join('/'); // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
@@ -66,7 +51,7 @@ export class TeamcityReporter extends reporters.Base {
|
|
66
51
|
}); // Output failed test as passed due TC don't support retry mechanic
|
67
52
|
// https://teamcity-support.jetbrains.com/hc/en-us/community/posts/207216829-Count-test-as-successful-if-at-least-one-try-is-successful?page=1#community_comment_207394125
|
68
53
|
|
69
|
-
reporterOptions.willRetry ? console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`) : console.log(`##teamcity[testFailed name='${this.escape(test.title)}' message='${this.escape(error.message)}' details='${this.escape(
|
54
|
+
reporterOptions.willRetry ? console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`) : console.log(`##teamcity[testFailed name='${this.escape(test.title)}' message='${this.escape(error.message)}' details='${this.escape(error.stack ?? '')}' flowId='${process.pid}']`);
|
70
55
|
});
|
71
56
|
runner.on('pending', test => console.log(`##teamcity[testIgnored name='${this.escape(test.title)}' message='${this.escape(typeof test.skipReason == 'boolean' ? test.title : test.skipReason)}' flowId='${process.pid}']`));
|
72
57
|
runner.on('test end', test => console.log(`##teamcity[testFinished name='${this.escape(test.title)}' flowId='${process.pid}']`));
|
@@ -74,6 +59,11 @@ export class TeamcityReporter extends reporters.Base {
|
|
74
59
|
runner.on('end', () => console.log(`##teamcity[testSuiteFinished name='${topLevelSuite}' flowId='${process.pid}']`));
|
75
60
|
}
|
76
61
|
|
62
|
+
escape = str => {
|
63
|
+
if (!str) return '';
|
64
|
+
return str.toString() // eslint-disable-next-line no-control-regex
|
65
|
+
.replace(/\x1B.*?m/g, '').replace(/\|/g, '||').replace(/\n/g, '|n').replace(/\r/g, '|r').replace(/\[/g, '|[').replace(/\]/g, '|]').replace(/\u0085/g, '|x').replace(/\u2028/g, '|l').replace(/\u2029/g, '|p').replace(/'/g, "|'");
|
66
|
+
};
|
77
67
|
}
|
78
68
|
|
79
69
|
function getErrors(error, imageErrorToString, errorToString) {
|
@@ -88,9 +78,7 @@ function getErrors(error, imageErrorToString, errorToString) {
|
|
88
78
|
} else {
|
89
79
|
const imageErrors = error.images;
|
90
80
|
Object.keys(imageErrors).forEach(imageName => {
|
91
|
-
|
92
|
-
|
93
|
-
errors.push(imageErrorToString((_imageErrors$imageNam = imageErrors[imageName]) !== null && _imageErrors$imageNam !== void 0 ? _imageErrors$imageNam : '', imageName));
|
81
|
+
errors.push(imageErrorToString(imageErrors[imageName] ?? '', imageName));
|
94
82
|
});
|
95
83
|
}
|
96
84
|
|
@@ -34,9 +34,7 @@ async function getLastImageNumber(imageDir, imageName) {
|
|
34
34
|
const actualImagesRegexp = new RegExp(`${imageName}-actual-(\\d+)\\.png`);
|
35
35
|
|
36
36
|
try {
|
37
|
-
|
38
|
-
|
39
|
-
return (_await$readdirAsync$m = (await readdirAsync(imageDir)).map(filename => filename.replace(actualImagesRegexp, '$1')).map(Number).filter(x => !isNaN(x)).sort((a, b) => b - a)[0]) !== null && _await$readdirAsync$m !== void 0 ? _await$readdirAsync$m : 0;
|
37
|
+
return (await readdirAsync(imageDir)).map(filename => filename.replace(actualImagesRegexp, '$1')).map(Number).filter(x => !isNaN(x)).sort((a, b) => b - a)[0] ?? 0;
|
40
38
|
} catch (_error) {
|
41
39
|
return 0;
|
42
40
|
}
|
@@ -54,8 +52,6 @@ export default async function worker(config, options) {
|
|
54
52
|
|
55
53
|
function runHandler(failures) {
|
56
54
|
if (failures > 0 && (error || Object.values(images).some(image => (image === null || image === void 0 ? void 0 : image.error) != null))) {
|
57
|
-
var _error2;
|
58
|
-
|
59
55
|
const isTimeout = hasTimeout(error) || Object.values(images).some(image => hasTimeout(image === null || image === void 0 ? void 0 : image.error));
|
60
56
|
const payload = {
|
61
57
|
status: 'failed',
|
@@ -65,7 +61,7 @@ export default async function worker(config, options) {
|
|
65
61
|
isTimeout ? emitWorkerMessage({
|
66
62
|
type: 'error',
|
67
63
|
payload: {
|
68
|
-
error:
|
64
|
+
error: error ?? 'Unknown error'
|
69
65
|
}
|
70
66
|
}) : emitTestMessage({
|
71
67
|
type: 'end',
|
@@ -96,18 +92,16 @@ export default async function worker(config, options) {
|
|
96
92
|
}
|
97
93
|
|
98
94
|
async function getExpected(assertImageName) {
|
99
|
-
var _images$imageName;
|
100
|
-
|
101
95
|
// context => [kind, story, test, browser]
|
102
96
|
// rootSuite -> kindSuite -> storyTest -> [browsers.png]
|
103
97
|
// rootSuite -> kindSuite -> storySuite -> test -> [browsers.png]
|
104
98
|
const testPath = [...testScope];
|
105
|
-
const imageName = assertImageName
|
99
|
+
const imageName = assertImageName ?? testPath.pop();
|
106
100
|
const imagesMeta = [];
|
107
101
|
const reportImageDir = path.join(config.reportDir, ...testPath);
|
108
102
|
const imageNumber = (await getLastImageNumber(reportImageDir, imageName)) + 1;
|
109
103
|
const actualImageName = `${imageName}-actual-${imageNumber}.png`;
|
110
|
-
const image = images[imageName] =
|
104
|
+
const image = images[imageName] = images[imageName] ?? {
|
111
105
|
actual: actualImageName
|
112
106
|
};
|
113
107
|
|
@@ -169,9 +163,7 @@ export default async function worker(config, options) {
|
|
169
163
|
|
170
164
|
}
|
171
165
|
};
|
172
|
-
const mocha = new Mocha(mochaOptions);
|
173
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
174
|
-
|
166
|
+
const mocha = new Mocha(mochaOptions);
|
175
167
|
mocha.cleanReferencesAfterRun(false);
|
176
168
|
chai.use(chaiImage(getExpected, config.diffOptions));
|
177
169
|
if ((await getBrowser(config, options.browser)) == null) return;
|
@@ -222,9 +214,7 @@ export default async function worker(config, options) {
|
|
222
214
|
if (!(reason instanceof Error)) {
|
223
215
|
error = reason;
|
224
216
|
} else if (!isImageError(reason)) {
|
225
|
-
|
226
|
-
|
227
|
-
error = (_reason$stack = reason.stack) !== null && _reason$stack !== void 0 ? _reason$stack : reason.message;
|
217
|
+
error = reason.stack ?? reason.message;
|
228
218
|
} else if (typeof reason.images == 'string') {
|
229
219
|
const image = images[testScope.slice(-1)[0]];
|
230
220
|
if (image) image.error = reason.images;
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import { mapValues, mergeWith, cloneDeepWith } from 'lodash';
|
2
|
+
import { deserializeRegExp, isSerializedRegExp, isRegExp, serializeRegExp } from './serializeRegExp'; // NOTE: Copy-paste from storybook/api
|
3
|
+
|
4
|
+
export const combineParameters = function () {
|
5
|
+
for (var _len = arguments.length, parameterSets = new Array(_len), _key = 0; _key < _len; _key++) {
|
6
|
+
parameterSets[_key] = arguments[_key];
|
7
|
+
}
|
8
|
+
|
9
|
+
return (// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
10
|
+
mergeWith({}, ...parameterSets, (_, srcValue) => {
|
11
|
+
// Treat arrays as scalars:
|
12
|
+
if (Array.isArray(srcValue)) return srcValue;
|
13
|
+
return undefined;
|
14
|
+
})
|
15
|
+
);
|
16
|
+
}; // NOTE: Copy-paste from storybook/api
|
17
|
+
|
18
|
+
export const denormalizeStoryParameters = _ref => {
|
19
|
+
let {
|
20
|
+
globalParameters,
|
21
|
+
kindParameters,
|
22
|
+
stories
|
23
|
+
} = _ref;
|
24
|
+
return mapValues(stories, storyData => {
|
25
|
+
var _kindParameters$story;
|
26
|
+
|
27
|
+
return { ...storyData,
|
28
|
+
parameters: combineParameters(globalParameters, (_kindParameters$story = kindParameters[storyData.kind]) !== null && _kindParameters$story !== void 0 ? _kindParameters$story : {}, storyData.parameters)
|
29
|
+
};
|
30
|
+
});
|
31
|
+
};
|
32
|
+
export const serializeRawStories = stories => {
|
33
|
+
return mapValues(stories, storyData => {
|
34
|
+
const creevey = storyData.parameters.creevey;
|
35
|
+
|
36
|
+
if (creevey !== null && creevey !== void 0 && creevey.skip) {
|
37
|
+
return { ...storyData,
|
38
|
+
parameters: { ...storyData.parameters,
|
39
|
+
creevey: { ...creevey,
|
40
|
+
skip: cloneDeepWith(creevey.skip, value => {
|
41
|
+
if (isRegExp(value)) {
|
42
|
+
return serializeRegExp(value);
|
43
|
+
}
|
44
|
+
|
45
|
+
return undefined;
|
46
|
+
})
|
47
|
+
}
|
48
|
+
}
|
49
|
+
};
|
50
|
+
}
|
51
|
+
|
52
|
+
return storyData;
|
53
|
+
});
|
54
|
+
};
|
55
|
+
export const deserializeRawStories = stories => {
|
56
|
+
return mapValues(stories, deserializeStory);
|
57
|
+
};
|
58
|
+
export const deserializeStory = story => {
|
59
|
+
const creevey = story.parameters.creevey;
|
60
|
+
|
61
|
+
if (creevey !== null && creevey !== void 0 && creevey.skip) {
|
62
|
+
return { ...story,
|
63
|
+
parameters: { ...story.parameters,
|
64
|
+
creevey: { ...creevey,
|
65
|
+
skip: cloneDeepWith(creevey.skip, value => {
|
66
|
+
if (isSerializedRegExp(value)) {
|
67
|
+
return deserializeRegExp(value);
|
68
|
+
}
|
69
|
+
|
70
|
+
return undefined;
|
71
|
+
})
|
72
|
+
}
|
73
|
+
}
|
74
|
+
};
|
75
|
+
}
|
76
|
+
|
77
|
+
return story;
|
78
|
+
};
|
@@ -0,0 +1,24 @@
|
|
1
|
+
export const isRegExp = exp => {
|
2
|
+
return exp instanceof RegExp;
|
3
|
+
};
|
4
|
+
export const isSerializedRegExp = exp => {
|
5
|
+
return typeof exp === 'object' && exp !== null && Reflect.get(exp, '__regexp') === true;
|
6
|
+
};
|
7
|
+
export const serializeRegExp = exp => {
|
8
|
+
const {
|
9
|
+
source,
|
10
|
+
flags
|
11
|
+
} = exp;
|
12
|
+
return {
|
13
|
+
__regexp: true,
|
14
|
+
source,
|
15
|
+
flags
|
16
|
+
};
|
17
|
+
};
|
18
|
+
export const deserializeRegExp = _ref => {
|
19
|
+
let {
|
20
|
+
source,
|
21
|
+
flags
|
22
|
+
} = _ref;
|
23
|
+
return new RegExp(source, flags);
|
24
|
+
};
|
package/lib/types/cli.d.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
#!/usr/bin/env node
|
1
|
+
#!/usr/bin/env node
|
@@ -1,37 +1,37 @@
|
|
1
|
-
import { API } from '@storybook/api';
|
2
|
-
import {
|
3
|
-
import { CreeveyStatus, CreeveyUpdate, TestData, TestStatus, StoriesRaw } from '../../types';
|
4
|
-
import { CreeveyClientApi } from '../shared/creeveyClientApi';
|
5
|
-
export declare class CreeveyManager {
|
6
|
-
storybookApi: API;
|
7
|
-
storyId: string;
|
8
|
-
activeBrowser: string;
|
9
|
-
selectedTestId: string;
|
10
|
-
status: CreeveyStatus;
|
11
|
-
creeveyApi: CreeveyClientApi | null;
|
12
|
-
stories: StoriesRaw;
|
13
|
-
updateStatusListeners: Array<(update: CreeveyUpdate) => void>;
|
14
|
-
changeTestListeners: Array<(testId: string) => void>;
|
15
|
-
constructor(storybookApi: API);
|
16
|
-
initAll: () => Promise<void>;
|
17
|
-
onUpdateStatus(listener: (update: CreeveyUpdate) => void): () => void;
|
18
|
-
onChangeTest(listener: (testId: string) => void): () => void;
|
19
|
-
handleCreeveyUpdate: (update: CreeveyUpdate) => void;
|
20
|
-
getCurrentTest: () => TestData | undefined;
|
21
|
-
onStoryRendered: (storyId: string) => void;
|
22
|
-
onStart: () => void;
|
23
|
-
onStop: () => void;
|
24
|
-
onImageApprove: (id: string, retry: number, image: string) => void;
|
25
|
-
onStartAllStoryTests: () => void;
|
26
|
-
onStartAllTests: () => void;
|
27
|
-
onSetStories: (data:
|
28
|
-
setActiveBrowser: (browser: string) => void;
|
29
|
-
setSelectedTestId: (testId: string) => void;
|
30
|
-
getStoryTests: (storyId: string) => TestData[];
|
31
|
-
getBrowsers: () => string[];
|
32
|
-
getTestsByStoryIdAndBrowser: (browser: string) => TestData[];
|
33
|
-
getTabTitle: (browser: string) => string;
|
34
|
-
setPanelsTitle: () => void;
|
35
|
-
addStatusesToSideBar(): Promise<void>;
|
36
|
-
addStatusToStoryName(name: string, status: TestStatus | undefined, skip: string | boolean): string;
|
37
|
-
}
|
1
|
+
import { API } from '@storybook/api';
|
2
|
+
import { denormalizeStoryParameters } from '../../shared';
|
3
|
+
import { CreeveyStatus, CreeveyUpdate, TestData, TestStatus, StoriesRaw } from '../../types';
|
4
|
+
import { CreeveyClientApi } from '../shared/creeveyClientApi';
|
5
|
+
export declare class CreeveyManager {
|
6
|
+
storybookApi: API;
|
7
|
+
storyId: string;
|
8
|
+
activeBrowser: string;
|
9
|
+
selectedTestId: string;
|
10
|
+
status: CreeveyStatus;
|
11
|
+
creeveyApi: CreeveyClientApi | null;
|
12
|
+
stories: StoriesRaw;
|
13
|
+
updateStatusListeners: Array<(update: CreeveyUpdate) => void>;
|
14
|
+
changeTestListeners: Array<(testId: string) => void>;
|
15
|
+
constructor(storybookApi: API);
|
16
|
+
initAll: () => Promise<void>;
|
17
|
+
onUpdateStatus(listener: (update: CreeveyUpdate) => void): () => void;
|
18
|
+
onChangeTest(listener: (testId: string) => void): () => void;
|
19
|
+
handleCreeveyUpdate: (update: CreeveyUpdate) => void;
|
20
|
+
getCurrentTest: () => TestData | undefined;
|
21
|
+
onStoryRendered: (storyId: string) => void;
|
22
|
+
onStart: () => void;
|
23
|
+
onStop: () => void;
|
24
|
+
onImageApprove: (id: string, retry: number, image: string) => void;
|
25
|
+
onStartAllStoryTests: () => void;
|
26
|
+
onStartAllTests: () => void;
|
27
|
+
onSetStories: (data: Parameters<typeof denormalizeStoryParameters>['0']) => void;
|
28
|
+
setActiveBrowser: (browser: string) => void;
|
29
|
+
setSelectedTestId: (testId: string) => void;
|
30
|
+
getStoryTests: (storyId: string) => TestData[];
|
31
|
+
getBrowsers: () => string[];
|
32
|
+
getTestsByStoryIdAndBrowser: (browser: string) => TestData[];
|
33
|
+
getTabTitle: (browser: string) => string;
|
34
|
+
setPanelsTitle: () => void;
|
35
|
+
addStatusesToSideBar(): Promise<void>;
|
36
|
+
addStatusToStoryName(name: string, status: TestStatus | undefined, skip: string | boolean): string;
|
37
|
+
}
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import { CreeveyManager } from '../Manager';
|
2
|
-
interface AddonProps {
|
3
|
-
active?: boolean;
|
4
|
-
browser: string;
|
5
|
-
manager: CreeveyManager;
|
6
|
-
}
|
7
|
-
export declare const Addon: ({ active, browser, manager }: AddonProps) => JSX.Element | null;
|
8
|
-
export {};
|
1
|
+
import { CreeveyManager } from '../Manager';
|
2
|
+
interface AddonProps {
|
3
|
+
active?: boolean;
|
4
|
+
browser: string;
|
5
|
+
manager: CreeveyManager;
|
6
|
+
}
|
7
|
+
export declare const Addon: ({ active, browser, manager }: AddonProps) => JSX.Element | null;
|
8
|
+
export {};
|
@@ -1,7 +1,7 @@
|
|
1
|
-
interface IconProps {
|
2
|
-
width?: number;
|
3
|
-
height?: number;
|
4
|
-
}
|
5
|
-
export declare const NextIcon: ({ width, height }: IconProps) => JSX.Element;
|
6
|
-
export declare const ForwardIcon: ({ width, height }: IconProps) => JSX.Element;
|
7
|
-
export {};
|
1
|
+
interface IconProps {
|
2
|
+
width?: number;
|
3
|
+
height?: number;
|
4
|
+
}
|
5
|
+
export declare const NextIcon: ({ width, height }: IconProps) => JSX.Element;
|
6
|
+
export declare const ForwardIcon: ({ width, height }: IconProps) => JSX.Element;
|
7
|
+
export {};
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import { TestData } from '../../../types';
|
2
|
-
interface PanelProps {
|
3
|
-
tests: TestData[];
|
4
|
-
selectedTestId: string;
|
5
|
-
onChangeTest: (testId: string) => void;
|
6
|
-
onImageApprove: (id: string, retry: number, image: string) => void;
|
7
|
-
}
|
8
|
-
export declare const Panel: ({ tests, selectedTestId, onChangeTest, onImageApprove }: PanelProps) => JSX.Element;
|
9
|
-
export {};
|
1
|
+
import { TestData } from '../../../types';
|
2
|
+
interface PanelProps {
|
3
|
+
tests: TestData[];
|
4
|
+
selectedTestId: string;
|
5
|
+
onChangeTest: (testId: string) => void;
|
6
|
+
onImageApprove: (id: string, retry: number, image: string) => void;
|
7
|
+
}
|
8
|
+
export declare const Panel: ({ tests, selectedTestId, onChangeTest, onImageApprove }: PanelProps) => JSX.Element;
|
9
|
+
export {};
|
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
export
|
9
|
-
export {};
|
1
|
+
import { TestData } from '../../../types';
|
2
|
+
interface TestSelectProps {
|
3
|
+
tests: TestData[];
|
4
|
+
selectedTestId: string;
|
5
|
+
onChangeTest: (testId: string) => void;
|
6
|
+
}
|
7
|
+
export default function TestSelect(props: TestSelectProps): JSX.Element;
|
8
|
+
export {};
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import { CreeveyManager } from '../Manager';
|
2
|
-
interface ToolsProps {
|
3
|
-
manager: CreeveyManager;
|
4
|
-
}
|
5
|
-
export declare const Tools: ({ manager }: ToolsProps) => JSX.Element | null;
|
6
|
-
export {};
|
1
|
+
import { CreeveyManager } from '../Manager';
|
2
|
+
interface ToolsProps {
|
3
|
+
manager: CreeveyManager;
|
4
|
+
}
|
5
|
+
export declare const Tools: ({ manager }: ToolsProps) => JSX.Element | null;
|
6
|
+
export {};
|
@@ -1 +1 @@
|
|
1
|
-
export declare const decorators: import("@storybook/addons").MakeDecoratorResult[];
|
1
|
+
export declare const decorators: import("@storybook/addons").MakeDecoratorResult[];
|
@@ -1,24 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
export declare function
|
4
|
-
|
5
|
-
|
6
|
-
const
|
7
|
-
const
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
export declare function managerWebpack(config: Configuration, options: CreeveyAddonOptions): Promise<Configuration>;
|
1
|
+
import { Configuration } from 'webpack';
|
2
|
+
export declare function config(entry?: string[]): string[];
|
3
|
+
export declare function managerEntries(entry?: string[]): string[];
|
4
|
+
declare global {
|
5
|
+
const __CREEVEY_SERVER_HOST__: string;
|
6
|
+
const __CREEVEY_SERVER_PORT__: number;
|
7
|
+
const __CREEVEY_CLIENT_PORT__: number | null;
|
8
|
+
}
|
9
|
+
export interface CreeveyAddonOptions {
|
10
|
+
creeveyConfigPath?: string;
|
11
|
+
creeveyPreExtract?: string;
|
12
|
+
creeveyHost?: string;
|
13
|
+
creeveyPort?: number;
|
14
|
+
clientPort?: number;
|
15
|
+
configType: string;
|
16
|
+
configDir: string;
|
17
|
+
outputDir: string;
|
18
|
+
skipExtract?: boolean;
|
19
|
+
presets?: {
|
20
|
+
apply: <T>(preset: string) => Promise<T | undefined>;
|
21
|
+
};
|
22
|
+
}
|
23
|
+
export declare function _managerWebpack(config: Configuration, options: CreeveyAddonOptions): Promise<Configuration>;
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import type { Configuration } from 'webpack';
|
2
|
+
import { PluginItem } from '@babel/core';
|
3
|
+
interface BabelOptions {
|
4
|
+
extends: string | null;
|
5
|
+
presets: PluginItem[] | null;
|
6
|
+
}
|
7
|
+
export declare const babel: (config: BabelOptions) => BabelOptions;
|
8
|
+
export declare const managerWebpack: (webpackConfig?: Configuration) => Configuration;
|
9
|
+
export declare const webpack: (webpackConfig?: Configuration) => Configuration;
|
10
|
+
export {};
|
@@ -1,6 +1,6 @@
|
|
1
|
-
declare global {
|
2
|
-
interface Window {
|
3
|
-
__CREEVEY_SET_READY_FOR_CAPTURE__?: () => void;
|
4
|
-
}
|
5
|
-
}
|
6
|
-
export declare function readyForCapture(): void;
|
1
|
+
declare global {
|
2
|
+
interface Window {
|
3
|
+
__CREEVEY_SET_READY_FOR_CAPTURE__?: () => void;
|
4
|
+
}
|
5
|
+
}
|
6
|
+
export declare function readyForCapture(): void;
|
@@ -1,3 +1,3 @@
|
|
1
|
-
import { API } from '@storybook/api';
|
2
|
-
export declare const ADDON_ID = "creevey";
|
3
|
-
export declare function registerCreeveyPanels(storybookApi: API): Promise<void>;
|
1
|
+
import { API } from '@storybook/api';
|
2
|
+
export declare const ADDON_ID = "creevey";
|
3
|
+
export declare function registerCreeveyPanels(storybookApi: API): Promise<void>;
|
@@ -1,2 +1,3 @@
|
|
1
|
-
import { TestStatus } from '../../types';
|
2
|
-
export declare function getEmojiByTestStatus(status: TestStatus | undefined, skip?: string | boolean): string;
|
1
|
+
import { TestStatus } from '../../types';
|
2
|
+
export declare function getEmojiByTestStatus(status: TestStatus | undefined, skip?: string | boolean): string;
|
3
|
+
export declare const isInternetExplorer: boolean;
|