creevey 0.9.0-beta.13 → 0.9.0-beta.14
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/.yarn/install-state.gz +0 -0
- package/.yarnrc.yml +1 -0
- package/lib/cjs/cli.js +1 -0
- package/lib/cjs/client/addon/Manager.js +151 -223
- package/lib/cjs/client/addon/components/Addon.js +2 -9
- package/lib/cjs/client/addon/components/Icons.js +1 -7
- package/lib/cjs/client/addon/components/Panel.js +5 -18
- package/lib/cjs/client/addon/components/TestSelect.js +12 -25
- package/lib/cjs/client/addon/components/Tools.js +17 -28
- package/lib/cjs/client/addon/decorator.js +1 -4
- package/lib/cjs/client/addon/index.js +0 -4
- package/lib/cjs/client/addon/preset.js +3 -12
- package/lib/cjs/client/addon/preview.js +1 -4
- package/lib/cjs/client/addon/readyForCapture.js +1 -4
- package/lib/cjs/client/addon/register.js +11 -26
- package/lib/cjs/client/addon/utils.js +1 -9
- package/lib/cjs/client/addon/withCreevey.js +55 -134
- package/lib/cjs/client/shared/components/ImagesView/BlendView.js +5 -17
- package/lib/cjs/client/shared/components/ImagesView/ImagesView.js +8 -24
- package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +7 -23
- package/lib/cjs/client/shared/components/ImagesView/SlideView.js +7 -22
- package/lib/cjs/client/shared/components/ImagesView/SwapView.js +5 -17
- package/lib/cjs/client/shared/components/ImagesView/index.js +0 -5
- package/lib/cjs/client/shared/components/PageFooter/PageFooter.js +1 -8
- package/lib/cjs/client/shared/components/PageFooter/Paging.js +2 -19
- package/lib/cjs/client/shared/components/PageHeader/ImagePreview.js +21 -17
- package/lib/cjs/client/shared/components/PageHeader/PageHeader.js +5 -24
- package/lib/cjs/client/shared/components/ResultsPage.js +9 -37
- package/lib/cjs/client/shared/creeveyClientApi.js +3 -13
- package/lib/cjs/client/shared/helpers.js +21 -75
- package/lib/cjs/client/shared/viewMode.js +2 -6
- package/lib/cjs/client/web/192.js +1 -0
- package/lib/cjs/client/web/632.js +43 -0
- package/lib/cjs/client/web/794.js +1 -0
- package/lib/cjs/client/web/main.js +78 -1
- package/lib/cjs/client/web/main.js.LICENSE.txt +0 -15
- package/lib/cjs/creevey.js +5 -21
- package/lib/cjs/index.js +0 -15
- package/lib/cjs/server/config.js +13 -33
- package/lib/cjs/server/docker.js +5 -27
- package/lib/cjs/server/index.js +8 -33
- package/lib/cjs/server/logger.js +5 -19
- package/lib/cjs/server/master/api.js +1 -14
- package/lib/cjs/server/master/index.js +15 -46
- package/lib/cjs/server/master/master.js +6 -21
- package/lib/cjs/server/master/pool.js +2 -37
- package/lib/cjs/server/master/runner.js +15 -42
- package/lib/cjs/server/master/server.js +5 -27
- package/lib/cjs/server/messages.js +7 -53
- package/lib/cjs/server/selenium/browser.js +51 -136
- package/lib/cjs/server/selenium/index.js +0 -4
- package/lib/cjs/server/selenium/selenoid.js +7 -33
- package/lib/cjs/server/stories.js +25 -30
- package/lib/cjs/server/storybook/providers/browser.js +5 -18
- package/lib/cjs/server/storybook/providers/hybrid.js +9 -29
- package/lib/cjs/server/testsFiles/parser.js +3 -19
- package/lib/cjs/server/testsFiles/register.js +7 -9
- package/lib/cjs/server/update.js +3 -20
- package/lib/cjs/server/utils.js +9 -41
- package/lib/cjs/server/worker/chai-image.js +1 -27
- package/lib/cjs/server/worker/helpers.js +2 -12
- package/lib/cjs/server/worker/index.js +1 -3
- package/lib/cjs/server/worker/reporter.js +8 -24
- package/lib/cjs/server/worker/worker.js +5 -49
- package/lib/cjs/shared/index.js +22 -36
- package/lib/cjs/shared/serializeRegExp.js +0 -8
- package/lib/cjs/types.js +4 -14
- package/lib/esm/cli.js +1 -1
- package/lib/esm/client/addon/Manager.js +151 -214
- package/lib/esm/client/addon/components/Panel.js +4 -6
- package/lib/esm/client/addon/components/TestSelect.js +11 -17
- package/lib/esm/client/addon/components/Tools.js +15 -14
- package/lib/esm/client/addon/preset.js +2 -8
- package/lib/esm/client/addon/readyForCapture.js +1 -3
- package/lib/esm/client/addon/register.js +6 -8
- package/lib/esm/client/addon/utils.js +0 -5
- package/lib/esm/client/addon/withCreevey.js +54 -116
- package/lib/esm/client/shared/components/ImagesView/BlendView.js +1 -1
- package/lib/esm/client/shared/components/ImagesView/ImagesView.js +6 -8
- package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +3 -4
- package/lib/esm/client/shared/components/ImagesView/SlideView.js +3 -3
- package/lib/esm/client/shared/components/ImagesView/SwapView.js +1 -1
- package/lib/esm/client/shared/components/PageFooter/Paging.js +1 -11
- package/lib/esm/client/shared/components/PageHeader/ImagePreview.js +18 -7
- package/lib/esm/client/shared/components/PageHeader/PageHeader.js +3 -8
- package/lib/esm/client/shared/components/ResultsPage.js +6 -15
- package/lib/esm/client/shared/creeveyClientApi.js +3 -10
- package/lib/esm/client/shared/helpers.js +21 -47
- package/lib/esm/client/web/192.js +1 -0
- package/lib/esm/client/web/632.js +43 -0
- package/lib/esm/client/web/794.js +1 -0
- package/lib/esm/client/web/index.html +19 -0
- package/lib/esm/client/web/main.js +79 -0
- package/lib/esm/client/web/main.js.LICENSE.txt +34 -0
- package/lib/esm/creevey.js +4 -8
- package/lib/esm/index.js +0 -1
- package/lib/esm/server/config.js +7 -14
- package/lib/esm/server/docker.js +4 -12
- package/lib/esm/server/index.js +7 -21
- package/lib/esm/server/logger.js +0 -1
- package/lib/esm/server/master/api.js +0 -9
- package/lib/esm/server/master/index.js +15 -32
- package/lib/esm/server/master/master.js +2 -7
- package/lib/esm/server/master/pool.js +0 -23
- package/lib/esm/server/master/runner.js +14 -27
- package/lib/esm/server/master/server.js +4 -9
- package/lib/esm/server/messages.js +6 -38
- package/lib/esm/server/selenium/browser.js +50 -114
- package/lib/esm/server/selenium/selenoid.js +6 -17
- package/lib/esm/server/stories.js +24 -20
- package/lib/esm/server/storybook/providers/browser.js +4 -8
- package/lib/esm/server/storybook/providers/hybrid.js +6 -14
- package/lib/esm/server/testsFiles/parser.js +0 -6
- package/lib/esm/server/testsFiles/register.js +5 -2
- package/lib/esm/server/update.js +0 -8
- package/lib/esm/server/utils.js +3 -11
- package/lib/esm/server/worker/chai-image.js +0 -21
- package/lib/esm/server/worker/helpers.js +2 -9
- package/lib/esm/server/worker/reporter.js +7 -10
- package/lib/esm/server/worker/worker.js +4 -25
- package/lib/esm/shared/index.js +24 -25
- package/lib/esm/types.js +4 -1
- package/lib/types/client/addon/Manager.d.ts +1 -1
- package/lib/types/client/addon/components/Addon.d.ts +1 -0
- package/lib/types/client/addon/components/Icons.d.ts +1 -0
- package/lib/types/client/addon/components/Panel.d.ts +1 -0
- package/lib/types/client/addon/components/TestSelect.d.ts +1 -0
- package/lib/types/client/addon/components/Tools.d.ts +1 -0
- package/lib/types/client/addon/decorator.d.ts +1 -1
- package/lib/types/client/addon/preset.d.ts +2 -2
- package/lib/types/client/addon/preview.d.ts +1 -1
- package/lib/types/client/addon/withCreevey.d.ts +3 -2
- package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +3 -1
- package/lib/types/client/shared/components/ImagesView/ImagesView.d.ts +1 -0
- package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +3 -1
- package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +3 -1
- package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +3 -1
- package/lib/types/client/shared/components/PageFooter/PageFooter.d.ts +1 -0
- package/lib/types/client/shared/components/PageFooter/Paging.d.ts +1 -0
- package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +3 -1
- package/lib/types/client/shared/components/PageHeader/PageHeader.d.ts +1 -0
- package/lib/types/client/shared/components/ResultsPage.d.ts +3 -1
- package/lib/types/client/web/CreeveyApp.d.ts +1 -0
- package/lib/types/client/web/CreeveyLoader.d.ts +2 -1
- package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +4 -1
- package/lib/types/client/web/CreeveyView/SideBar/Search.d.ts +1 -0
- package/lib/types/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +1 -0
- package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +19 -14
- package/lib/types/client/web/CreeveyView/SideBar/TestLink.d.ts +1 -0
- package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +3 -1
- package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +3 -1
- package/lib/types/client/web/CreeveyView/SideBar/Toggle.d.ts +1 -0
- package/lib/types/shared/index.d.ts +1 -1
- package/lib/types/types.d.ts +7 -28
- package/package.json +60 -78
- package/lib/cjs/client/addon/preset.ie11.js +0 -74
- package/lib/cjs/client/addon/preset.sb7.js +0 -19
- package/lib/cjs/client/web/142.js +0 -2
- package/lib/cjs/client/web/142.js.LICENSE.txt +0 -12
- package/lib/cjs/client/web/32.js +0 -1
- package/lib/cjs/client/web/551.js +0 -1
- package/lib/cjs/client/web/566.js +0 -2
- package/lib/cjs/client/web/566.js.LICENSE.txt +0 -31
- package/lib/cjs/client/web/691.js +0 -2
- package/lib/cjs/client/web/691.js.LICENSE.txt +0 -8
- package/lib/cjs/client/web/725.js +0 -1
- package/lib/cjs/server/extract.js +0 -46
- package/lib/cjs/server/loaders/babel/creevey-plugin.js +0 -86
- package/lib/cjs/server/loaders/babel/helpers.js +0 -469
- package/lib/cjs/server/loaders/babel/register.js +0 -124
- package/lib/cjs/server/loaders/hooks/mdx.js +0 -30
- package/lib/cjs/server/loaders/hooks/svelte.js +0 -65
- package/lib/cjs/server/loaders/webpack/compile.js +0 -269
- package/lib/cjs/server/loaders/webpack/creevey-loader.js +0 -172
- package/lib/cjs/server/loaders/webpack/dummy-hmr.js +0 -39
- package/lib/cjs/server/loaders/webpack/mdx-loader.js +0 -72
- package/lib/cjs/server/loaders/webpack/start.js +0 -41
- package/lib/cjs/server/storybook/entry.js +0 -53
- package/lib/cjs/server/storybook/helpers.js +0 -158
- package/lib/cjs/server/storybook/providers/nodejs.js +0 -239
- package/lib/esm/client/addon/preset.ie11.js +0 -59
- package/lib/esm/client/addon/preset.sb7.js +0 -8
- package/lib/esm/server/extract.js +0 -32
- package/lib/esm/server/loaders/babel/creevey-plugin.js +0 -72
- package/lib/esm/server/loaders/babel/helpers.js +0 -452
- package/lib/esm/server/loaders/babel/register.js +0 -103
- package/lib/esm/server/loaders/hooks/mdx.js +0 -15
- package/lib/esm/server/loaders/hooks/svelte.js +0 -49
- package/lib/esm/server/loaders/webpack/compile.js +0 -246
- package/lib/esm/server/loaders/webpack/creevey-loader.js +0 -152
- package/lib/esm/server/loaders/webpack/dummy-hmr.js +0 -32
- package/lib/esm/server/loaders/webpack/mdx-loader.js +0 -58
- package/lib/esm/server/loaders/webpack/start.js +0 -27
- package/lib/esm/server/storybook/entry.js +0 -27
- package/lib/esm/server/storybook/helpers.js +0 -97
- package/lib/esm/server/storybook/providers/nodejs.js +0 -216
- package/lib/types/client/addon/preset.ie11.d.ts +0 -10
- package/lib/types/client/addon/preset.sb7.d.ts +0 -2
- package/lib/types/server/extract.d.ts +0 -2
- package/lib/types/server/loaders/babel/creevey-plugin.d.ts +0 -1
- package/lib/types/server/loaders/babel/helpers.d.ts +0 -19
- package/lib/types/server/loaders/babel/register.d.ts +0 -5
- package/lib/types/server/loaders/hooks/mdx.d.ts +0 -1
- package/lib/types/server/loaders/hooks/svelte.d.ts +0 -1
- package/lib/types/server/loaders/webpack/compile.d.ts +0 -2
- package/lib/types/server/loaders/webpack/creevey-loader.d.ts +0 -4
- package/lib/types/server/loaders/webpack/dummy-hmr.d.ts +0 -10
- package/lib/types/server/loaders/webpack/mdx-loader.d.ts +0 -6
- package/lib/types/server/loaders/webpack/start.d.ts +0 -1
- package/lib/types/server/storybook/entry.d.ts +0 -17
- package/lib/types/server/storybook/helpers.d.ts +0 -24
- package/lib/types/server/storybook/providers/nodejs.d.ts +0 -9
- package/preset/ie11.js +0 -5
- package/preset/index.js +0 -9
- package/preset/sb7.js +0 -5
- package/types/mdx.d.ts +0 -7
@@ -4,19 +4,18 @@ import { createHash } from 'crypto';
|
|
4
4
|
import { mapValues, pick } from 'lodash';
|
5
5
|
import { isDefined, isFunction, isObject } from '../types';
|
6
6
|
import { shouldSkip, removeProps } from './utils';
|
7
|
-
|
8
7
|
function storyTestFabric(delay, testFn) {
|
9
8
|
return async function storyTest() {
|
10
9
|
delay ? await new Promise(resolve => setTimeout(resolve, delay)) : void 0;
|
11
10
|
await (testFn ? testFn.call(this) : this.screenshots.length > 0 ? this.expect(this.screenshots.reduce((screenshots, {
|
12
11
|
imageName,
|
13
12
|
screenshot
|
14
|
-
}, index) => ({
|
13
|
+
}, index) => ({
|
14
|
+
...screenshots,
|
15
15
|
[imageName ?? `screenshot_${index}`]: screenshot
|
16
16
|
}), {})).to.matchImages() : this.expect(await this.takeScreenshot()).to.matchImage());
|
17
17
|
};
|
18
18
|
}
|
19
|
-
|
20
19
|
function createCreeveyTest(browser, storyMeta, skipOptions, testName) {
|
21
20
|
const {
|
22
21
|
kind,
|
@@ -38,7 +37,6 @@ function createCreeveyTest(browser, storyMeta, skipOptions, testName) {
|
|
38
37
|
storyId
|
39
38
|
};
|
40
39
|
}
|
41
|
-
|
42
40
|
function convertStories(browserName, stories) {
|
43
41
|
const tests = {};
|
44
42
|
(Array.isArray(stories) ? stories : Object.values(stories)).forEach(storyMeta => {
|
@@ -49,24 +47,27 @@ function convertStories(browserName, stories) {
|
|
49
47
|
tests: storyTests,
|
50
48
|
skip
|
51
49
|
} = storyMeta.parameters.creevey ?? {};
|
52
|
-
const delay = typeof delayParam == 'number' ? delayParam : delayParam !== null && delayParam !== void 0 && delayParam.for.includes(browserName) ? delayParam.ms : 0;
|
50
|
+
const delay = typeof delayParam == 'number' ? delayParam : delayParam !== null && delayParam !== void 0 && delayParam.for.includes(browserName) ? delayParam.ms : 0;
|
51
|
+
|
52
|
+
// typeof tests === "undefined" => rootSuite -> kindSuite -> storyTest -> [browsers.png]
|
53
53
|
// typeof tests === "function" => rootSuite -> kindSuite -> storyTest -> browser -> [images.png]
|
54
54
|
// typeof tests === "object" => rootSuite -> kindSuite -> storySuite -> test -> [browsers.png]
|
55
55
|
// typeof tests === "object" => rootSuite -> kindSuite -> storySuite -> test -> browser -> [images.png]
|
56
56
|
|
57
57
|
if (!storyTests) {
|
58
58
|
const test = createCreeveyTest(browserName, storyMeta, skip);
|
59
|
-
tests[test.id] = {
|
59
|
+
tests[test.id] = {
|
60
|
+
...test,
|
60
61
|
storyId: storyMeta.id,
|
61
62
|
story: storyMeta,
|
62
63
|
fn: storyTestFabric(delay)
|
63
64
|
};
|
64
65
|
return;
|
65
66
|
}
|
66
|
-
|
67
67
|
Object.entries(storyTests).forEach(([testName, testFn]) => {
|
68
68
|
const test = createCreeveyTest(browserName, storyMeta, skip, testName);
|
69
|
-
tests[test.id] = {
|
69
|
+
tests[test.id] = {
|
70
|
+
...test,
|
70
71
|
storyId: storyMeta.id,
|
71
72
|
story: storyMeta,
|
72
73
|
fn: storyTestFabric(delay, testFn)
|
@@ -75,7 +76,6 @@ function convertStories(browserName, stories) {
|
|
75
76
|
});
|
76
77
|
return tests;
|
77
78
|
}
|
78
|
-
|
79
79
|
export async function loadTestsFromStories(browsers, provider, update) {
|
80
80
|
const testIdsByFiles = new Map();
|
81
81
|
const stories = await provider(storiesByFiles => {
|
@@ -84,7 +84,6 @@ export async function loadTestsFromStories(browsers, provider, update) {
|
|
84
84
|
browsers.forEach(browser => {
|
85
85
|
Array.from(storiesByFiles.entries()).forEach(([filename, stories]) => {
|
86
86
|
var _testIdsByFiles$get;
|
87
|
-
|
88
87
|
Object.assign(tests, convertStories(browser, stories));
|
89
88
|
const changed = Object.keys(tests);
|
90
89
|
const removed = ((_testIdsByFiles$get = testIdsByFiles.get(filename)) === null || _testIdsByFiles$get === void 0 ? void 0 : _testIdsByFiles$get.filter(testId => !tests[testId])) ?? [];
|
@@ -93,7 +92,7 @@ export async function loadTestsFromStories(browsers, provider, update) {
|
|
93
92
|
removed.forEach(testId => testsDiff[testId] = undefined);
|
94
93
|
});
|
95
94
|
});
|
96
|
-
update === null || update === void 0
|
95
|
+
update === null || update === void 0 || update(testsDiff);
|
97
96
|
});
|
98
97
|
const tests = browsers.reduce((tests, browser) => Object.assign(tests, convertStories(browser, stories)), {});
|
99
98
|
Object.values(tests).filter(isDefined).forEach(({
|
@@ -103,22 +102,26 @@ export async function loadTestsFromStories(browsers, provider, update) {
|
|
103
102
|
fileName
|
104
103
|
}
|
105
104
|
}
|
106
|
-
}) =>
|
105
|
+
}) =>
|
106
|
+
// TODO Don't use filename as a key, due possible collisions if two require.context with same structure of modules are defined
|
107
107
|
testIdsByFiles.set(fileName, [...(testIdsByFiles.get(fileName) ?? []), id]));
|
108
108
|
return tests;
|
109
109
|
}
|
110
110
|
export function saveStoriesJson(storiesData, extract) {
|
111
|
-
const outputDir = typeof extract == 'boolean' ? 'storybook-static' : extract;
|
111
|
+
const outputDir = typeof extract == 'boolean' ? 'storybook-static' : extract;
|
112
112
|
|
113
|
+
// NOTE Copy-pasted from Storybook's `getStoriesJsonData` method
|
113
114
|
const allowed = ['fileName', 'docsOnly', 'framework', '__id', '__isArgsStory'];
|
114
|
-
storiesData.globalParameters = pick(storiesData.globalParameters, allowed);
|
115
|
-
|
116
|
-
storiesData.kindParameters = mapValues(storiesData.kindParameters, v => pick(v, allowed));
|
117
|
-
|
118
|
-
storiesData.stories = mapValues(storiesData.stories, v => ({
|
115
|
+
storiesData.globalParameters = pick(storiesData.globalParameters, allowed);
|
116
|
+
// @ts-expect-error ignore error
|
117
|
+
storiesData.kindParameters = mapValues(storiesData.kindParameters, v => pick(v, allowed));
|
118
|
+
// @ts-expect-error ignore error
|
119
|
+
storiesData.stories = mapValues(storiesData.stories, v => ({
|
120
|
+
...pick(v, ['id', 'name', 'kind', 'story']),
|
119
121
|
parameters: pick(v.parameters, allowed)
|
120
|
-
}));
|
122
|
+
}));
|
121
123
|
|
124
|
+
// TODO Fix args stories
|
122
125
|
removeProps(storiesData ?? {}, ['stories', () => true, 'parameters', '__isArgsStory']);
|
123
126
|
Object.values((storiesData === null || storiesData === void 0 ? void 0 : storiesData.stories) ?? {}).forEach(story => isObject(story) && 'parameters' in story && isObject(story.parameters) && delete story.parameters.__isArgsStory);
|
124
127
|
mkdirSync(outputDir, {
|
@@ -130,6 +133,7 @@ export function saveTestsJson(tests, dstPath = process.cwd()) {
|
|
130
133
|
mkdirSync(dstPath, {
|
131
134
|
recursive: true
|
132
135
|
});
|
133
|
-
writeFileSync(path.join(dstPath, 'tests.json'),
|
136
|
+
writeFileSync(path.join(dstPath, 'tests.json'),
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
134
138
|
JSON.stringify(tests, (_, value) => isFunction(value) ? value.toString() : value, 2));
|
135
139
|
}
|
@@ -8,7 +8,6 @@ export const loadStories = async (_config, _options, storiesListener) => {
|
|
8
8
|
if (cluster.isPrimary) {
|
9
9
|
return new Promise(resolve => {
|
10
10
|
const worker = Object.values(cluster.workers ?? {}).filter(isDefined).find(worker => worker.isConnected());
|
11
|
-
|
12
11
|
if (worker) {
|
13
12
|
const unsubscribe = subscribeOnWorker(worker, 'stories', message => {
|
14
13
|
if (message.type == 'set') {
|
@@ -25,7 +24,6 @@ export const loadStories = async (_config, _options, storiesListener) => {
|
|
25
24
|
type: 'get'
|
26
25
|
});
|
27
26
|
}
|
28
|
-
|
29
27
|
subscribeOn('stories', message => {
|
30
28
|
// TODO updates only one browser :(
|
31
29
|
if (message.type == 'update') storiesListener(new Map(message.payload));
|
@@ -45,12 +43,10 @@ export const loadStories = async (_config, _options, storiesListener) => {
|
|
45
43
|
const stories = deserializeRawStories(await loadStoriesFromBrowser());
|
46
44
|
const storiesWithOldTests = [];
|
47
45
|
Object.values(stories).forEach(story => {
|
48
|
-
var _parameters
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
(_parameters2 = story.parameters) === null || _parameters2 === void 0 ? true : (_parameters2$creevey = _parameters2.creevey) === null || _parameters2$creevey === void 0 ? true : delete _parameters2$creevey.tests;
|
46
|
+
var _parameters;
|
47
|
+
if ((_parameters = story.parameters) !== null && _parameters !== void 0 && (_parameters = _parameters.creevey) !== null && _parameters !== void 0 && _parameters.tests) {
|
48
|
+
var _parameters2;
|
49
|
+
(_parameters2 = story.parameters) === null || _parameters2 === void 0 || (_parameters2 = _parameters2.creevey) === null || _parameters2 === void 0 || delete _parameters2.tests;
|
54
50
|
storiesWithOldTests.push(`${story.kind}/${story.name}`);
|
55
51
|
}
|
56
52
|
});
|
@@ -6,55 +6,47 @@ import { readDirRecursive } from '../../../server/utils';
|
|
6
6
|
import { combineParameters } from '../../../shared';
|
7
7
|
export const loadStories = async (_config, _options, storiesListener) => {
|
8
8
|
let creeveyParamsByStoryId = {};
|
9
|
-
|
10
9
|
const mergeParamsFromTestsToStory = (story, creeveyParams) => {
|
11
10
|
if (story.parameters) {
|
12
11
|
story.parameters.creevey = combineParameters(story.parameters.creevey || {}, creeveyParams);
|
13
12
|
}
|
14
13
|
};
|
15
|
-
|
16
14
|
const stories = await browserProvider(_config, {}, updatedStoriesByFiles => {
|
17
15
|
Array.from(updatedStoriesByFiles.entries()).forEach(([, storiesArray]) => {
|
18
16
|
storiesArray.forEach(story => {
|
19
17
|
const creeveyParams = creeveyParamsByStoryId[story.id];
|
20
|
-
|
21
18
|
if (creeveyParams) {
|
22
19
|
mergeParamsFromTestsToStory(story, creeveyParams);
|
23
20
|
}
|
24
21
|
});
|
25
22
|
});
|
26
23
|
storiesListener(updatedStoriesByFiles);
|
27
|
-
});
|
24
|
+
});
|
28
25
|
|
29
|
-
|
30
|
-
/*, (data) => console.log(data) */
|
31
|
-
);
|
26
|
+
// TODO fix test files hot reloading
|
27
|
+
creeveyParamsByStoryId = await parseParams(_config /*, (data) => console.log(data) */);
|
32
28
|
Object.entries(stories).forEach(([storyId, story]) => {
|
33
29
|
mergeParamsFromTestsToStory(story, creeveyParamsByStoryId[storyId]);
|
34
30
|
});
|
35
31
|
return stories;
|
36
32
|
};
|
37
|
-
|
38
33
|
async function parseParams(config, listener) {
|
39
34
|
if (!config.testsDir) {
|
40
35
|
return Promise.resolve({});
|
41
36
|
}
|
42
|
-
|
43
37
|
const testFiles = readDirRecursive(config.testsDir).filter(file => {
|
44
38
|
var _config$testsRegex;
|
45
|
-
|
46
39
|
return (_config$testsRegex = config.testsRegex) === null || _config$testsRegex === void 0 ? void 0 : _config$testsRegex.test(file);
|
47
40
|
});
|
48
41
|
await (await import('../../testsFiles/register')).default(config);
|
49
|
-
|
50
42
|
if (listener) {
|
51
43
|
chokidar.watch(testFiles).on('change', filePath => {
|
52
|
-
logger.debug(`changed: ${filePath}`);
|
53
|
-
// see https://github.com/nodejs/modules/issues/307
|
44
|
+
logger.debug(`changed: ${filePath}`);
|
54
45
|
|
46
|
+
// doesn't work, always returns {} due modules caching
|
47
|
+
// see https://github.com/nodejs/modules/issues/307
|
55
48
|
void parse(testFiles).then(data => listener(data));
|
56
49
|
});
|
57
50
|
}
|
58
|
-
|
59
51
|
return parse(testFiles);
|
60
52
|
}
|
@@ -8,15 +8,12 @@ let result = {};
|
|
8
8
|
let kindTitle = '';
|
9
9
|
let storyTitle = '';
|
10
10
|
let storyParams = null;
|
11
|
-
|
12
11
|
const setStoryParameters = params => {
|
13
12
|
storyParams = params;
|
14
13
|
};
|
15
|
-
|
16
14
|
const getStoryId = (kindTitle, storyTitle) => {
|
17
15
|
return toId(kindTitle, storyNameFromExport(storyTitle));
|
18
16
|
};
|
19
|
-
|
20
17
|
export const kind = (title, kindFn) => {
|
21
18
|
kindTitle = title;
|
22
19
|
kindFn();
|
@@ -24,7 +21,6 @@ export const kind = (title, kindFn) => {
|
|
24
21
|
};
|
25
22
|
export const story = (title, storyFn) => {
|
26
23
|
var _result$storyId;
|
27
|
-
|
28
24
|
storyTitle = title;
|
29
25
|
storyParams = null;
|
30
26
|
storyFn({
|
@@ -39,11 +35,9 @@ export const story = (title, storyFn) => {
|
|
39
35
|
};
|
40
36
|
export const test = (title, testFn) => {
|
41
37
|
const storyId = getStoryId(kindTitle, storyTitle);
|
42
|
-
|
43
38
|
if (!result[storyId]) {
|
44
39
|
result[storyId] = {};
|
45
40
|
}
|
46
|
-
|
47
41
|
result[storyId].tests = Object.assign({}, result[storyId].tests, {
|
48
42
|
[title]: testFn
|
49
43
|
});
|
@@ -7,8 +7,9 @@ export default async function register(config) {
|
|
7
7
|
});
|
8
8
|
const {
|
9
9
|
path: tsConfigPath
|
10
|
-
} = getTsconfig(config.tsConfig) || {};
|
10
|
+
} = getTsconfig(config.tsConfig) || {};
|
11
11
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
12
13
|
(await import('@babel/register')).default(config.babelOptions({
|
13
14
|
babelrc: false,
|
14
15
|
rootMode: 'upward-optional',
|
@@ -27,5 +28,7 @@ export default async function register(config) {
|
|
27
28
|
plugins: [['@babel/plugin-transform-runtime'], ...(tsConfigPath ? [['babel-plugin-tsconfig-paths', {
|
28
29
|
tsconfig: tsConfigPath
|
29
30
|
}]] : [])]
|
30
|
-
}));
|
31
|
+
}));
|
32
|
+
|
33
|
+
// (await import('ts-node')).register({ project: tsConfigPath, transpileOnly: true });
|
31
34
|
}
|
package/lib/esm/server/update.js
CHANGED
@@ -2,7 +2,6 @@ import path from 'path';
|
|
2
2
|
import fs, { mkdirSync } from 'fs';
|
3
3
|
import micromatch from 'micromatch';
|
4
4
|
import { isDefined } from '../types';
|
5
|
-
|
6
5
|
function tryToLoadTestsData(filename) {
|
7
6
|
try {
|
8
7
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
@@ -11,9 +10,7 @@ function tryToLoadTestsData(filename) {
|
|
11
10
|
/* noop */
|
12
11
|
}
|
13
12
|
}
|
14
|
-
|
15
13
|
const actualRegex = /^(.*)-actual-(\d+)\.png$/i;
|
16
|
-
|
17
14
|
function approve(dirents, srcPath, dstPath, testPaths, isMatch) {
|
18
15
|
dirents.filter(dirent => dirent.isFile()).map(dirent => actualRegex.exec(dirent.name)).filter(isDefined).filter(([fileName, imageName]) => !testPaths || testPaths.find(([token]) => token == imageName) && isMatch(path.join(srcPath, fileName))).reduce((images, [, imageName, retry]) => Number(retry) > (images.get(imageName) ?? -1) ? images.set(imageName, Number(retry)) : images, new Map()).forEach((retry, imageName) => {
|
19
16
|
mkdirSync(dstPath, {
|
@@ -22,7 +19,6 @@ function approve(dirents, srcPath, dstPath, testPaths, isMatch) {
|
|
22
19
|
fs.copyFileSync(path.join(srcPath, `${imageName}-actual-${retry}.png`), path.join(dstPath, `${imageName}.png`));
|
23
20
|
});
|
24
21
|
}
|
25
|
-
|
26
22
|
function traverse(srcPath, dstPath, testPaths, isMatch) {
|
27
23
|
const dirents = fs.readdirSync(srcPath, {
|
28
24
|
withFileTypes: true
|
@@ -30,7 +26,6 @@ function traverse(srcPath, dstPath, testPaths, isMatch) {
|
|
30
26
|
approve(dirents, srcPath, dstPath, testPaths, isMatch);
|
31
27
|
dirents.filter(dirent => dirent.isDirectory()).map(dirent => [dirent.name, testPaths === null || testPaths === void 0 ? void 0 : testPaths.map(([token, ...restPath]) => token == dirent.name ? restPath : null).filter(isDefined)]).filter(([, paths]) => !paths || paths.length > 0).forEach(([dirname, paths]) => traverse(path.join(srcPath, dirname), path.join(dstPath, dirname), paths, isMatch));
|
32
28
|
}
|
33
|
-
|
34
29
|
export default function update(config, grepPattern) {
|
35
30
|
const {
|
36
31
|
reportDir,
|
@@ -42,13 +37,11 @@ export default function update(config, grepPattern) {
|
|
42
37
|
const testsMeta = tryToLoadTestsData(`${reportDir}/tests.json`);
|
43
38
|
const testsReport = tryToLoadTestsData(`${reportDir}/data`);
|
44
39
|
let testPaths = null;
|
45
|
-
|
46
40
|
if (testsMeta && testsReport) {
|
47
41
|
testPaths = Object.values(testsMeta).filter(isDefined).filter(({
|
48
42
|
id
|
49
43
|
}) => {
|
50
44
|
var _testsReport$id;
|
51
|
-
|
52
45
|
return ((_testsReport$id = testsReport[id]) === null || _testsReport$id === void 0 ? void 0 : _testsReport$id.status) == 'failed';
|
53
46
|
}).map(({
|
54
47
|
storyPath,
|
@@ -56,6 +49,5 @@ export default function update(config, grepPattern) {
|
|
56
49
|
browser
|
57
50
|
}) => [...storyPath, ...(testName ? [testName] : []), browser]);
|
58
51
|
}
|
59
|
-
|
60
52
|
traverse(reportDir, screenDir, testPaths, value => isMatch(path.relative(reportDir, value)));
|
61
53
|
}
|
package/lib/esm/server/utils.js
CHANGED
@@ -10,21 +10,17 @@ export const isShuttingDown = {
|
|
10
10
|
export const LOCALHOST_REGEXP = /(localhost|127\.0\.0\.1)/i;
|
11
11
|
export const extensions = ['.js', '.jsx', '.ts', '.tsx'];
|
12
12
|
export const skipOptionKeys = ['in', 'kinds', 'stories', 'tests', 'reason'];
|
13
|
-
|
14
13
|
function matchBy(pattern, value) {
|
15
14
|
return typeof pattern == 'string' && pattern == value || Array.isArray(pattern) && pattern.includes(value) || pattern instanceof RegExp && pattern.test(value) || !isDefined(pattern);
|
16
15
|
}
|
17
|
-
|
18
16
|
export function shouldSkip(browser, meta, skipOptions, test) {
|
19
17
|
if (typeof skipOptions != 'object') {
|
20
18
|
return skipOptions;
|
21
19
|
}
|
22
|
-
|
23
20
|
for (const skipKey in skipOptions) {
|
24
21
|
const reason = shouldSkipByOption(browser, meta, skipOptions[skipKey], skipKey, test);
|
25
22
|
if (reason) return reason;
|
26
23
|
}
|
27
|
-
|
28
24
|
return false;
|
29
25
|
}
|
30
26
|
export function shouldSkipByOption(browser, meta, skipOption, reason, test) {
|
@@ -33,10 +29,8 @@ export function shouldSkipByOption(browser, meta, skipOption, reason, test) {
|
|
33
29
|
const result = shouldSkipByOption(browser, meta, skip, reason, test);
|
34
30
|
if (result) return result;
|
35
31
|
}
|
36
|
-
|
37
32
|
return false;
|
38
33
|
}
|
39
|
-
|
40
34
|
const {
|
41
35
|
in: browsers,
|
42
36
|
kinds,
|
@@ -88,11 +82,11 @@ export function testsToImages(tests) {
|
|
88
82
|
results
|
89
83
|
}) => {
|
90
84
|
var _results$slice$;
|
91
|
-
|
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`);
|
85
|
+
return Object.keys((results === null || results === 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`);
|
93
86
|
})));
|
94
|
-
}
|
87
|
+
}
|
95
88
|
|
89
|
+
// https://tuhrig.de/how-to-know-you-are-inside-a-docker-container/
|
96
90
|
export const isInsideDocker = existsSync('/proc/1/cgroup') && /docker/.test(readFileSync('/proc/1/cgroup', 'utf8'));
|
97
91
|
export const downloadBinary = (downloadUrl, destination) => new Promise((resolve, reject) => get(downloadUrl, response => {
|
98
92
|
if (response.statusCode == 302) {
|
@@ -102,7 +96,6 @@ export const downloadBinary = (downloadUrl, destination) => new Promise((resolve
|
|
102
96
|
if (!location) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
|
103
97
|
return resolve(downloadBinary(location, destination));
|
104
98
|
}
|
105
|
-
|
106
99
|
if (response.statusCode != 200) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
|
107
100
|
const fileStream = createWriteStream(destination);
|
108
101
|
response.pipe(fileStream);
|
@@ -117,7 +110,6 @@ export const downloadBinary = (downloadUrl, destination) => new Promise((resolve
|
|
117
110
|
}));
|
118
111
|
export function removeProps(obj, propPath) {
|
119
112
|
const [prop, ...restPath] = propPath;
|
120
|
-
|
121
113
|
if (restPath.length > 0) {
|
122
114
|
if (typeof prop == 'string') obj[prop] && removeProps(obj[prop], restPath);
|
123
115
|
if (isFunction(prop)) Object.keys(obj).filter(prop).forEach(key => obj[key] && removeProps(obj[key], restPath));
|
@@ -1,13 +1,10 @@
|
|
1
1
|
import { PNG } from 'pngjs';
|
2
2
|
import pixelmatch from 'pixelmatch';
|
3
|
-
|
4
3
|
function normalizeImageSize(image, width, height) {
|
5
4
|
const normalizedImage = Buffer.alloc(4 * width * height);
|
6
|
-
|
7
5
|
for (let y = 0; y < height; y++) {
|
8
6
|
for (let x = 0; x < width; x++) {
|
9
7
|
const i = (y * width + x) * 4;
|
10
|
-
|
11
8
|
if (x < image.width && y < image.height) {
|
12
9
|
const j = (y * image.width + x) * 4;
|
13
10
|
normalizedImage[i + 0] = image.data[j + 0];
|
@@ -22,18 +19,14 @@ function normalizeImageSize(image, width, height) {
|
|
22
19
|
}
|
23
20
|
}
|
24
21
|
}
|
25
|
-
|
26
22
|
return normalizedImage;
|
27
23
|
}
|
28
|
-
|
29
24
|
function hasDiffPixels(diff) {
|
30
25
|
for (let i = 0; i < diff.length; i += 4) {
|
31
26
|
if (diff[i + 0] == 255 && diff[i + 1] == 0 && diff[i + 2] == 0 && diff[i + 3] == 255) return true;
|
32
27
|
}
|
33
|
-
|
34
28
|
return false;
|
35
29
|
}
|
36
|
-
|
37
30
|
function compareImages(expect, actual, diffOptions) {
|
38
31
|
const expectImage = PNG.sync.read(expect);
|
39
32
|
const actualImage = PNG.sync.read(actual);
|
@@ -44,42 +37,34 @@ function compareImages(expect, actual, diffOptions) {
|
|
44
37
|
height
|
45
38
|
});
|
46
39
|
let actualImageData = actualImage.data;
|
47
|
-
|
48
40
|
if (actualImage.width < width || actualImage.height < height) {
|
49
41
|
actualImageData = normalizeImageSize(actualImage, width, height);
|
50
42
|
}
|
51
|
-
|
52
43
|
let expectImageData = expectImage.data;
|
53
|
-
|
54
44
|
if (expectImage.width < width || expectImage.height < height) {
|
55
45
|
expectImageData = normalizeImageSize(expectImage, width, height);
|
56
46
|
}
|
57
|
-
|
58
47
|
pixelmatch(expectImageData, actualImageData, diffImage.data, width, height, diffOptions);
|
59
48
|
return {
|
60
49
|
isEqual: !hasDiffPixels(diffImage.data),
|
61
50
|
diff: PNG.sync.write(diffImage)
|
62
51
|
};
|
63
52
|
}
|
64
|
-
|
65
53
|
export default function (getExpected, diffOptions) {
|
66
54
|
return function chaiImage({
|
67
55
|
Assertion
|
68
56
|
}, utils) {
|
69
57
|
async function assertImage(actual, imageName) {
|
70
58
|
let onCompare = () => Promise.resolve();
|
71
|
-
|
72
59
|
let expected = await getExpected(imageName);
|
73
60
|
if (!(expected instanceof Buffer) && expected != null) ({
|
74
61
|
expected,
|
75
62
|
onCompare
|
76
63
|
} = expected);
|
77
|
-
|
78
64
|
if (expected == null) {
|
79
65
|
await onCompare(actual);
|
80
66
|
return imageName ? `Expected image '${imageName}' does not exists` : 'Expected image does not exists';
|
81
67
|
}
|
82
|
-
|
83
68
|
if (actual.equals(expected)) return await onCompare(actual);
|
84
69
|
const {
|
85
70
|
isEqual,
|
@@ -89,11 +74,9 @@ export default function (getExpected, diffOptions) {
|
|
89
74
|
await onCompare(actual, expected, diff);
|
90
75
|
return imageName ? `Expected image '${imageName}' to match` : 'Expected image to match';
|
91
76
|
}
|
92
|
-
|
93
77
|
utils.addMethod(Assertion.prototype, 'matchImage', async function matchImage(imageName) {
|
94
78
|
const actual = utils.flag(this, 'object');
|
95
79
|
const errorMessage = await assertImage(typeof actual == 'string' ? Buffer.from(actual, 'base64') : actual, imageName);
|
96
|
-
|
97
80
|
if (errorMessage) {
|
98
81
|
throw createImageError(imageName ? {
|
99
82
|
[imageName]: errorMessage
|
@@ -104,25 +87,21 @@ export default function (getExpected, diffOptions) {
|
|
104
87
|
const errors = {};
|
105
88
|
await Promise.all(Object.entries(utils.flag(this, 'object')).map(async ([imageName, imageOrBase64]) => {
|
106
89
|
let errorMessage;
|
107
|
-
|
108
90
|
try {
|
109
91
|
errorMessage = await assertImage(typeof imageOrBase64 == 'string' ? Buffer.from(imageOrBase64, 'base64') : imageOrBase64, imageName);
|
110
92
|
} catch (error) {
|
111
93
|
errorMessage = error.stack;
|
112
94
|
}
|
113
|
-
|
114
95
|
if (errorMessage) {
|
115
96
|
errors[imageName] = errorMessage;
|
116
97
|
}
|
117
98
|
}));
|
118
|
-
|
119
99
|
if (Object.keys(errors).length > 0) {
|
120
100
|
throw createImageError(errors);
|
121
101
|
}
|
122
102
|
});
|
123
103
|
};
|
124
104
|
}
|
125
|
-
|
126
105
|
function createImageError(imageErrors) {
|
127
106
|
const error = new Error('Expected image to match');
|
128
107
|
error.images = imageErrors;
|
@@ -1,28 +1,23 @@
|
|
1
1
|
import { Suite, Test } from 'mocha';
|
2
2
|
import { isDefined } from '../../types';
|
3
3
|
import { loadTestsFromStories } from '../stories';
|
4
|
-
|
5
4
|
function findOrCreateSuite(name, parent) {
|
6
5
|
const suite = parent.suites.find(({
|
7
6
|
title
|
8
7
|
}) => title == name) || new Suite(name, parent.ctx);
|
9
|
-
|
10
8
|
if (!suite.parent) {
|
11
9
|
suite.parent = parent;
|
12
10
|
parent.addSuite(suite);
|
13
11
|
}
|
14
|
-
|
15
12
|
return suite;
|
16
13
|
}
|
17
|
-
|
18
14
|
function createTest(name, fn, skip = false) {
|
19
15
|
const test = new Test(name, skip ? undefined : fn);
|
20
|
-
test.pending = Boolean(skip);
|
21
|
-
|
16
|
+
test.pending = Boolean(skip);
|
17
|
+
// NOTE Can't define skip reason in mocha https://github.com/mochajs/mocha/issues/2026
|
22
18
|
test.skipReason = skip;
|
23
19
|
return test;
|
24
20
|
}
|
25
|
-
|
26
21
|
function addTest(rootSuite, test) {
|
27
22
|
const [testName, ...suitePath] = [...test.storyPath, test.testName].reverse().filter(isDefined);
|
28
23
|
const suite = suitePath.reduceRight((subSuite, suiteName) => findOrCreateSuite(suiteName, subSuite), rootSuite);
|
@@ -34,7 +29,6 @@ function addTest(rootSuite, test) {
|
|
34
29
|
}, suite.ctx);
|
35
30
|
return mochaTest;
|
36
31
|
}
|
37
|
-
|
38
32
|
function removeTestOrSuite(testOrSuite) {
|
39
33
|
const {
|
40
34
|
parent
|
@@ -44,7 +38,6 @@ function removeTestOrSuite(testOrSuite) {
|
|
44
38
|
if (testOrSuite instanceof Suite) parent.suites = parent.suites.filter(suite => suite != testOrSuite);
|
45
39
|
if (parent.tests.length == 0 && parent.suites.length == 0) removeTestOrSuite(parent);
|
46
40
|
}
|
47
|
-
|
48
41
|
export async function addTestsFromStories(rootSuite, config, {
|
49
42
|
browser,
|
50
43
|
...options
|
@@ -20,13 +20,11 @@ export class CreeveyReporter extends reporters.Base {
|
|
20
20
|
format(level) {
|
21
21
|
return `${testLevels[level]} => (${topLevelSuite}:${chalk.gray(sessionId)})`;
|
22
22
|
}
|
23
|
-
|
24
23
|
});
|
25
24
|
runner.on('test', test => testLogger.warn(chalk.cyan(test.titlePath().join('/'))));
|
26
25
|
runner.on('pass', test => testLogger.info(chalk.cyan(test.titlePath().join('/'))));
|
27
26
|
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 ')));
|
28
27
|
}
|
29
|
-
|
30
28
|
}
|
31
29
|
export class TeamcityReporter extends reporters.Base {
|
32
30
|
constructor(runner, options) {
|
@@ -38,8 +36,8 @@ export class TeamcityReporter extends reporters.Base {
|
|
38
36
|
runner.on('fail', (test, error) => {
|
39
37
|
Object.entries(reporterOptions.images).forEach(([name, image]) => {
|
40
38
|
if (!image) return;
|
41
|
-
const filePath = test.titlePath().concat(name == topLevelSuite ? [] : [topLevelSuite]).map(this.escape).join('/');
|
42
|
-
|
39
|
+
const filePath = test.titlePath().concat(name == topLevelSuite ? [] : [topLevelSuite]).map(this.escape).join('/');
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
43
41
|
const {
|
44
42
|
error,
|
45
43
|
...rest
|
@@ -48,7 +46,9 @@ export class TeamcityReporter extends reporters.Base {
|
|
48
46
|
console.log(`##teamcity[publishArtifacts '${reporterOptions.reportDir}/${filePath}/${fileName} => report/${filePath}']`);
|
49
47
|
console.log(`##teamcity[testMetadata testName='${this.escape(test.title)}' type='image' value='report/${filePath}/${fileName}' flowId='${process.pid}']`);
|
50
48
|
});
|
51
|
-
});
|
49
|
+
});
|
50
|
+
|
51
|
+
// Output failed test as passed due TC don't support retry mechanic
|
52
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
|
53
53
|
|
54
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}']`);
|
@@ -58,17 +58,15 @@ export class TeamcityReporter extends reporters.Base {
|
|
58
58
|
runner.on('suite end', suite => suite.root || console.log(`##teamcity[testSuiteFinished name='${this.escape(suite.title)}' flowId='${process.pid}']`));
|
59
59
|
runner.on('end', () => console.log(`##teamcity[testSuiteFinished name='${topLevelSuite}' flowId='${process.pid}']`));
|
60
60
|
}
|
61
|
-
|
62
61
|
escape = str => {
|
63
62
|
if (!str) return '';
|
64
|
-
return str.toString()
|
63
|
+
return str.toString()
|
64
|
+
// eslint-disable-next-line no-control-regex
|
65
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
66
|
};
|
67
67
|
}
|
68
|
-
|
69
68
|
function getErrors(error, imageErrorToString, errorToString) {
|
70
69
|
const errors = [];
|
71
|
-
|
72
70
|
if (!(error instanceof Error)) {
|
73
71
|
errors.push(error);
|
74
72
|
} else if (!isImageError(error)) {
|
@@ -81,6 +79,5 @@ function getErrors(error, imageErrorToString, errorToString) {
|
|
81
79
|
errors.push(imageErrorToString(imageErrors[imageName] ?? '', imageName));
|
82
80
|
});
|
83
81
|
}
|
84
|
-
|
85
82
|
return errors;
|
86
83
|
}
|