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
@@ -0,0 +1,34 @@
|
|
1
|
+
/*
|
2
|
+
object-assign
|
3
|
+
(c) Sindre Sorhus
|
4
|
+
@license MIT
|
5
|
+
*/
|
6
|
+
|
7
|
+
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
8
|
+
|
9
|
+
/** @license React v0.20.2
|
10
|
+
* scheduler.production.min.js
|
11
|
+
*
|
12
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
13
|
+
*
|
14
|
+
* This source code is licensed under the MIT license found in the
|
15
|
+
* LICENSE file in the root directory of this source tree.
|
16
|
+
*/
|
17
|
+
|
18
|
+
/** @license React v17.0.2
|
19
|
+
* react-dom.production.min.js
|
20
|
+
*
|
21
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
22
|
+
*
|
23
|
+
* This source code is licensed under the MIT license found in the
|
24
|
+
* LICENSE file in the root directory of this source tree.
|
25
|
+
*/
|
26
|
+
|
27
|
+
/** @license React v17.0.2
|
28
|
+
* react.production.min.js
|
29
|
+
*
|
30
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
31
|
+
*
|
32
|
+
* This source code is licensed under the MIT license found in the
|
33
|
+
* LICENSE file in the root directory of this source tree.
|
34
|
+
*/
|
package/lib/esm/creevey.js
CHANGED
@@ -6,7 +6,6 @@ import { emitWorkerMessage } from './server/messages';
|
|
6
6
|
import { isShuttingDown, shutdown, shutdownWorkers } from './server/utils';
|
7
7
|
import { setDefaultLevel, levels } from 'loglevel';
|
8
8
|
import { logger } from './server/logger';
|
9
|
-
|
10
9
|
function shutdownOnException(reason) {
|
11
10
|
if (isShuttingDown.current) return;
|
12
11
|
const error = reason instanceof Error ? reason.stack ?? reason.message : reason;
|
@@ -20,14 +19,13 @@ function shutdownOnException(reason) {
|
|
20
19
|
});
|
21
20
|
if (cluster.isPrimary && !isShuttingDown.current) void shutdownWorkers();
|
22
21
|
}
|
23
|
-
|
24
22
|
process.on('uncaughtException', shutdownOnException);
|
25
23
|
process.on('unhandledRejection', shutdownOnException);
|
26
24
|
if (cluster.isWorker) process.on('SIGINT', noop);
|
27
25
|
if (cluster.isPrimary) process.on('SIGINT', shutdown);
|
28
26
|
const argv = minimist(process.argv.slice(2), {
|
29
27
|
string: ['browser', 'config', 'reporter', 'reportDir', 'screenDir'],
|
30
|
-
boolean: ['debug', 'ui', 'saveReport', '
|
28
|
+
boolean: ['debug', 'ui', 'saveReport', 'tests'],
|
31
29
|
default: {
|
32
30
|
port: 3000,
|
33
31
|
saveReport: true
|
@@ -36,13 +34,12 @@ const argv = minimist(process.argv.slice(2), {
|
|
36
34
|
port: 'p',
|
37
35
|
config: 'c',
|
38
36
|
debug: 'd',
|
39
|
-
update: 'u'
|
40
|
-
extract: 'e'
|
37
|
+
update: 'u'
|
41
38
|
}
|
42
|
-
});
|
39
|
+
});
|
43
40
|
|
41
|
+
// @ts-expect-error: define log level for storybook
|
44
42
|
global.LOGLEVEL = argv.debug ? 'debug' : 'warn';
|
45
|
-
|
46
43
|
if (argv.debug) {
|
47
44
|
logger.setDefaultLevel(levels.DEBUG);
|
48
45
|
setDefaultLevel(levels.DEBUG);
|
@@ -50,5 +47,4 @@ if (argv.debug) {
|
|
50
47
|
logger.setDefaultLevel(levels.INFO);
|
51
48
|
setDefaultLevel(levels.INFO);
|
52
49
|
}
|
53
|
-
|
54
50
|
void creevey(argv);
|
package/lib/esm/index.js
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
export * from './types';
|
2
2
|
export { loadStories as browserStoriesProvider } from './server/storybook/providers/browser';
|
3
|
-
export { loadStories as nodejsStoriesProvider } from './server/storybook/providers/nodejs';
|
4
3
|
export { loadStories as hybridStoriesProvider } from './server/storybook/providers/hybrid';
|
5
4
|
export * from './server/testsFiles/parser';
|
package/lib/esm/server/config.js
CHANGED
@@ -1,13 +1,10 @@
|
|
1
1
|
import fs from 'fs';
|
2
2
|
import path from 'path';
|
3
|
-
import { isCSFv3Enabled, storybookDirRef } from './storybook/helpers';
|
4
|
-
import { loadStories as nodejsStoriesProvider } from './storybook/providers/nodejs';
|
5
3
|
import { loadStories as browserStoriesProvider } from './storybook/providers/browser';
|
6
4
|
import { isDefined } from '../types';
|
7
5
|
export const defaultBrowser = 'chrome';
|
8
6
|
export const defaultConfig = {
|
9
7
|
useDocker: true,
|
10
|
-
useWebpackToExtractTests: false,
|
11
8
|
dockerImage: 'aerokube/selenoid:latest-release',
|
12
9
|
dockerImagePlatform: '',
|
13
10
|
pullImages: true,
|
@@ -15,7 +12,6 @@ export const defaultConfig = {
|
|
15
12
|
storybookUrl: 'http://localhost:6006',
|
16
13
|
screenDir: path.resolve('images'),
|
17
14
|
reportDir: path.resolve('report'),
|
18
|
-
storybookDir: path.resolve('.storybook'),
|
19
15
|
maxRetries: 0,
|
20
16
|
diffOptions: {
|
21
17
|
threshold: 0,
|
@@ -28,7 +24,6 @@ export const defaultConfig = {
|
|
28
24
|
babelOptions: _ => _,
|
29
25
|
testsRegex: /\.creevey\.(t|j)s$/
|
30
26
|
};
|
31
|
-
|
32
27
|
function normalizeBrowserConfig(name, config) {
|
33
28
|
if (typeof config == 'boolean') return {
|
34
29
|
browserName: name
|
@@ -38,33 +33,31 @@ function normalizeBrowserConfig(name, config) {
|
|
38
33
|
};
|
39
34
|
return config;
|
40
35
|
}
|
41
|
-
|
42
36
|
function resolveConfigPath(configPath) {
|
43
37
|
const rootDir = process.cwd();
|
44
38
|
const configDir = path.resolve('.creevey');
|
45
|
-
|
46
39
|
if (isDefined(configPath)) {
|
47
40
|
configPath = path.resolve(configPath);
|
48
41
|
} else if (fs.existsSync(configDir)) {
|
49
|
-
configPath = path.join(configDir, 'config');
|
42
|
+
configPath = path.join(configDir, 'config');
|
43
|
+
// TODO We already find file with extension, why not use it?
|
50
44
|
} else if (fs.readdirSync(rootDir).find(filename => filename.startsWith('creevey.config'))) {
|
51
45
|
configPath = path.join(rootDir, 'creevey.config');
|
52
46
|
}
|
53
|
-
|
54
47
|
return configPath;
|
55
48
|
}
|
56
|
-
|
57
49
|
export async function readConfig(options) {
|
58
50
|
const configPath = resolveConfigPath(options.config);
|
59
|
-
const userConfig = {
|
51
|
+
const userConfig = {
|
52
|
+
...defaultConfig
|
60
53
|
};
|
61
54
|
if (isDefined(configPath)) Object.assign(userConfig, (await import(configPath)).default);
|
62
|
-
|
63
|
-
if (!userConfig.storiesProvider) userConfig.storiesProvider = (await isCSFv3Enabled()) ? browserStoriesProvider : nodejsStoriesProvider;
|
55
|
+
if (!userConfig.storiesProvider) userConfig.storiesProvider = browserStoriesProvider;
|
64
56
|
if (options.failFast != undefined) userConfig.failFast = Boolean(options.failFast);
|
65
57
|
if (options.reportDir) userConfig.reportDir = path.resolve(options.reportDir);
|
66
|
-
if (options.screenDir) userConfig.screenDir = path.resolve(options.screenDir);
|
58
|
+
if (options.screenDir) userConfig.screenDir = path.resolve(options.screenDir);
|
67
59
|
|
60
|
+
// NOTE: Hack to pass typescript checking
|
68
61
|
const config = userConfig;
|
69
62
|
Object.entries(config.browsers).forEach(([browser, browserConfig]) => config.browsers[browser] = normalizeBrowserConfig(browser, browserConfig));
|
70
63
|
return config;
|
package/lib/esm/server/docker.js
CHANGED
@@ -7,14 +7,11 @@ import { Writable } from 'stream';
|
|
7
7
|
import ora from 'ora';
|
8
8
|
import { logger } from './logger';
|
9
9
|
const docker = new Dockerode();
|
10
|
-
|
11
10
|
class DevNull extends Writable {
|
12
11
|
_write(_chunk, _encoding, callback) {
|
13
12
|
setImmediate(callback);
|
14
13
|
}
|
15
|
-
|
16
14
|
}
|
17
|
-
|
18
15
|
export async function pullImages(images, {
|
19
16
|
auth,
|
20
17
|
platform
|
@@ -23,30 +20,27 @@ export async function pullImages(images, {
|
|
23
20
|
if (auth) args.authconfig = auth;
|
24
21
|
if (platform) args.platform = platform;
|
25
22
|
logger.info('Pull docker images');
|
26
|
-
|
27
23
|
for (const image of images) {
|
28
24
|
await new Promise((resolve, reject) => {
|
29
|
-
const spinner = ora(`${image}: Pull start`).start();
|
25
|
+
const spinner = ora(`${image}: Pull start`).start();
|
30
26
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
31
28
|
docker.pull(image, args, function (pullError, stream) {
|
32
29
|
if (pullError) {
|
33
30
|
spinner.fail();
|
34
31
|
return reject(pullError);
|
35
|
-
}
|
36
|
-
|
32
|
+
}
|
37
33
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
38
35
|
docker.modem.followProgress(stream, onFinished, onProgress);
|
39
|
-
|
40
36
|
function onFinished(error) {
|
41
37
|
if (error) {
|
42
38
|
spinner.fail();
|
43
39
|
return reject(error);
|
44
40
|
}
|
45
|
-
|
46
41
|
spinner.succeed(`${image}: Pull complete`);
|
47
42
|
resolve();
|
48
43
|
}
|
49
|
-
|
50
44
|
function onProgress(event) {
|
51
45
|
if (!/^[a-z0-9]{12}$/i.test(event.id)) return;
|
52
46
|
spinner.text = `${image}: [${event.id}] ${event.status} ${event.progress ? `${event.progress}` : ''}`;
|
@@ -63,13 +57,11 @@ export async function runImage(image, args, options, debug) {
|
|
63
57
|
}
|
64
58
|
})).map(async info => {
|
65
59
|
const container = docker.getContainer(info.Id);
|
66
|
-
|
67
60
|
try {
|
68
61
|
await container.stop();
|
69
62
|
} catch (_) {
|
70
63
|
/* noop */
|
71
64
|
}
|
72
|
-
|
73
65
|
await container.remove();
|
74
66
|
}));
|
75
67
|
const hub = docker.run(image, args, debug ? process.stdout : new DevNull(), options, error => {
|
package/lib/esm/server/index.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import cluster from 'cluster';
|
2
2
|
import { readConfig, defaultBrowser } from './config';
|
3
|
-
import { logger } from './logger';
|
3
|
+
import { logger } from './logger';
|
4
4
|
|
5
|
+
// NOTE: Impure function, mutate config by adding gridUrl prop
|
5
6
|
async function startWebdriverServer(config, options) {
|
6
7
|
if (config.useDocker) {
|
7
8
|
return (await import('./docker')).default(config, options.browser, async () => (await import('./selenium/selenoid')).startSelenoidContainer(config, options.debug));
|
@@ -9,54 +10,39 @@ async function startWebdriverServer(config, options) {
|
|
9
10
|
return (await import('./selenium/selenoid')).startSelenoidStandalone(config, options.debug);
|
10
11
|
}
|
11
12
|
}
|
12
|
-
|
13
13
|
export default async function (options) {
|
14
14
|
const config = await readConfig(options);
|
15
15
|
const {
|
16
16
|
browser = defaultBrowser,
|
17
|
-
extract,
|
18
17
|
tests,
|
19
18
|
update,
|
20
|
-
webpack,
|
21
19
|
ui,
|
22
20
|
port
|
23
21
|
} = options;
|
24
|
-
if (!config) return;
|
22
|
+
if (!config) return;
|
25
23
|
|
24
|
+
// NOTE: We don't need docker nor selenoid for webpack or update options
|
26
25
|
if (!(config.gridUrl || Object.values(config.browsers).every(({
|
27
26
|
gridUrl
|
28
|
-
}) => gridUrl)) && !
|
27
|
+
}) => gridUrl)) && !tests && !update) {
|
29
28
|
await startWebdriverServer(config, options);
|
30
29
|
}
|
31
|
-
|
32
30
|
switch (true) {
|
33
|
-
case Boolean(extract) || tests:
|
34
|
-
{
|
35
|
-
return (await import('./extract')).default(config, options);
|
36
|
-
}
|
37
|
-
|
38
31
|
case Boolean(update):
|
39
32
|
{
|
40
33
|
return (await import('./update')).default(config, typeof update == 'string' ? update : undefined);
|
41
34
|
}
|
42
|
-
|
43
|
-
case webpack:
|
44
|
-
{
|
45
|
-
logger.info('Starting Webpack Compiler');
|
46
|
-
return (await import('./loaders/webpack/compile')).default(config, options);
|
47
|
-
}
|
48
|
-
|
49
35
|
case cluster.isPrimary:
|
50
36
|
{
|
51
37
|
logger.info('Starting Master Process');
|
52
38
|
const resolveApi = (await import('./master/server')).default(config.reportDir, port, ui);
|
53
39
|
return (await import('./master')).default(config, options, resolveApi);
|
54
40
|
}
|
55
|
-
|
56
41
|
default:
|
57
42
|
{
|
58
43
|
logger.info(`Starting Worker for ${browser}`);
|
59
|
-
return (await import('./worker')).default(config, {
|
44
|
+
return (await import('./worker')).default(config, {
|
45
|
+
...options,
|
60
46
|
browser
|
61
47
|
});
|
62
48
|
}
|
package/lib/esm/server/logger.js
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import WebSocket from 'ws';
|
2
2
|
import { logger } from '../logger';
|
3
|
-
|
4
3
|
function broadcast(wss, message) {
|
5
4
|
wss.clients.forEach(ws => {
|
6
5
|
if (ws.readyState === WebSocket.OPEN) {
|
@@ -8,7 +7,6 @@ function broadcast(wss, message) {
|
|
8
7
|
}
|
9
8
|
});
|
10
9
|
}
|
11
|
-
|
12
10
|
export default function creeveyApi(runner) {
|
13
11
|
return {
|
14
12
|
subscribe(wss) {
|
@@ -17,15 +15,12 @@ export default function creeveyApi(runner) {
|
|
17
15
|
payload
|
18
16
|
}));
|
19
17
|
},
|
20
|
-
|
21
18
|
handleMessage(ws, message) {
|
22
19
|
if (typeof message != 'string') {
|
23
20
|
logger.info('unhandled message', message);
|
24
21
|
return;
|
25
22
|
}
|
26
|
-
|
27
23
|
const command = JSON.parse(message);
|
28
|
-
|
29
24
|
switch (command.type) {
|
30
25
|
case 'status':
|
31
26
|
{
|
@@ -35,19 +30,16 @@ export default function creeveyApi(runner) {
|
|
35
30
|
}));
|
36
31
|
return;
|
37
32
|
}
|
38
|
-
|
39
33
|
case 'start':
|
40
34
|
{
|
41
35
|
runner.start(command.payload);
|
42
36
|
return;
|
43
37
|
}
|
44
|
-
|
45
38
|
case 'stop':
|
46
39
|
{
|
47
40
|
runner.stop();
|
48
41
|
return;
|
49
42
|
}
|
50
|
-
|
51
43
|
case 'approve':
|
52
44
|
{
|
53
45
|
void runner.approve(command.payload);
|
@@ -55,6 +47,5 @@ export default function creeveyApi(runner) {
|
|
55
47
|
}
|
56
48
|
}
|
57
49
|
}
|
58
|
-
|
59
50
|
};
|
60
51
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import path from 'path';
|
2
|
-
import {
|
2
|
+
import { copyFile, readdir, mkdir, existsSync, writeFile } from 'fs';
|
3
3
|
import { promisify } from 'util';
|
4
4
|
import master from './master';
|
5
5
|
import creeveyApi from './api';
|
@@ -7,10 +7,10 @@ import { isDefined } from '../../types';
|
|
7
7
|
import { shutdown, shutdownWorkers, testsToImages, readDirRecursive } from '../utils';
|
8
8
|
import { subscribeOn } from '../messages';
|
9
9
|
import { logger } from '../logger';
|
10
|
+
const writeFileAsync = promisify(writeFile);
|
10
11
|
const copyFileAsync = promisify(copyFile);
|
11
12
|
const readdirAsync = promisify(readdir);
|
12
13
|
const mkdirAsync = promisify(mkdir);
|
13
|
-
|
14
14
|
async function copyStatics(reportDir) {
|
15
15
|
const clientDir = path.join(__dirname, '../../client/web');
|
16
16
|
const files = (await readdirAsync(clientDir, {
|
@@ -19,12 +19,10 @@ async function copyStatics(reportDir) {
|
|
19
19
|
await mkdirAsync(reportDir, {
|
20
20
|
recursive: true
|
21
21
|
});
|
22
|
-
|
23
22
|
for (const file of files) {
|
24
23
|
await copyFileAsync(path.join(clientDir, file), path.join(reportDir, file));
|
25
24
|
}
|
26
25
|
}
|
27
|
-
|
28
26
|
function reportDataModule(data) {
|
29
27
|
return `
|
30
28
|
(function (root, factory) {
|
@@ -36,44 +34,34 @@ function reportDataModule(data) {
|
|
36
34
|
}(this, function () { return ${JSON.stringify(data)} }));
|
37
35
|
`;
|
38
36
|
}
|
39
|
-
|
40
37
|
function outputUnnecessaryImages(imagesDir, images) {
|
41
38
|
if (!existsSync(imagesDir)) return;
|
42
39
|
const unnecessaryImages = readDirRecursive(imagesDir).map(imagePath => path.posix.relative(imagesDir, imagePath)).filter(imagePath => !images.has(imagePath));
|
43
|
-
|
44
40
|
if (unnecessaryImages.length > 0) {
|
45
41
|
logger.warn('We found unnecessary screenshot images, those can be safely removed:\n', unnecessaryImages.join('\n'));
|
46
42
|
}
|
47
43
|
}
|
48
|
-
|
49
44
|
export default async function (config, options, resolveApi) {
|
50
45
|
let runner = null;
|
51
|
-
|
52
46
|
if (config.hooks.before) {
|
53
47
|
await config.hooks.before();
|
54
48
|
}
|
55
|
-
|
56
49
|
subscribeOn('shutdown', () => {
|
57
50
|
var _config$hooks$after, _config$hooks;
|
58
|
-
|
59
51
|
return (_config$hooks$after = (_config$hooks = config.hooks).after) === null || _config$hooks$after === void 0 ? void 0 : _config$hooks$after.call(_config$hooks);
|
60
52
|
});
|
61
53
|
process.removeListener('SIGINT', shutdown);
|
62
54
|
process.on('SIGINT', () => {
|
63
55
|
var _runner, _runner2;
|
64
|
-
|
65
|
-
(_runner = runner) === null || _runner === void 0 ? void 0 : _runner.removeAllListeners('stop');
|
66
|
-
|
56
|
+
(_runner = runner) === null || _runner === void 0 || _runner.removeAllListeners('stop');
|
67
57
|
if ((_runner2 = runner) !== null && _runner2 !== void 0 && _runner2.isRunning) {
|
68
58
|
var _runner4;
|
69
|
-
|
70
59
|
// TODO Better handle stop
|
71
60
|
void Promise.race([new Promise(resolve => setTimeout(resolve, 10000)), new Promise(resolve => {
|
72
61
|
var _runner3;
|
73
|
-
|
74
62
|
return (_runner3 = runner) === null || _runner3 === void 0 ? void 0 : _runner3.once('stop', resolve);
|
75
63
|
})]).then(() => shutdownWorkers());
|
76
|
-
(_runner4 = runner) === null || _runner4 === void 0
|
64
|
+
(_runner4 = runner) === null || _runner4 === void 0 || _runner4.stop();
|
77
65
|
} else {
|
78
66
|
void shutdownWorkers();
|
79
67
|
}
|
@@ -83,43 +71,38 @@ export default async function (config, options, resolveApi) {
|
|
83
71
|
debug: options.debug,
|
84
72
|
port: options.port
|
85
73
|
});
|
86
|
-
|
87
74
|
if (options.saveReport) {
|
88
|
-
|
89
|
-
runner.on('stop', () => {
|
75
|
+
runner.on('stop', async () => {
|
90
76
|
var _runner5;
|
91
|
-
|
92
|
-
|
77
|
+
await copyStatics(config.reportDir);
|
78
|
+
await writeFileAsync(path.join(config.reportDir, 'data.js'), reportDataModule((_runner5 = runner) === null || _runner5 === void 0 ? void 0 : _runner5.status.tests));
|
93
79
|
});
|
94
80
|
}
|
95
|
-
|
96
81
|
if (options.ui) {
|
97
82
|
resolveApi(creeveyApi(runner));
|
98
83
|
logger.info(`Started on http://localhost:${options.port}`);
|
99
84
|
} else {
|
100
85
|
if (Object.values(runner.status.tests).filter(test => test && !test.skip).length == 0) {
|
101
|
-
logger.warn("Don't have any tests to run");
|
102
|
-
|
86
|
+
logger.warn("Don't have any tests to run");
|
87
|
+
// eslint-disable-next-line no-process-exit
|
103
88
|
void shutdownWorkers().then(() => process.exit());
|
104
89
|
return;
|
105
90
|
}
|
106
|
-
|
107
91
|
runner.once('stop', () => {
|
108
92
|
var _runner6;
|
109
|
-
|
110
93
|
const tests = Object.values(((_runner6 = runner) === null || _runner6 === void 0 ? void 0 : _runner6.status.tests) ?? {});
|
111
94
|
const isSuccess = tests.filter(isDefined).filter(({
|
112
95
|
skip
|
113
96
|
}) => !skip).every(({
|
114
97
|
status
|
115
|
-
}) => status == 'success');
|
116
|
-
|
98
|
+
}) => status == 'success');
|
99
|
+
// TODO output summary
|
117
100
|
process.exitCode = isSuccess ? 0 : -1;
|
118
|
-
if (!config.failFast) outputUnnecessaryImages(config.screenDir, testsToImages(tests));
|
119
|
-
|
101
|
+
if (!config.failFast) outputUnnecessaryImages(config.screenDir, testsToImages(tests));
|
102
|
+
// eslint-disable-next-line no-process-exit
|
120
103
|
void shutdownWorkers().then(() => process.exit());
|
121
|
-
});
|
122
|
-
|
104
|
+
});
|
105
|
+
// TODO grep
|
123
106
|
runner.start(Object.keys(runner.status.tests));
|
124
107
|
}
|
125
108
|
}
|
@@ -2,8 +2,6 @@ import path from 'path';
|
|
2
2
|
import { isDefined } from '../../types';
|
3
3
|
import { loadTestsFromStories, saveTestsJson } from '../stories';
|
4
4
|
import Runner from './runner';
|
5
|
-
import { startWebpackCompiler } from '../loaders/webpack/start';
|
6
|
-
|
7
5
|
function mergeTests(testsWithReports, testsFromStories) {
|
8
6
|
Object.values(testsFromStories).filter(isDefined).forEach(test => {
|
9
7
|
const testWithReport = testsWithReports[test.id];
|
@@ -15,18 +13,15 @@ function mergeTests(testsWithReports, testsFromStories) {
|
|
15
13
|
});
|
16
14
|
return testsFromStories;
|
17
15
|
}
|
18
|
-
|
19
16
|
export default async function master(config, options) {
|
20
|
-
if (config.useWebpackToExtractTests) await startWebpackCompiler();
|
21
17
|
const runner = new Runner(config);
|
22
18
|
const reportDataPath = path.join(config.reportDir, 'data.js');
|
23
19
|
let testsFromReport = {};
|
24
|
-
|
25
20
|
try {
|
26
21
|
testsFromReport = await import(reportDataPath);
|
27
|
-
} catch (error) {
|
22
|
+
} catch (error) {
|
23
|
+
// Ignore error
|
28
24
|
}
|
29
|
-
|
30
25
|
await runner.init();
|
31
26
|
const tests = await loadTestsFromStories(Object.keys(config.browsers), listener => config.storiesProvider(config, options, listener), testsDiff => {
|
32
27
|
runner.updateTests(testsDiff);
|
@@ -8,11 +8,9 @@ export default class Pool extends EventEmitter {
|
|
8
8
|
workers = [];
|
9
9
|
queue = [];
|
10
10
|
forcedStop = false;
|
11
|
-
|
12
11
|
get isRunning() {
|
13
12
|
return this.workers.length !== this.freeWorkers.length;
|
14
13
|
}
|
15
|
-
|
16
14
|
constructor(config, browser) {
|
17
15
|
super();
|
18
16
|
this.browser = browser;
|
@@ -20,7 +18,6 @@ export default class Pool extends EventEmitter {
|
|
20
18
|
this.maxRetries = config.maxRetries;
|
21
19
|
this.config = config.browsers[browser];
|
22
20
|
}
|
23
|
-
|
24
21
|
async init() {
|
25
22
|
const poolSize = this.config.limit || 1;
|
26
23
|
this.workers = (await Promise.all(Array.from({
|
@@ -29,7 +26,6 @@ export default class Pool extends EventEmitter {
|
|
29
26
|
if (this.workers.length != poolSize) throw new Error(`Can't instantiate workers for ${this.browser} due many errors`);
|
30
27
|
this.workers.forEach(worker => this.exitHandler(worker));
|
31
28
|
}
|
32
|
-
|
33
29
|
start(tests) {
|
34
30
|
if (this.isRunning) return false;
|
35
31
|
this.queue = tests.map(({
|
@@ -43,27 +39,22 @@ export default class Pool extends EventEmitter {
|
|
43
39
|
this.process();
|
44
40
|
return true;
|
45
41
|
}
|
46
|
-
|
47
42
|
stop() {
|
48
43
|
if (!this.isRunning) {
|
49
44
|
this.emit('stop');
|
50
45
|
return;
|
51
46
|
}
|
52
|
-
|
53
47
|
this.forcedStop = true;
|
54
48
|
this.queue = [];
|
55
49
|
}
|
56
|
-
|
57
50
|
process() {
|
58
51
|
const worker = this.getFreeWorker();
|
59
52
|
const [test] = this.queue;
|
60
|
-
|
61
53
|
if (this.queue.length == 0 && this.workers.length === this.freeWorkers.length) {
|
62
54
|
this.forcedStop = false;
|
63
55
|
this.emit('stop');
|
64
56
|
return;
|
65
57
|
}
|
66
|
-
|
67
58
|
if (!worker || !test) return;
|
68
59
|
worker.isRunning = true;
|
69
60
|
const {
|
@@ -81,23 +72,18 @@ export default class Pool extends EventEmitter {
|
|
81
72
|
});
|
82
73
|
this.process();
|
83
74
|
}
|
84
|
-
|
85
75
|
sendStatus(message) {
|
86
76
|
this.emit('test', message);
|
87
77
|
}
|
88
|
-
|
89
78
|
getFreeWorker() {
|
90
79
|
return this.freeWorkers[Math.floor(Math.random() * this.freeWorkers.length)];
|
91
80
|
}
|
92
|
-
|
93
81
|
get aliveWorkers() {
|
94
82
|
return this.workers.filter(worker => !worker.exitedAfterDisconnect);
|
95
83
|
}
|
96
|
-
|
97
84
|
get freeWorkers() {
|
98
85
|
return this.aliveWorkers.filter(worker => !worker.isRunning);
|
99
86
|
}
|
100
|
-
|
101
87
|
async forkWorker(retry = 0) {
|
102
88
|
cluster.setupMaster({
|
103
89
|
args: ['--browser', this.browser, ...process.argv.slice(2)]
|
@@ -109,7 +95,6 @@ export default class Pool extends EventEmitter {
|
|
109
95
|
worker.off('message', readyHandler);
|
110
96
|
resolve(message);
|
111
97
|
};
|
112
|
-
|
113
98
|
worker.on('message', readyHandler);
|
114
99
|
});
|
115
100
|
if (message.type != 'error') return worker;
|
@@ -117,7 +102,6 @@ export default class Pool extends EventEmitter {
|
|
117
102
|
if (retry == FORK_RETRIES) return message.payload;
|
118
103
|
return this.forkWorker(retry + 1);
|
119
104
|
}
|
120
|
-
|
121
105
|
exitHandler(worker) {
|
122
106
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
123
107
|
worker.once('exit', async () => {
|
@@ -129,25 +113,20 @@ export default class Pool extends EventEmitter {
|
|
129
113
|
this.process();
|
130
114
|
});
|
131
115
|
}
|
132
|
-
|
133
116
|
gracefullyKill(worker) {
|
134
117
|
const timeout = setTimeout(() => worker.kill(), 10000);
|
135
118
|
worker.on('exit', () => clearTimeout(timeout));
|
136
119
|
sendShutdownMessage(worker);
|
137
120
|
}
|
138
|
-
|
139
121
|
shouldRetry(test) {
|
140
122
|
return test.retries < this.maxRetries && !this.forcedStop;
|
141
123
|
}
|
142
|
-
|
143
124
|
handleTestResult(worker, test, result) {
|
144
125
|
const shouldRetry = result.status == 'failed' && this.shouldRetry(test);
|
145
|
-
|
146
126
|
if (shouldRetry) {
|
147
127
|
test.retries += 1;
|
148
128
|
this.queue[this.failFast ? 'unshift' : 'push'](test);
|
149
129
|
}
|
150
|
-
|
151
130
|
this.sendStatus({
|
152
131
|
id: test.id,
|
153
132
|
status: shouldRetry ? 'retrying' : result.status,
|
@@ -156,7 +135,6 @@ export default class Pool extends EventEmitter {
|
|
156
135
|
worker.isRunning = false;
|
157
136
|
setImmediate(() => this.process());
|
158
137
|
}
|
159
|
-
|
160
138
|
subscribe(worker, test) {
|
161
139
|
const subscriptions = [subscribeOnWorker(worker, 'worker', message => {
|
162
140
|
if (message.type != 'error') return;
|
@@ -172,5 +150,4 @@ export default class Pool extends EventEmitter {
|
|
172
150
|
this.handleTestResult(worker, test, message.payload);
|
173
151
|
})];
|
174
152
|
}
|
175
|
-
|
176
153
|
}
|