creevey 0.9.0-beta.2 → 0.9.0-non-webpack.1
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/AUTHORS +15 -15
- package/CHANGELOG.md +1275 -1275
- package/LICENSE +21 -21
- package/README.md +7 -0
- package/addon/README.md +3 -0
- package/addon/package.json +4 -0
- package/docs/config.md +212 -212
- package/docs/grid.md +10 -10
- package/docs/tests.md +63 -63
- package/jest.config.js +6 -0
- package/lib/cjs/client/addon/Manager.js +123 -271
- package/lib/cjs/client/addon/components/Addon.js +17 -38
- package/lib/cjs/client/addon/components/Icons.js +12 -8
- 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.js +13 -32
- package/lib/cjs/client/addon/register.js +46 -70
- package/lib/cjs/client/addon/utils.js +1 -1
- package/lib/cjs/client/addon/withCreevey.js +164 -344
- 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 +143 -214
- 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/index.html +19 -19
- 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 +1 -1
- package/lib/cjs/server/docker.js +3 -7
- 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 +1 -3
- package/lib/cjs/server/loaders/webpack/compile.js +31 -24
- package/lib/cjs/server/loaders/webpack/creevey-loader.js +10 -5
- package/lib/cjs/server/loaders/webpack/dummy-hmr.js +2 -7
- package/lib/cjs/server/loaders/webpack/mdx-loader.js +1 -1
- 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 +2 -2
- package/lib/cjs/server/messages.js +8 -10
- package/lib/cjs/server/selenium/browser.js +23 -31
- package/lib/cjs/server/selenium/selenoid.js +5 -7
- package/lib/cjs/server/stories.js +9 -20
- package/lib/cjs/server/storybook/entry.js +5 -3
- package/lib/cjs/server/storybook/helpers.js +15 -21
- package/lib/cjs/server/storybook/providers/browser.js +5 -9
- package/lib/cjs/server/storybook/providers/nodejs.js +4 -4
- package/lib/cjs/server/update.js +1 -5
- package/lib/cjs/server/utils.js +13 -15
- 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 +123 -271
- package/lib/esm/client/addon/components/Addon.js +15 -34
- package/lib/esm/client/addon/components/Icons.js +11 -7
- 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.js +10 -25
- package/lib/esm/client/addon/register.js +42 -66
- package/lib/esm/client/addon/utils.js +1 -1
- package/lib/esm/client/addon/withCreevey.js +157 -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 +127 -198
- 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/docker.js +2 -2
- 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 +1 -3
- package/lib/esm/server/loaders/webpack/compile.js +31 -24
- package/lib/esm/server/loaders/webpack/creevey-loader.js +9 -4
- package/lib/esm/server/loaders/webpack/dummy-hmr.js +2 -6
- 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 +2 -2
- package/lib/esm/server/messages.js +3 -5
- package/lib/esm/server/selenium/browser.js +20 -28
- package/lib/esm/server/selenium/selenoid.js +4 -6
- package/lib/esm/server/stories.js +9 -20
- package/lib/esm/server/storybook/entry.js +4 -2
- package/lib/esm/server/storybook/helpers.js +7 -15
- package/lib/esm/server/storybook/providers/browser.js +4 -5
- package/lib/esm/server/storybook/providers/nodejs.js +3 -3
- package/lib/esm/server/update.js +1 -5
- package/lib/esm/server/utils.js +5 -9
- 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/readyForCapture.d.ts +6 -6
- package/lib/types/client/addon/register.d.ts +3 -3
- package/lib/types/client/addon/utils.d.ts +2 -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 +18 -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 +20 -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 +490 -489
- package/package.json +115 -102
- package/preset.js +9 -9
- package/types/babel__register.d.ts +1 -1
- package/types/chai.d.ts +12 -12
- package/types/event-source-polyfill.d.ts +6 -6
- package/types/mdx.d.ts +3 -2
- package/types/mocha.d.ts +20 -20
- package/types/png.d.ts +4 -4
- 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
@@ -10,7 +10,7 @@ import { PageLoadStrategy } from 'selenium-webdriver/lib/capabilities';
|
|
10
10
|
import { isDefined, noop } from '../../types';
|
11
11
|
import { colors, logger } from '../logger';
|
12
12
|
import { emitStoriesMessage, subscribeOn } from '../messages';
|
13
|
-
import { importStorybookCoreEvents, isStorybookVersionLessThan } from '../storybook/helpers';
|
13
|
+
import { importStorybookCoreEvents, isStorybookVersionGreaterThan, isStorybookVersionLessThan } from '../storybook/helpers';
|
14
14
|
import { isShuttingDown, LOCALHOST_REGEXP, runSequence } from '../utils';
|
15
15
|
const DOCKER_INTERNAL = 'host.docker.internal';
|
16
16
|
let browserLogger = logger;
|
@@ -23,9 +23,7 @@ function getSessionData(grid, sessionId = '') {
|
|
23
23
|
gridUrl.pathname = `/host/${sessionId}`;
|
24
24
|
return new Promise((resolve, reject) => (gridUrl.protocol == 'https:' ? https : http).get(gridUrl.toString(), res => {
|
25
25
|
if (res.statusCode !== 200) {
|
26
|
-
|
27
|
-
|
28
|
-
return reject(new Error(`Couldn't get session data for ${sessionId}. Status code: ${(_res$statusCode = res.statusCode) !== null && _res$statusCode !== void 0 ? _res$statusCode : 'Unknown'}`));
|
26
|
+
return reject(new Error(`Couldn't get session data for ${sessionId}. Status code: ${res.statusCode ?? 'Unknown'}`));
|
29
27
|
}
|
30
28
|
|
31
29
|
let data = '';
|
@@ -35,9 +33,7 @@ function getSessionData(grid, sessionId = '') {
|
|
35
33
|
try {
|
36
34
|
resolve(JSON.parse(data));
|
37
35
|
} catch (error) {
|
38
|
-
|
39
|
-
|
40
|
-
reject(new Error(`Couldn't get session data for ${sessionId}. ${error instanceof Error ? (_error$stack = error.stack) !== null && _error$stack !== void 0 ? _error$stack : error.message : error}`));
|
36
|
+
reject(new Error(`Couldn't get session data for ${sessionId}. ${error instanceof Error ? error.stack ?? error.message : error}`));
|
41
37
|
}
|
42
38
|
});
|
43
39
|
}));
|
@@ -104,7 +100,7 @@ function getUrlChecker(browser) {
|
|
104
100
|
|
105
101
|
async function waitForStorybook(browser) {
|
106
102
|
// NOTE: Storybook 5.x doesn't have the `last` method
|
107
|
-
if (isStorybookVersionLessThan(6)) {
|
103
|
+
if (isStorybookVersionLessThan(6) || isStorybookVersionGreaterThan(6, 4)) {
|
108
104
|
browserLogger.debug('Waiting for `load` event to make sure that storybook is initiated');
|
109
105
|
return browser.executeAsyncScript(function (callback) {
|
110
106
|
if (document.readyState == 'complete') return callback();
|
@@ -136,11 +132,11 @@ async function waitForStorybook(browser) {
|
|
136
132
|
}
|
137
133
|
|
138
134
|
async function resetMousePosition(browser) {
|
139
|
-
var
|
135
|
+
var _await$browser$getCap, _await$browser$getCap2;
|
140
136
|
|
141
137
|
browserLogger.debug('Resetting mouse position to the top-left corner');
|
142
138
|
const browserName = (await browser.getCapabilities()).getBrowserName();
|
143
|
-
const [browserVersion] = (
|
139
|
+
const [browserVersion] = ((_await$browser$getCap = (await browser.getCapabilities()).getBrowserVersion()) === null || _await$browser$getCap === void 0 ? void 0 : _await$browser$getCap.split('.')) ?? ((_await$browser$getCap2 = (await browser.getCapabilities()).get('version')) === null || _await$browser$getCap2 === void 0 ? void 0 : _await$browser$getCap2.split('.')) ?? []; // NOTE Reset mouse position to support keweb selenium grid browser versions
|
144
140
|
|
145
141
|
if (browserName == 'chrome' && browserVersion == '70') {
|
146
142
|
const {
|
@@ -224,10 +220,10 @@ const getScrollBarWidth = (() => {
|
|
224
220
|
|
225
221
|
|
226
222
|
async function hasScrollBar(browser) {
|
227
|
-
var _await$browser$
|
223
|
+
var _await$browser$getCap3;
|
228
224
|
|
229
225
|
const browserName = (await browser.getCapabilities()).getBrowserName();
|
230
|
-
const [browserVersion] = (
|
226
|
+
const [browserVersion] = ((_await$browser$getCap3 = (await browser.getCapabilities()).getBrowserVersion()) === null || _await$browser$getCap3 === void 0 ? void 0 : _await$browser$getCap3.split('.')) ?? [];
|
231
227
|
return browserName != 'Safari' && // NOTE This need to work with keweb selenium grid
|
232
228
|
!(browserName == 'firefox' && browserVersion == '61');
|
233
229
|
}
|
@@ -278,7 +274,8 @@ async function takeCompositeScreenshot(browser, windowRect, elementRect) {
|
|
278
274
|
const scrollOffset = isFitVertically || isScreenshotWithoutScrollBar ? 0 : scrollBarWidth;
|
279
275
|
const i = (y * compositeImage.width + x) * 4;
|
280
276
|
const j = // NOTE compositeImage(x, y) => image(x, y)
|
281
|
-
(y % viewportHeight * (viewportWidth + scrollOffset) + x % viewportWidth) * 4 + (
|
277
|
+
(y % viewportHeight * (viewportWidth + scrollOffset) + x % viewportWidth) * 4 + ( // NOTE Offset for last row/col image
|
278
|
+
isLastRow ? yOffset * (viewportWidth + scrollOffset) * 4 : 0) + (isLastCol ? xOffset * 4 : 0);
|
282
279
|
const image = images[row * cols + col];
|
283
280
|
compositeImage.data[i + 0] = image.data[j + 0];
|
284
281
|
compositeImage.data[i + 1] = image.data[j + 1];
|
@@ -327,7 +324,7 @@ export async function takeScreenshot(browser, captureElement, ignoreElements) {
|
|
327
324
|
const {
|
328
325
|
elementRect,
|
329
326
|
windowRect
|
330
|
-
} = rects
|
327
|
+
} = rects ?? {};
|
331
328
|
if (!elementRect || !windowRect) throw new Error(`Couldn't find element with selector: '${captureElement}'`);
|
332
329
|
const isFitIntoViewport = elementRect.width + elementRect.left <= windowRect.width && elementRect.height + elementRect.top <= windowRect.height;
|
333
330
|
if (isFitIntoViewport) browserLogger.debug(`Capturing ${chalk.cyan(captureElement)}`);else browserLogger.debug(`Capturing composite screenshot image of ${chalk.cyan(captureElement)}`);
|
@@ -353,9 +350,9 @@ async function selectStory(browser, {
|
|
353
350
|
return callback(["Creevey can't switch story. This may happened if forget to add `creevey` addon to your storybook config, or storybook not loaded in browser due syntax error."]);
|
354
351
|
}
|
355
352
|
|
356
|
-
window.__CREEVEY_SELECT_STORY__(id, kind, name, shouldWaitForReady, callback);
|
353
|
+
void window.__CREEVEY_SELECT_STORY__(id, kind, name, shouldWaitForReady, callback);
|
357
354
|
}, id, kind, name, waitForReady);
|
358
|
-
const [errorMessage, isCaptureCalled = false] = result
|
355
|
+
const [errorMessage, isCaptureCalled = false] = result ?? [];
|
359
356
|
if (errorMessage) throw new Error(errorMessage);
|
360
357
|
return isCaptureCalled;
|
361
358
|
}
|
@@ -402,11 +399,8 @@ async function resolveCreeveyHost(browser, port) {
|
|
402
399
|
const addresses = getAddresses();
|
403
400
|
creeveyServerHost = await browser.executeAsyncScript(function (hosts, port, callback) {
|
404
401
|
void Promise.all(hosts.map(function (host) {
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
fetch('//' + host + ':' + port + '/ping').then(resolve).catch(reject);
|
409
|
-
}).then(function (response) {
|
402
|
+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
403
|
+
return fetch('http://' + host + ':' + port + '/ping').then(function (response) {
|
410
404
|
return response.text();
|
411
405
|
}).then(function (pong) {
|
412
406
|
return pong == 'pong' ? host : null;
|
@@ -498,7 +492,7 @@ export async function getBrowser(config, name) {
|
|
498
492
|
});
|
499
493
|
}, () => viewport && browser && resizeViewport(browser, viewport), () => browser && openStorybookPage(browser, realAddress, config.resolveStorybookUrl), () => browser && waitForStorybook(browser)], () => !isShuttingDown.current);
|
500
494
|
} catch (originalError) {
|
501
|
-
var
|
495
|
+
var _browser4;
|
502
496
|
|
503
497
|
if (isShuttingDown.current) {
|
504
498
|
var _browser3;
|
@@ -509,7 +503,7 @@ export async function getBrowser(config, name) {
|
|
509
503
|
}
|
510
504
|
|
511
505
|
if (originalError instanceof Error && originalError.name == 'ResolveUrlError') throw originalError;
|
512
|
-
const error = new Error(`Can't load storybook root page by URL ${(
|
506
|
+
const error = new Error(`Can't load storybook root page by URL ${(await ((_browser4 = browser) === null || _browser4 === void 0 ? void 0 : _browser4.getCurrentUrl())) ?? realAddress}`);
|
513
507
|
if (originalError instanceof Error) error.stack = originalError.stack;
|
514
508
|
throw error;
|
515
509
|
}
|
@@ -546,7 +540,7 @@ export async function closeBrowser() {
|
|
546
540
|
}
|
547
541
|
}
|
548
542
|
export async function switchStory() {
|
549
|
-
var _this$currentTest, _this$currentTest$ctx
|
543
|
+
var _this$currentTest, _this$currentTest$ctx;
|
550
544
|
|
551
545
|
let testOrSuite = this.currentTest;
|
552
546
|
if (!testOrSuite) throw new Error("Can't switch story, because test context doesn't have 'currentTest' field");
|
@@ -573,7 +567,7 @@ export async function switchStory() {
|
|
573
567
|
captureElement = '#root',
|
574
568
|
waitForReady,
|
575
569
|
ignoreElements
|
576
|
-
} =
|
570
|
+
} = parameters.creevey ?? {};
|
577
571
|
browserLogger.debug(`Switching to story ${chalk.cyan(kind)}/${chalk.cyan(name)} by id ${chalk.magenta(id)}`);
|
578
572
|
if (captureElement) Object.defineProperty(this, 'captureElement', {
|
579
573
|
enumerable: true,
|
@@ -589,8 +583,6 @@ export async function switchStory() {
|
|
589
583
|
let storyPlayResolver;
|
590
584
|
let waitForComplete = new Promise(resolve => storyPlayResolver = resolve);
|
591
585
|
const unsubscribe = subscribeOn('stories', message => {
|
592
|
-
var _payload$captureEleme, _payload$ignoreElemen;
|
593
|
-
|
594
586
|
if (message.type != 'capture') return;
|
595
587
|
const {
|
596
588
|
payload = {},
|
@@ -598,7 +590,7 @@ export async function switchStory() {
|
|
598
590
|
imageName
|
599
591
|
} = {}
|
600
592
|
} = message;
|
601
|
-
void takeScreenshot(this.browser,
|
593
|
+
void takeScreenshot(this.browser, payload.captureElement ?? captureElement, payload.ignoreElements ?? ignoreElements).then(screenshot => {
|
602
594
|
this.screenshots.push({
|
603
595
|
imageName,
|
604
596
|
screenshot
|
@@ -5,7 +5,7 @@ import { downloadBinary, getCreeveyCache } from '../utils';
|
|
5
5
|
import { pullImages, runImage } from '../docker';
|
6
6
|
import { Octokit } from '@octokit/core';
|
7
7
|
import { subscribeOn } from '../messages';
|
8
|
-
import
|
8
|
+
import cluster from 'cluster';
|
9
9
|
import { chmod, exec } from 'shelljs';
|
10
10
|
const mkdirAsync = promisify(mkdir);
|
11
11
|
const writeFileAsync = promisify(writeFile);
|
@@ -41,8 +41,6 @@ async function createSelenoidConfig(browsers, {
|
|
41
41
|
}
|
42
42
|
|
43
43
|
async function downloadSelenoidBinary(destination) {
|
44
|
-
var _assets$find;
|
45
|
-
|
46
44
|
const platformNameMapping = {
|
47
45
|
darwin: 'selenoid_darwin_amd64',
|
48
46
|
linux: 'selenoid_linux_amd64',
|
@@ -59,9 +57,9 @@ async function downloadSelenoidBinary(destination) {
|
|
59
57
|
const {
|
60
58
|
browser_download_url: downloadUrl,
|
61
59
|
size: binarySize
|
62
|
-
} =
|
60
|
+
} = assets.find(({
|
63
61
|
name
|
64
|
-
}) => platformNameMapping[process.platform] == name)
|
62
|
+
}) => platformNameMapping[process.platform] == name) ?? {};
|
65
63
|
if (existsSync(destination) && lstatSync(destination).size == binarySize) return;
|
66
64
|
|
67
65
|
if (!downloadUrl) {
|
@@ -73,7 +71,7 @@ async function downloadSelenoidBinary(destination) {
|
|
73
71
|
|
74
72
|
export async function startSelenoidStandalone(config, debug) {
|
75
73
|
config.gridUrl = 'http://localhost:4444/wd/hub';
|
76
|
-
if (isWorker) return;
|
74
|
+
if (cluster.isWorker) return;
|
77
75
|
const browsers = Object.values(config.browsers).filter(browser => !browser.gridUrl);
|
78
76
|
const selenoidConfigDir = await createSelenoidConfig(browsers, {
|
79
77
|
useDocker: false
|
@@ -8,14 +8,12 @@ import { isStorybookVersionLessThan } from './storybook/helpers';
|
|
8
8
|
|
9
9
|
function storyTestFabric(delay, testFn) {
|
10
10
|
return async function storyTest() {
|
11
|
-
var _testFn$call;
|
12
|
-
|
13
11
|
delay ? await new Promise(resolve => setTimeout(resolve, delay)) : void 0;
|
14
|
-
await (
|
12
|
+
await (testFn ? testFn.call(this) : this.screenshots.length > 0 ? this.expect(this.screenshots.reduce((screenshots, {
|
15
13
|
imageName,
|
16
14
|
screenshot
|
17
15
|
}, index) => ({ ...screenshots,
|
18
|
-
[imageName
|
16
|
+
[imageName ?? `screenshot_${index}`]: screenshot
|
19
17
|
}), {})).to.matchImages() : this.expect(await this.takeScreenshot()).to.matchImage());
|
20
18
|
};
|
21
19
|
}
|
@@ -45,15 +43,13 @@ function createCreeveyTest(browser, storyMeta, skipOptions, testName) {
|
|
45
43
|
function convertStories(browserName, stories) {
|
46
44
|
const tests = {};
|
47
45
|
(Array.isArray(stories) ? stories : Object.values(stories)).forEach(storyMeta => {
|
48
|
-
var _storyMeta$parameters;
|
49
|
-
|
50
46
|
// TODO Skip docsOnly stories for now
|
51
47
|
if (storyMeta.parameters.docsOnly) return;
|
52
48
|
const {
|
53
49
|
delay: delayParam,
|
54
50
|
tests: storyTests,
|
55
51
|
skip
|
56
|
-
} =
|
52
|
+
} = storyMeta.parameters.creevey ?? {};
|
57
53
|
const delay = typeof delayParam == 'number' ? delayParam : delayParam !== null && delayParam !== void 0 && delayParam.for.includes(browserName) ? delayParam.ms : 0; // typeof tests === "undefined" => rootSuite -> kindSuite -> storyTest -> [browsers.png]
|
58
54
|
// typeof tests === "function" => rootSuite -> kindSuite -> storyTest -> browser -> [images.png]
|
59
55
|
// typeof tests === "object" => rootSuite -> kindSuite -> storySuite -> test -> [browsers.png]
|
@@ -88,11 +84,11 @@ export async function loadTestsFromStories(browsers, provider, update) {
|
|
88
84
|
const tests = {};
|
89
85
|
browsers.forEach(browser => {
|
90
86
|
Array.from(storiesByFiles.entries()).forEach(([filename, stories]) => {
|
91
|
-
var _testIdsByFiles$get
|
87
|
+
var _testIdsByFiles$get;
|
92
88
|
|
93
89
|
Object.assign(tests, convertStories(browser, stories));
|
94
90
|
const changed = Object.keys(tests);
|
95
|
-
const removed = (
|
91
|
+
const removed = ((_testIdsByFiles$get = testIdsByFiles.get(filename)) === null || _testIdsByFiles$get === void 0 ? void 0 : _testIdsByFiles$get.filter(testId => !tests[testId])) ?? [];
|
96
92
|
if (changed.length == 0) testIdsByFiles.delete(filename);else testIdsByFiles.set(filename, changed);
|
97
93
|
Object.assign(testsDiff, tests);
|
98
94
|
removed.forEach(testId => testsDiff[testId] = undefined);
|
@@ -108,18 +104,11 @@ export async function loadTestsFromStories(browsers, provider, update) {
|
|
108
104
|
fileName
|
109
105
|
}
|
110
106
|
}
|
111
|
-
}) =>
|
112
|
-
|
113
|
-
|
114
|
-
return (// TODO Don't use filename as a key, due possible collisions if two require.context with same structure of modules are defined
|
115
|
-
testIdsByFiles.set(fileName, [...((_testIdsByFiles$get2 = testIdsByFiles.get(fileName)) !== null && _testIdsByFiles$get2 !== void 0 ? _testIdsByFiles$get2 : []), id])
|
116
|
-
);
|
117
|
-
});
|
107
|
+
}) => // TODO Don't use filename as a key, due possible collisions if two require.context with same structure of modules are defined
|
108
|
+
testIdsByFiles.set(fileName, [...(testIdsByFiles.get(fileName) ?? []), id]));
|
118
109
|
return tests;
|
119
110
|
}
|
120
111
|
export function saveStoriesJson(storiesData, extract) {
|
121
|
-
var _storiesData$stories;
|
122
|
-
|
123
112
|
const outputDir = typeof extract == 'boolean' ? 'storybook-static' : extract;
|
124
113
|
|
125
114
|
if (!isStorybookVersionLessThan(6)) {
|
@@ -135,8 +124,8 @@ export function saveStoriesJson(storiesData, extract) {
|
|
135
124
|
} // TODO Fix args stories
|
136
125
|
|
137
126
|
|
138
|
-
removeProps(storiesData
|
139
|
-
Object.values((
|
127
|
+
removeProps(storiesData ?? {}, ['stories', () => true, 'parameters', '__isArgsStory']);
|
128
|
+
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);
|
140
129
|
mkdirSync(outputDir, {
|
141
130
|
recursive: true
|
142
131
|
});
|
@@ -1,4 +1,4 @@
|
|
1
|
-
var _api$
|
1
|
+
var _api$context;
|
2
2
|
|
3
3
|
import { addons } from '@storybook/addons';
|
4
4
|
import { getStorybookFramework, isStorybookVersionLessThan, resolveFromStorybook } from './helpers';
|
@@ -10,7 +10,9 @@ const core = require(resolveFromStorybook('@storybook/core')); //@ts-expect-erro
|
|
10
10
|
|
11
11
|
const start = isStorybookVersionLessThan(6, 2) ? core.default.start : core.start;
|
12
12
|
const api = start(() => void 0);
|
13
|
-
export const channel = isStorybookVersionLessThan(6, 4) ?
|
13
|
+
export const channel = isStorybookVersionLessThan(6, 4) ? //@ts-expect-error: 6.x has { channel }, but 5.x has { context: { channel } }
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
15
|
+
api.channel ?? ((_api$context = api.context) === null || _api$context === void 0 ? void 0 : _api$context.channel) : addons.getChannel();
|
14
16
|
export const clientApi = api.clientApi;
|
15
17
|
export const forceReRender = api.forceReRender;
|
16
18
|
export const storiesOf = (kind, m) => {
|
@@ -35,32 +35,24 @@ export function getStorybookVersion() {
|
|
35
35
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
36
36
|
const {
|
37
37
|
version
|
38
|
-
} = require(resolveFromStorybook('@storybook/core/package.json'));
|
38
|
+
} = require(resolveFromStorybook('@storybook/core-server/package.json'));
|
39
39
|
|
40
40
|
return version;
|
41
41
|
}
|
42
42
|
export function isStorybookVersionLessThan(major, minor) {
|
43
|
-
|
44
|
-
|
45
|
-
const [sbMajor, sbMinor] = ((_process$env$__CREEVE = process.env.__CREEVEY_STORYBOOK_VERSION__) !== null && _process$env$__CREEVE !== void 0 ? _process$env$__CREEVE : getStorybookVersion()).split('.');
|
43
|
+
const [sbMajor, sbMinor] = (process.env.__CREEVEY_STORYBOOK_VERSION__ ?? getStorybookVersion()).split('.');
|
46
44
|
return Number(sbMajor) < major || minor != undefined && Number(sbMajor) == major && Number(sbMinor) < minor;
|
47
45
|
}
|
48
46
|
export function isStorybookVersionGreaterThan(major, minor) {
|
49
|
-
|
50
|
-
|
51
|
-
const [sbMajor, sbMinor] = ((_process$env$__CREEVE2 = process.env.__CREEVEY_STORYBOOK_VERSION__) !== null && _process$env$__CREEVE2 !== void 0 ? _process$env$__CREEVE2 : getStorybookVersion()).split('.');
|
47
|
+
const [sbMajor, sbMinor] = (process.env.__CREEVEY_STORYBOOK_VERSION__ ?? getStorybookVersion()).split('.');
|
52
48
|
return Number(sbMajor) > major || minor != undefined && Number(sbMajor) == major && Number(sbMinor) > minor;
|
53
49
|
}
|
54
50
|
export function isStorybookVersion(major, minor) {
|
55
|
-
|
56
|
-
|
57
|
-
const [sbMajor, sbMinor] = ((_process$env$__CREEVE3 = process.env.__CREEVEY_STORYBOOK_VERSION__) !== null && _process$env$__CREEVE3 !== void 0 ? _process$env$__CREEVE3 : getStorybookVersion()).split('.');
|
51
|
+
const [sbMajor, sbMinor] = (process.env.__CREEVEY_STORYBOOK_VERSION__ ?? getStorybookVersion()).split('.');
|
58
52
|
return Number(sbMajor) == major || minor != undefined && Number(sbMajor) == major && Number(sbMinor) == minor;
|
59
53
|
}
|
60
54
|
export function getStorybookFramework() {
|
61
|
-
|
62
|
-
|
63
|
-
const framework = (_process$env$__CREEVE4 = process.env.__CREEVEY_STORYBOOK_FRAMEWORK__) !== null && _process$env$__CREEVE4 !== void 0 ? _process$env$__CREEVE4 : supportedFrameworks.find(framework => {
|
55
|
+
const framework = process.env.__CREEVEY_STORYBOOK_FRAMEWORK__ ?? supportedFrameworks.find(framework => {
|
64
56
|
try {
|
65
57
|
return require.resolve(resolveFromStorybook(`@storybook/${framework}`));
|
66
58
|
} catch (_) {
|
@@ -100,7 +92,7 @@ export async function importStorybookConfig() {
|
|
100
92
|
}
|
101
93
|
}
|
102
94
|
export async function isCSFv3Enabled() {
|
103
|
-
var _await$importStoryboo, _await$importStoryboo2
|
95
|
+
var _await$importStoryboo, _await$importStoryboo2;
|
104
96
|
|
105
|
-
return (_await$importStoryboo =
|
97
|
+
return ((_await$importStoryboo = await importStorybookConfig()) === null || _await$importStoryboo === void 0 ? void 0 : (_await$importStoryboo2 = _await$importStoryboo.features) === null || _await$importStoryboo2 === void 0 ? void 0 : _await$importStoryboo2.previewCsfV3) ?? false;
|
106
98
|
}
|
@@ -1,15 +1,14 @@
|
|
1
|
-
import cluster
|
1
|
+
import cluster from 'cluster';
|
2
2
|
import { loadStoriesFromBrowser } from '../../selenium';
|
3
3
|
import { emitStoriesMessage, sendStoriesMessage, subscribeOn, subscribeOnWorker } from '../../messages';
|
4
|
-
import { deserializeRawStories } from '../../../shared';
|
5
4
|
import { isDefined } from '../../../types';
|
6
5
|
import { logger } from '../../logger';
|
7
6
|
export async function loadStories(_config, {
|
8
7
|
port
|
9
8
|
}, storiesListener) {
|
10
|
-
if (
|
9
|
+
if (cluster.isPrimary) {
|
11
10
|
return new Promise(resolve => {
|
12
|
-
const worker = Object.values(cluster.workers).filter(isDefined).find(worker => worker.isConnected());
|
11
|
+
const worker = Object.values(cluster.workers ?? {}).filter(isDefined).find(worker => worker.isConnected());
|
13
12
|
|
14
13
|
if (worker) {
|
15
14
|
const unsubscribe = subscribeOnWorker(worker, 'stories', message => {
|
@@ -44,7 +43,7 @@ export async function loadStories(_config, {
|
|
44
43
|
});
|
45
44
|
if (message.type == 'update') storiesListener(new Map(message.payload));
|
46
45
|
});
|
47
|
-
const stories =
|
46
|
+
const stories = await loadStoriesFromBrowser(port);
|
48
47
|
const storiesWithOldTests = [];
|
49
48
|
Object.values(stories).forEach(story => {
|
50
49
|
var _parameters, _parameters$creevey;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/ban-ts-comment */
|
2
2
|
import path from 'path';
|
3
|
-
import
|
3
|
+
import cluster from 'cluster';
|
4
4
|
import chokidar from 'chokidar';
|
5
5
|
import { noop } from '../../../types';
|
6
6
|
import { getCreeveyCache } from '../../utils';
|
@@ -25,7 +25,7 @@ async function initStorybookEnvironment() {
|
|
25
25
|
logger
|
26
26
|
} = await importStorybookClientLogger(); // NOTE: Disable duplication warnings for >=6.2 storybook
|
27
27
|
|
28
|
-
if (isWorker) logger.warn = noop; // NOTE: disable logger for 5.x storybook
|
28
|
+
if (cluster.isWorker) logger.warn = noop; // NOTE: disable logger for 5.x storybook
|
29
29
|
|
30
30
|
logger.debug = noop;
|
31
31
|
return import('../entry');
|
@@ -154,7 +154,7 @@ async function loadStoriesDirectly(config, {
|
|
154
154
|
try {
|
155
155
|
configure(contexts.map(ctx => ctx()), module, false);
|
156
156
|
} catch (error) {
|
157
|
-
if (
|
157
|
+
if (cluster.isPrimary) logger.error(error);
|
158
158
|
}
|
159
159
|
}
|
160
160
|
|
package/lib/esm/server/update.js
CHANGED
@@ -15,11 +15,7 @@ function tryToLoadTestsData(filename) {
|
|
15
15
|
const actualRegex = /^(.*)-actual-(\d+)\.png$/i;
|
16
16
|
|
17
17
|
function approve(dirents, srcPath, dstPath, testPaths, isMatch) {
|
18
|
-
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]) => {
|
19
|
-
var _images$get;
|
20
|
-
|
21
|
-
return Number(retry) > ((_images$get = images.get(imageName)) !== null && _images$get !== void 0 ? _images$get : -1) ? images.set(imageName, Number(retry)) : images;
|
22
|
-
}, new Map()).forEach((retry, imageName) => {
|
18
|
+
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) => {
|
23
19
|
mkdirSync(dstPath, {
|
24
20
|
recursive: true
|
25
21
|
});
|
package/lib/esm/server/utils.js
CHANGED
@@ -64,7 +64,7 @@ export function shouldSkip(browser, meta, skipOptions, test) {
|
|
64
64
|
}
|
65
65
|
export async function shutdownWorkers() {
|
66
66
|
isShuttingDown.current = true;
|
67
|
-
await Promise.all(Object.values(cluster.workers).filter(isDefined).filter(worker => worker.isConnected()).map(worker => new Promise(resolve => {
|
67
|
+
await Promise.all(Object.values(cluster.workers ?? {}).filter(isDefined).filter(worker => worker.isConnected()).map(worker => new Promise(resolve => {
|
68
68
|
const timeout = setTimeout(() => worker.kill(), 10000);
|
69
69
|
worker.on('exit', () => {
|
70
70
|
clearTimeout(timeout);
|
@@ -96,27 +96,23 @@ export function testsToImages(tests) {
|
|
96
96
|
storyPath,
|
97
97
|
results
|
98
98
|
}) => {
|
99
|
-
var _results$slice
|
99
|
+
var _results$slice$;
|
100
100
|
|
101
|
-
return Object.keys((
|
101
|
+
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
102
|
})));
|
103
103
|
} // https://tuhrig.de/how-to-know-you-are-inside-a-docker-container/
|
104
104
|
|
105
105
|
export const isInsideDocker = existsSync('/proc/1/cgroup') && /docker/.test(readFileSync('/proc/1/cgroup', 'utf8'));
|
106
106
|
export const downloadBinary = (downloadUrl, destination) => new Promise((resolve, reject) => get(downloadUrl, response => {
|
107
|
-
var _response$statusCode2;
|
108
|
-
|
109
107
|
if (response.statusCode == 302) {
|
110
|
-
var _response$statusCode;
|
111
|
-
|
112
108
|
const {
|
113
109
|
location
|
114
110
|
} = response.headers;
|
115
|
-
if (!location) return reject(new Error(`Couldn't download selenoid. Status code: ${
|
111
|
+
if (!location) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
|
116
112
|
return resolve(downloadBinary(location, destination));
|
117
113
|
}
|
118
114
|
|
119
|
-
if (response.statusCode != 200) return reject(new Error(`Couldn't download selenoid. Status code: ${
|
115
|
+
if (response.statusCode != 200) return reject(new Error(`Couldn't download selenoid. Status code: ${response.statusCode ?? 'UNKNOWN'}`));
|
120
116
|
const fileStream = createWriteStream(destination);
|
121
117
|
response.pipe(fileStream);
|
122
118
|
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;
|