creevey 0.10.0-beta.4 → 0.10.0-beta.6
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/dist/creevey.js +12 -5
- package/dist/creevey.js.map +1 -1
- package/dist/server/config.js +2 -1
- package/dist/server/config.js.map +1 -1
- package/dist/server/docker.js +2 -2
- package/dist/server/docker.js.map +1 -1
- package/dist/server/index.js +4 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/logger.d.ts +2 -1
- package/dist/server/logger.js +7 -3
- package/dist/server/logger.js.map +1 -1
- package/dist/server/master/api.js +1 -1
- package/dist/server/master/api.js.map +1 -1
- package/dist/server/master/pool.d.ts +3 -3
- package/dist/server/master/pool.js +10 -65
- package/dist/server/master/pool.js.map +1 -1
- package/dist/server/master/queue.d.ts +13 -0
- package/dist/server/master/queue.js +64 -0
- package/dist/server/master/queue.js.map +1 -0
- package/dist/server/master/runner.d.ts +1 -0
- package/dist/server/master/runner.js +4 -1
- package/dist/server/master/runner.js.map +1 -1
- package/dist/server/master/server.js +1 -1
- package/dist/server/master/server.js.map +1 -1
- package/dist/server/master/start.js +4 -4
- package/dist/server/master/start.js.map +1 -1
- package/dist/server/playwright/internal.js +17 -20
- package/dist/server/playwright/internal.js.map +1 -1
- package/dist/server/playwright/webdriver.js +1 -1
- package/dist/server/playwright/webdriver.js.map +1 -1
- package/dist/server/providers/browser.js +1 -1
- package/dist/server/providers/browser.js.map +1 -1
- package/dist/server/providers/hybrid.js +1 -1
- package/dist/server/providers/hybrid.js.map +1 -1
- package/dist/server/reporter.js +3 -3
- package/dist/server/reporter.js.map +1 -1
- package/dist/server/selenium/internal.d.ts +1 -2
- package/dist/server/selenium/internal.js +105 -81
- package/dist/server/selenium/internal.js.map +1 -1
- package/dist/server/selenium/webdriver.js +1 -1
- package/dist/server/selenium/webdriver.js.map +1 -1
- package/dist/server/utils.d.ts +2 -1
- package/dist/server/utils.js +11 -0
- package/dist/server/utils.js.map +1 -1
- package/dist/server/webdriver.d.ts +2 -3
- package/dist/server/webdriver.js +10 -9
- package/dist/server/webdriver.js.map +1 -1
- package/dist/server/worker/chai-image.d.ts +1 -2
- package/dist/server/worker/chai-image.js +4 -3
- package/dist/server/worker/chai-image.js.map +1 -1
- package/dist/server/worker/start.js +7 -10
- package/dist/server/worker/start.js.map +1 -1
- package/dist/types.d.ts +6 -2
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/creevey.ts +12 -6
- package/src/server/config.ts +2 -1
- package/src/server/docker.ts +2 -2
- package/src/server/index.ts +4 -4
- package/src/server/logger.ts +6 -2
- package/src/server/master/api.ts +1 -1
- package/src/server/master/pool.ts +18 -58
- package/src/server/master/queue.ts +64 -0
- package/src/server/master/runner.ts +4 -1
- package/src/server/master/server.ts +1 -1
- package/src/server/master/start.ts +7 -4
- package/src/server/playwright/internal.ts +17 -20
- package/src/server/playwright/webdriver.ts +1 -1
- package/src/server/providers/browser.ts +1 -1
- package/src/server/providers/hybrid.ts +1 -1
- package/src/server/reporter.ts +3 -2
- package/src/server/selenium/internal.ts +107 -81
- package/src/server/selenium/webdriver.ts +1 -1
- package/src/server/utils.ts +12 -1
- package/src/server/webdriver.ts +10 -15
- package/src/server/worker/chai-image.ts +4 -4
- package/src/server/worker/start.ts +7 -11
- package/src/types.ts +6 -2
- package/.yarnrc.yml +0 -1
package/dist/server/webdriver.js
CHANGED
@@ -15,14 +15,15 @@ const messages_js_1 = require("./messages.js");
|
|
15
15
|
exports.storybookRootID = 'storybook-root';
|
16
16
|
exports.LOCALHOST_REGEXP = /(localhost|127\.0\.0\.1)/i;
|
17
17
|
const DOCKER_INTERNAL = 'host.docker.internal';
|
18
|
-
async function resolveStorybookUrl(storybookUrl, checkUrl
|
19
|
-
logger.debug('Resolving storybook url');
|
18
|
+
async function resolveStorybookUrl(storybookUrl, checkUrl) {
|
19
|
+
(0, logger_js_1.logger)().debug('Resolving storybook url');
|
20
20
|
const addresses = getAddresses();
|
21
|
+
// TODO Use Promise.race?
|
21
22
|
for (const ip of addresses) {
|
22
23
|
const resolvedUrl = storybookUrl.replace(exports.LOCALHOST_REGEXP, ip);
|
23
|
-
logger.debug(`Checking storybook availability on ${chalk_1.default.magenta(resolvedUrl)}`);
|
24
|
+
(0, logger_js_1.logger)().debug(`Checking storybook availability on ${chalk_1.default.magenta(resolvedUrl)}`);
|
24
25
|
if (await checkUrl(resolvedUrl)) {
|
25
|
-
logger.debug(`Resolved storybook url ${chalk_1.default.magenta(resolvedUrl)}`);
|
26
|
+
(0, logger_js_1.logger)().debug(`Resolved storybook url ${chalk_1.default.magenta(resolvedUrl)}`);
|
26
27
|
return resolvedUrl;
|
27
28
|
}
|
28
29
|
}
|
@@ -40,10 +41,10 @@ function getAddresses() {
|
|
40
41
|
.map((network) => network.filter((info) => info.family == 'IPv4').map((info) => info.address)));
|
41
42
|
}
|
42
43
|
class CreeveyWebdriverBase {
|
43
|
-
async switchStory(story, context
|
44
|
+
async switchStory(story, context) {
|
44
45
|
const { id, title, name, parameters } = story;
|
45
46
|
const { captureElement = `#${exports.storybookRootID}`, waitForReady, ignoreElements, } = (parameters.creevey ?? {});
|
46
|
-
logger.debug(`Switching to story ${chalk_1.default.cyan(title)}/${chalk_1.default.cyan(name)} by id ${chalk_1.default.magenta(id)}`);
|
47
|
+
(0, logger_js_1.logger)().debug(`Switching to story ${chalk_1.default.cyan(title)}/${chalk_1.default.cyan(name)} by id ${chalk_1.default.magenta(id)}`);
|
47
48
|
let storyPlayResolver;
|
48
49
|
let waitForComplete = new Promise((resolve) => (storyPlayResolver = resolve));
|
49
50
|
const unsubscribe = (0, messages_js_1.subscribeOn)('stories', (message) => {
|
@@ -58,16 +59,16 @@ class CreeveyWebdriverBase {
|
|
58
59
|
});
|
59
60
|
const isCaptureCalled = await this.selectStory(id, waitForReady);
|
60
61
|
if (isCaptureCalled) {
|
61
|
-
logger.debug(`Capturing screenshots from ${chalk_1.default.magenta(id)} story's \`play()\` function`);
|
62
|
+
(0, logger_js_1.logger)().debug(`Capturing screenshots from ${chalk_1.default.magenta(id)} story's \`play()\` function`);
|
62
63
|
while (!(await waitForComplete)) {
|
63
64
|
waitForComplete = new Promise((resolve) => (storyPlayResolver = resolve));
|
64
65
|
}
|
65
66
|
}
|
66
67
|
unsubscribe();
|
67
68
|
if (isCaptureCalled)
|
68
|
-
logger.debug(`Story ${chalk_1.default.magenta(id)} completed capturing`);
|
69
|
+
(0, logger_js_1.logger)().debug(`Story ${chalk_1.default.magenta(id)} completed capturing`);
|
69
70
|
else
|
70
|
-
logger.debug(`Story ${chalk_1.default.magenta(id)} ready for capturing`);
|
71
|
+
(0, logger_js_1.logger)().debug(`Story ${chalk_1.default.magenta(id)} ready for capturing`);
|
71
72
|
return Object.assign({
|
72
73
|
takeScreenshot: () => this.takeScreenshot(captureElement, ignoreElements),
|
73
74
|
updateStoryArgs: (updatedArgs) => this.updateStoryArgs(story, updatedArgs),
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"webdriver.js","sourceRoot":"","sources":["../../src/server/webdriver.ts"],"names":[],"mappings":";;;;;;
|
1
|
+
{"version":3,"file":"webdriver.js","sourceRoot":"","sources":["../../src/server/webdriver.ts"],"names":[],"mappings":"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"}
|
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
export default function (matchImage: (image: Buffer, imageName?: string) => Promise<void>, matchImages: (images: Record<string, Buffer>) => Promise<void>, logger: Logger.Logger): ({ Assertion }: Chai.ChaiStatic, utils: Chai.ChaiUtils) => void;
|
1
|
+
export default function (matchImage: (image: Buffer, imageName?: string) => Promise<void>, matchImages: (images: Record<string, Buffer>) => Promise<void>): ({ Assertion }: Chai.ChaiStatic, utils: Chai.ChaiUtils) => void;
|
@@ -1,12 +1,13 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.default = default_1;
|
4
|
-
|
4
|
+
const logger_1 = require("../logger");
|
5
|
+
function default_1(matchImage, matchImages) {
|
5
6
|
let isWarningShown = false;
|
6
7
|
return function chaiImage({ Assertion }, utils) {
|
7
8
|
utils.addMethod(Assertion.prototype, 'matchImage', async function (imageName) {
|
8
9
|
if (!isWarningShown) {
|
9
|
-
logger.warn('`expect(...).to.matchImage()` is deprecated and will be removed in the next major release. Please use `context.matchImage()` instead.');
|
10
|
+
(0, logger_1.logger)().warn('`expect(...).to.matchImage()` is deprecated and will be removed in the next major release. Please use `context.matchImage()` instead.');
|
10
11
|
isWarningShown = true;
|
11
12
|
}
|
12
13
|
const image = utils.flag(this, 'object');
|
@@ -14,7 +15,7 @@ function default_1(matchImage, matchImages, logger) {
|
|
14
15
|
});
|
15
16
|
utils.addMethod(Assertion.prototype, 'matchImages', async function () {
|
16
17
|
if (!isWarningShown) {
|
17
|
-
logger.warn('`expect(...).to.matchImages()` is deprecated and will be removed in the next major release. Please use `context.matchImages()` instead.');
|
18
|
+
(0, logger_1.logger)().warn('`expect(...).to.matchImages()` is deprecated and will be removed in the next major release. Please use `context.matchImages()` instead.');
|
18
19
|
isWarningShown = true;
|
19
20
|
}
|
20
21
|
const images = utils.flag(this, 'object');
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"chai-image.js","sourceRoot":"","sources":["../../../src/server/worker/chai-image.ts"],"names":[],"mappings":";;
|
1
|
+
{"version":3,"file":"chai-image.js","sourceRoot":"","sources":["../../../src/server/worker/chai-image.ts"],"names":[],"mappings":";;AAEA,4BAgCC;AAlCD,sCAAmC;AAEnC,mBACE,UAAgE,EAChE,WAA8D;IAE9D,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,OAAO,SAAS,SAAS,CAAC,EAAE,SAAS,EAAmB,EAAE,KAAqB;QAC7E,KAAK,CAAC,SAAS,CACb,SAAS,CAAC,SAAS,EACnB,YAAY,EACZ,KAAK,WAA0C,SAAkB;YAC/D,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,IAAA,eAAM,GAAE,CAAC,IAAI,CACX,uIAAuI,CACxI,CAAC;gBACF,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;YACD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAW,CAAC;YACnD,MAAM,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC,CACF,CAAC;QAEF,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK;YACvD,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,IAAA,eAAM,GAAE,CAAC,IAAI,CACX,yIAAyI,CAC1I,CAAC;gBACF,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAA2B,CAAC;YACpE,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
@@ -5,8 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
exports.start = start;
|
7
7
|
const chai_1 = __importDefault(require("chai"));
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
9
|
-
const loglevel_1 = __importDefault(require("loglevel"));
|
10
8
|
const events_1 = __importDefault(require("events"));
|
11
9
|
const types_js_1 = require("../../types.js");
|
12
10
|
const messages_js_1 = require("../messages.js");
|
@@ -70,7 +68,7 @@ function runHandler(browserName, images, error) {
|
|
70
68
|
}
|
71
69
|
async function setupWebdriver(webdriver) {
|
72
70
|
if ((await webdriver.openBrowser(true)) == null) {
|
73
|
-
logger_js_1.logger.error('Failed to start browser');
|
71
|
+
(0, logger_js_1.logger)().error('Failed to start browser');
|
74
72
|
(0, messages_js_1.emitWorkerMessage)({
|
75
73
|
type: 'error',
|
76
74
|
payload: { subtype: 'browser', error: 'Failed to start browser' },
|
@@ -104,7 +102,6 @@ async function start(browser, gridUrl, config, options) {
|
|
104
102
|
const [sessionId, webdriver] = (await setupWebdriver(new Webdriver(browser, gridUrl, config, options))) ?? [];
|
105
103
|
if (!webdriver || !sessionId)
|
106
104
|
return;
|
107
|
-
const workerLogger = loglevel_1.default.getLogger(`${browser}:${chalk_1.default.gray(sessionId)}`);
|
108
105
|
const reporterOptions = {
|
109
106
|
...config.reporterOptions,
|
110
107
|
creevey: {
|
@@ -127,13 +124,13 @@ async function start(browser, gridUrl, config, options) {
|
|
127
124
|
const { matchImage, matchImages } = options.odiff
|
128
125
|
? (0, match_image_js_1.getOdiffMatchers)(imagesContext, config)
|
129
126
|
: await (0, match_image_js_1.getMatchers)(imagesContext, config);
|
130
|
-
chai_1.default.use((0, chai_image_js_1.default)(matchImage, matchImages
|
127
|
+
chai_1.default.use((0, chai_image_js_1.default)(matchImage, matchImages));
|
131
128
|
const tests = await (async () => {
|
132
129
|
try {
|
133
130
|
return await getTestsFromStories(config, browser, webdriver);
|
134
131
|
}
|
135
132
|
catch (error) {
|
136
|
-
|
133
|
+
(0, logger_js_1.logger)().error('Failed to get tests from stories:', error);
|
137
134
|
(0, messages_js_1.emitWorkerMessage)({
|
138
135
|
type: 'error',
|
139
136
|
payload: { subtype: 'browser', error: serializeError(error) },
|
@@ -149,7 +146,7 @@ async function start(browser, gridUrl, config, options) {
|
|
149
146
|
const test = tests.get(message.payload.id);
|
150
147
|
if (!test) {
|
151
148
|
const error = `Test with id ${message.payload.id} not found`;
|
152
|
-
|
149
|
+
(0, logger_js_1.logger)().error(error);
|
153
150
|
(0, messages_js_1.emitWorkerMessage)({
|
154
151
|
type: 'error',
|
155
152
|
payload: { subtype: 'test', error },
|
@@ -198,7 +195,7 @@ async function start(browser, gridUrl, config, options) {
|
|
198
195
|
reject(`Timeout of ${config.testTimeout}ms exceeded`);
|
199
196
|
}, config.testTimeout)),
|
200
197
|
(async () => {
|
201
|
-
const context = await webdriver.switchStory(test.story, baseContext
|
198
|
+
const context = await webdriver.switchStory(test.story, baseContext);
|
202
199
|
await test.fn(context);
|
203
200
|
})(),
|
204
201
|
]);
|
@@ -223,14 +220,14 @@ async function start(browser, gridUrl, config, options) {
|
|
223
220
|
await webdriver.afterTest(test);
|
224
221
|
runHandler(baseContext.browserName, imagesContext.images, error);
|
225
222
|
})().catch((error) => {
|
226
|
-
|
223
|
+
(0, logger_js_1.logger)().error('Unexpected error:', error);
|
227
224
|
(0, messages_js_1.emitWorkerMessage)({
|
228
225
|
type: 'error',
|
229
226
|
payload: { subtype: 'test', error: serializeError(error) },
|
230
227
|
});
|
231
228
|
});
|
232
229
|
});
|
233
|
-
|
230
|
+
(0, logger_js_1.logger)().info('Browser is ready');
|
234
231
|
(0, messages_js_1.emitWorkerMessage)({ type: 'ready' });
|
235
232
|
}
|
236
233
|
//# sourceMappingURL=start.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/server/worker/start.ts"],"names":[],"mappings":";;;;;
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/server/worker/start.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
@@ -4,7 +4,6 @@ import type Pixelmatch from 'pixelmatch';
|
|
4
4
|
import type { ODiffOptions } from 'odiff-bin';
|
5
5
|
import type { expect } from 'chai';
|
6
6
|
import type EventEmitter from 'events';
|
7
|
-
import type Logger from 'loglevel';
|
8
7
|
import { LaunchOptions } from 'playwright-core';
|
9
8
|
export type DiffOptions = typeof Pixelmatch extends (x1: any, x2: any, x3: any, x4: any, x5: any, options?: infer T) => void ? T : never;
|
10
9
|
export interface SetStoriesData {
|
@@ -125,7 +124,7 @@ export interface CreeveyWebdriver {
|
|
125
124
|
openBrowser(fresh?: boolean): Promise<CreeveyWebdriver | null>;
|
126
125
|
closeBrowser(): Promise<void>;
|
127
126
|
loadStoriesFromBrowser(): Promise<StoriesRaw>;
|
128
|
-
switchStory(story: StoryInput, context: BaseCreeveyTestContext
|
127
|
+
switchStory(story: StoryInput, context: BaseCreeveyTestContext): Promise<CreeveyTestContext>;
|
129
128
|
afterTest(test: ServerTest): Promise<void>;
|
130
129
|
}
|
131
130
|
export interface HookConfig {
|
@@ -264,6 +263,11 @@ export interface Config {
|
|
264
263
|
* The `--ui` CLI option ignores this option
|
265
264
|
*/
|
266
265
|
failFast: boolean;
|
266
|
+
/**
|
267
|
+
* Start workers in sequential queue
|
268
|
+
* @default false
|
269
|
+
*/
|
270
|
+
useWorkerQueue: boolean;
|
267
271
|
/**
|
268
272
|
* Specify platform for docker images
|
269
273
|
*/
|
package/dist/types.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAojBA,oBAEC;AAED,8BAEC;AAED,wBASC;AAED,4BAEC;AAED,4BAEC;AAGD,gCAEC;AAED,oCAEC;AAED,4CAEC;AAED,0CAEC;AAED,4CAEC;AAED,sCAEC;AA3jBD,IAAY,eAUX;AAVD,WAAY,eAAe;IACzB,6CAA0B,CAAA;IAC1B,wDAAqC,CAAA;IACrC,iDAA8B,CAAA;IAC9B,mDAAgC,CAAA;IAChC,iDAA8B,CAAA;IAC9B,gEAA6C,CAAA;IAC7C,wDAAqC,CAAA;IACrC,6CAA0B,CAAA;IAC1B,mDAAgC,CAAA;AAClC,CAAC,EAVW,eAAe,+BAAf,eAAe,QAU1B;AAsWD,MAAa,WAAY,SAAQ,KAAK;IACpC,MAAM,CAA4C;CACnD;AAFD,kCAEC;AAwCD,IAAY,WAOX;AAPD,WAAY,WAAW;IACrB,kCAAmB,CAAA;IACnB,8BAAe,CAAA;IACf,kCAAmB,CAAA;IACnB,oCAAqB,CAAA;IACrB,iCAAkB,CAAA;IAClB,iCAAkB,CAAA;AACpB,CAAC,EAPW,WAAW,2BAAX,WAAW,QAOtB;AAwGD,SAAgB,IAAI;IAClB,UAAU;AACZ,CAAC;AAED,SAAgB,SAAS,CAAI,KAA2B;IACtD,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;AAC/C,CAAC;AAED,SAAgB,MAAM,CAAC,CAA8B;IACnD,OAAO,CACL,SAAS,CAAC,CAAC,CAAC;QACZ,QAAQ,CAAC,CAAC,CAAC;QACX,IAAI,IAAI,CAAC;QACT,SAAS,IAAI,CAAC;QACd,OAAO,CAAC,CAAC,EAAE,IAAI,QAAQ;QACvB,OAAO,CAAC,CAAC,OAAO,IAAI,QAAQ,CAC7B,CAAC;AACJ,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAU;IACjC,OAAO,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC,IAAI,IAAI,CAAC;AAC3C,CAAC;AAED,SAAgB,QAAQ,CAAC,CAAU;IACjC,OAAO,OAAO,CAAC,IAAI,QAAQ,CAAC;AAC9B,CAAC;AAED,8DAA8D;AAC9D,SAAgB,UAAU,CAAC,CAAU;IACnC,OAAO,OAAO,CAAC,IAAI,UAAU,CAAC;AAChC,CAAC;AAED,SAAgB,YAAY,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,WAAW,IAAI,QAAQ,IAAI,KAAK,CAAC;AAC3D,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,OAAO,CAAC;AACjD,CAAC;AAED,SAAgB,eAAe,CAAC,OAAgB;IAC9C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;AAChE,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC;AACjE,CAAC;AAED,SAAgB,aAAa,CAAC,OAAgB;IAC5C,OAAO,gBAAgB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC;AAC9D,CAAC"}
|
package/package.json
CHANGED
package/src/creevey.ts
CHANGED
@@ -5,14 +5,14 @@ import { Options } from './types.js';
|
|
5
5
|
import { emitWorkerMessage } from './server/messages.js';
|
6
6
|
import { isShuttingDown, shutdownWorkers } from './server/utils.js';
|
7
7
|
import Logger from 'loglevel';
|
8
|
-
import { logger } from './server/logger.js';
|
8
|
+
import { logger, setRootName } from './server/logger.js';
|
9
9
|
|
10
10
|
function shutdownOnException(reason: unknown): void {
|
11
11
|
if (isShuttingDown.current) return;
|
12
12
|
|
13
13
|
const error = reason instanceof Error ? (reason.stack ?? reason.message) : (reason as string);
|
14
14
|
|
15
|
-
logger.error(error);
|
15
|
+
logger().error(error);
|
16
16
|
|
17
17
|
process.exitCode = -1;
|
18
18
|
if (cluster.isWorker) emitWorkerMessage({ type: 'error', payload: { subtype: 'unknown', error } });
|
@@ -23,6 +23,9 @@ process.on('uncaughtException', shutdownOnException);
|
|
23
23
|
process.on('unhandledRejection', shutdownOnException);
|
24
24
|
// TODO SIGINT Stuck with selenium
|
25
25
|
process.on('SIGINT', () => {
|
26
|
+
if (isShuttingDown.current) {
|
27
|
+
process.exit(-1);
|
28
|
+
}
|
26
29
|
isShuttingDown.current = true;
|
27
30
|
});
|
28
31
|
|
@@ -33,9 +36,12 @@ const argv = minimist<Options>(process.argv.slice(2), {
|
|
33
36
|
alias: { port: 'p', config: 'c', debug: 'd', update: 'u' },
|
34
37
|
});
|
35
38
|
|
39
|
+
if ('port' in argv && !isNaN(argv.port)) argv.port = Number(argv.port);
|
40
|
+
if ('browser' in argv && argv.browser) setRootName(argv.browser);
|
41
|
+
|
36
42
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
37
43
|
if (cluster.isPrimary && argv.reporter) {
|
38
|
-
logger.warn(`--reporter option has been removed please describe reporter in config file:
|
44
|
+
logger().warn(`--reporter option has been removed please describe reporter in config file:
|
39
45
|
import { reporters } from 'mocha';
|
40
46
|
|
41
47
|
const config = {
|
@@ -52,13 +58,13 @@ if (cluster.isPrimary && argv.reporter) {
|
|
52
58
|
// @ts-expect-error: define log level for storybook
|
53
59
|
global.LOGLEVEL = argv.trace ? 'trace' : argv.debug ? 'debug' : 'warn';
|
54
60
|
if (argv.trace) {
|
55
|
-
logger.setDefaultLevel(Logger.levels.TRACE);
|
61
|
+
logger().setDefaultLevel(Logger.levels.TRACE);
|
56
62
|
Logger.setDefaultLevel(Logger.levels.TRACE);
|
57
63
|
} else if (argv.debug) {
|
58
|
-
logger.setDefaultLevel(Logger.levels.DEBUG);
|
64
|
+
logger().setDefaultLevel(Logger.levels.DEBUG);
|
59
65
|
Logger.setDefaultLevel(Logger.levels.DEBUG);
|
60
66
|
} else {
|
61
|
-
logger.setDefaultLevel(Logger.levels.INFO);
|
67
|
+
logger().setDefaultLevel(Logger.levels.INFO);
|
62
68
|
Logger.setDefaultLevel(Logger.levels.INFO);
|
63
69
|
}
|
64
70
|
|
package/src/server/config.ts
CHANGED
@@ -11,6 +11,7 @@ export const defaultBrowser = 'chrome';
|
|
11
11
|
|
12
12
|
export const defaultConfig: Omit<Config, 'gridUrl' | 'testsDir' | 'tsConfig' | 'webdriver'> = {
|
13
13
|
disableTelemetry: false,
|
14
|
+
useWorkerQueue: false,
|
14
15
|
useDocker: true,
|
15
16
|
dockerImage: 'aerokube/selenoid:latest-release',
|
16
17
|
dockerImagePlatform: '',
|
@@ -73,7 +74,7 @@ export async function readConfig(options: Options): Promise<Config> {
|
|
73
74
|
|
74
75
|
if (!configData.webdriver) {
|
75
76
|
const { SeleniumWebdriver } = await import('./selenium/webdriver.js');
|
76
|
-
logger.warn(
|
77
|
+
logger().warn(
|
77
78
|
"Creevey supports `Selenium` and `Playwright` webdrivers. For backward compatibility `Selenium` is used by default, but it might changed in the future. Please explicitly specify one of webdrivers in your Creevey's config",
|
78
79
|
);
|
79
80
|
configData.webdriver = SeleniumWebdriver;
|
package/src/server/docker.ts
CHANGED
@@ -21,7 +21,7 @@ export async function pullImages(
|
|
21
21
|
if (auth) args.authconfig = auth;
|
22
22
|
if (platform) args.platform = platform;
|
23
23
|
|
24
|
-
logger.info('Pull docker images');
|
24
|
+
logger().info('Pull docker images');
|
25
25
|
// TODO Replace with `import from`
|
26
26
|
const { default: yoctoSpinner } = await import('yocto-spinner');
|
27
27
|
for (const image of images) {
|
@@ -61,7 +61,7 @@ export async function buildImage(imageName: string, dockerfile: string): Promise
|
|
61
61
|
const images = await docker.listImages({ filters: { label: [`creevey=${imageName}`] } });
|
62
62
|
|
63
63
|
if (images.at(0)) {
|
64
|
-
logger.info(`Image ${imageName} already exists`);
|
64
|
+
logger().info(`Image ${imageName} already exists`);
|
65
65
|
return;
|
66
66
|
}
|
67
67
|
|
package/src/server/index.ts
CHANGED
@@ -97,25 +97,25 @@ export default async function (options: Options): Promise<void> {
|
|
97
97
|
try {
|
98
98
|
await import('selenium-webdriver');
|
99
99
|
} catch {
|
100
|
-
logger.error('Failed to start Creevey, missing required dependency: "selenium-webdriver"');
|
100
|
+
logger().error('Failed to start Creevey, missing required dependency: "selenium-webdriver"');
|
101
101
|
process.exit(-1);
|
102
102
|
}
|
103
103
|
} else {
|
104
104
|
try {
|
105
105
|
await import('playwright-core');
|
106
106
|
} catch {
|
107
|
-
logger.error('Failed to start Creevey, missing required dependency: "playwright-core"');
|
107
|
+
logger().error('Failed to start Creevey, missing required dependency: "playwright-core"');
|
108
108
|
process.exit(-1);
|
109
109
|
}
|
110
110
|
}
|
111
|
-
logger.info('Starting Master Process');
|
111
|
+
logger().info('Starting Master Process');
|
112
112
|
|
113
113
|
const resolveApi = (await import('./master/server.js')).start(config.reportDir, port, ui);
|
114
114
|
|
115
115
|
return (await import('./master/start.js')).start(gridUrl, config, options, resolveApi);
|
116
116
|
}
|
117
117
|
default: {
|
118
|
-
logger.info(`Starting Worker for ${browser}`);
|
118
|
+
logger().info(`Starting Worker for ${browser}`);
|
119
119
|
|
120
120
|
// NOTE: We assume that we pass `gridUrl` to worker CLI options
|
121
121
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
package/src/server/logger.ts
CHANGED
@@ -10,12 +10,16 @@ export const colors = {
|
|
10
10
|
ERROR: chalk.red,
|
11
11
|
};
|
12
12
|
|
13
|
+
let rootName = 'Creevey';
|
14
|
+
|
13
15
|
prefix.reg(Logger);
|
14
16
|
prefix.apply(Logger, {
|
15
|
-
format(level, name =
|
17
|
+
format(level, name = rootName) {
|
16
18
|
const levelColor = colors[level.toUpperCase() as keyof typeof colors];
|
17
19
|
return `[${name}:${chalk.gray(process.pid)}] ${levelColor(level)} =>`;
|
18
20
|
},
|
19
21
|
});
|
20
22
|
|
21
|
-
export const
|
23
|
+
export const setRootName = (newName: string) => (rootName = newName);
|
24
|
+
|
25
|
+
export const logger = () => Logger.getLogger(rootName);
|
package/src/server/master/api.ts
CHANGED
@@ -26,7 +26,7 @@ export default function creeveyApi(runner: Runner): CreeveyApi {
|
|
26
26
|
|
27
27
|
handleMessage(ws: WebSocket, message: WebSocket.Data) {
|
28
28
|
if (typeof message != 'string') {
|
29
|
-
logger.info('unhandled message', message);
|
29
|
+
logger().info('unhandled message', message);
|
30
30
|
return;
|
31
31
|
}
|
32
32
|
|
@@ -1,18 +1,9 @@
|
|
1
|
-
import
|
1
|
+
import { Worker as ClusterWorker } from 'cluster';
|
2
2
|
import { EventEmitter } from 'events';
|
3
|
-
import {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
BrowserConfigObject,
|
8
|
-
WorkerMessage,
|
9
|
-
TestStatus,
|
10
|
-
isWorkerMessage,
|
11
|
-
} from '../../types.js';
|
12
|
-
import { sendTestMessage, sendShutdownMessage, subscribeOnWorker } from '../messages.js';
|
13
|
-
import { isShuttingDown } from '../utils.js';
|
14
|
-
|
15
|
-
const FORK_RETRIES = 5;
|
3
|
+
import { Worker, Config, TestResult, BrowserConfigObject, TestStatus } from '../../types.js';
|
4
|
+
import { sendTestMessage, subscribeOnWorker } from '../messages.js';
|
5
|
+
import { gracefullyKill, isShuttingDown } from '../utils.js';
|
6
|
+
import { WorkerQueue } from './queue.js';
|
16
7
|
|
17
8
|
interface WorkerTest {
|
18
9
|
id: string;
|
@@ -32,6 +23,7 @@ export default class Pool extends EventEmitter {
|
|
32
23
|
return this.workers.length !== this.freeWorkers.length;
|
33
24
|
}
|
34
25
|
constructor(
|
26
|
+
public scheduler: WorkerQueue,
|
35
27
|
config: Config,
|
36
28
|
private browser: string,
|
37
29
|
gridUrl?: string,
|
@@ -46,10 +38,11 @@ export default class Pool extends EventEmitter {
|
|
46
38
|
|
47
39
|
async init(): Promise<void> {
|
48
40
|
const poolSize = Math.max(1, this.config.limit ?? 1);
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
41
|
+
this.workers = (
|
42
|
+
await Promise.all(
|
43
|
+
Array.from({ length: poolSize }).map(() => this.scheduler.forkWorker(this.browser, this.gridUrl)),
|
44
|
+
)
|
45
|
+
).filter((workerOrError): workerOrError is Worker => workerOrError instanceof ClusterWorker);
|
53
46
|
if (this.workers.length != poolSize)
|
54
47
|
throw new Error(`Can't instantiate workers for ${this.browser} due many errors`);
|
55
48
|
this.workers.forEach((worker) => {
|
@@ -66,7 +59,7 @@ export default class Pool extends EventEmitter {
|
|
66
59
|
return true;
|
67
60
|
}
|
68
61
|
|
69
|
-
stop()
|
62
|
+
stop() {
|
70
63
|
if (!this.isRunning) {
|
71
64
|
this.emit('stop');
|
72
65
|
return;
|
@@ -76,7 +69,7 @@ export default class Pool extends EventEmitter {
|
|
76
69
|
this.queue = [];
|
77
70
|
}
|
78
71
|
|
79
|
-
process()
|
72
|
+
process() {
|
80
73
|
const worker = this.getFreeWorker();
|
81
74
|
const test = this.queue.at(0);
|
82
75
|
|
@@ -99,7 +92,9 @@ export default class Pool extends EventEmitter {
|
|
99
92
|
|
100
93
|
sendTestMessage(worker, { type: 'start', payload: test });
|
101
94
|
|
102
|
-
|
95
|
+
setImmediate(() => {
|
96
|
+
this.process();
|
97
|
+
});
|
103
98
|
}
|
104
99
|
|
105
100
|
private sendStatus(message: { id: string; status: TestStatus; result?: TestResult }): void {
|
@@ -120,36 +115,12 @@ export default class Pool extends EventEmitter {
|
|
120
115
|
return this.aliveWorkers.filter((worker) => !worker.isRunning);
|
121
116
|
}
|
122
117
|
|
123
|
-
private async forkWorker(retry = 0): Promise<Worker | { error: string }> {
|
124
|
-
if (isShuttingDown.current) return { error: 'Master process is shutting down' };
|
125
|
-
|
126
|
-
cluster.setupPrimary({
|
127
|
-
args: ['--browser', this.browser, ...(this.gridUrl ? ['--gridUrl', this.gridUrl] : []), ...process.argv.slice(2)],
|
128
|
-
});
|
129
|
-
const worker = cluster.fork();
|
130
|
-
const message = await new Promise((resolve: (value: WorkerMessage) => void) => {
|
131
|
-
const readyHandler = (message: unknown): void => {
|
132
|
-
if (!isWorkerMessage(message) || message.type == 'port') return;
|
133
|
-
worker.off('message', readyHandler);
|
134
|
-
resolve(message);
|
135
|
-
};
|
136
|
-
worker.on('message', readyHandler);
|
137
|
-
});
|
138
|
-
|
139
|
-
if (message.type != 'error') return worker;
|
140
|
-
|
141
|
-
this.gracefullyKill(worker);
|
142
|
-
|
143
|
-
if (retry == FORK_RETRIES) return message.payload;
|
144
|
-
return this.forkWorker(retry + 1);
|
145
|
-
}
|
146
|
-
|
147
118
|
private exitHandler(worker: Worker): void {
|
148
119
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
149
120
|
worker.once('exit', async () => {
|
150
121
|
if (isShuttingDown.current) return;
|
151
122
|
|
152
|
-
const workerOrError = await this.forkWorker();
|
123
|
+
const workerOrError = await this.scheduler.forkWorker(this.browser, this.gridUrl);
|
153
124
|
|
154
125
|
if (!(workerOrError instanceof ClusterWorker))
|
155
126
|
throw new Error(`Can't instantiate worker for ${this.browser} due many errors`);
|
@@ -160,17 +131,6 @@ export default class Pool extends EventEmitter {
|
|
160
131
|
});
|
161
132
|
}
|
162
133
|
|
163
|
-
private gracefullyKill(worker: Worker): void {
|
164
|
-
worker.isShuttingDown = true;
|
165
|
-
const timeout = setTimeout(() => {
|
166
|
-
worker.kill();
|
167
|
-
}, 10000);
|
168
|
-
worker.on('exit', () => {
|
169
|
-
clearTimeout(timeout);
|
170
|
-
});
|
171
|
-
sendShutdownMessage(worker);
|
172
|
-
}
|
173
|
-
|
174
134
|
private shouldRetry(test: WorkerTest): boolean {
|
175
135
|
return test.retries < this.maxRetries && !this.forcedStop;
|
176
136
|
}
|
@@ -202,7 +162,7 @@ export default class Pool extends EventEmitter {
|
|
202
162
|
});
|
203
163
|
|
204
164
|
if (message.payload.subtype == 'unknown') {
|
205
|
-
|
165
|
+
gracefullyKill(worker);
|
206
166
|
}
|
207
167
|
|
208
168
|
this.handleTestResult(worker, test, { status: 'failed', error: message.payload.error });
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import cluster from 'cluster';
|
2
|
+
import { isWorkerMessage, Worker, WorkerMessage } from '../../types.js';
|
3
|
+
import { gracefullyKill, isShuttingDown } from '../utils.js';
|
4
|
+
|
5
|
+
const FORK_RETRIES = 5;
|
6
|
+
|
7
|
+
type MaybeWorker = Worker | { error: string };
|
8
|
+
|
9
|
+
export class WorkerQueue {
|
10
|
+
private isProcessing = false;
|
11
|
+
private queue: { browser: string; gridUrl?: string; retry: number; resolve: (mw: MaybeWorker) => void }[] = [];
|
12
|
+
|
13
|
+
// TODO Add concurrency
|
14
|
+
constructor(private useQueue: boolean) {}
|
15
|
+
|
16
|
+
async forkWorker(browser: string, gridUrl?: string, retry = 0): Promise<MaybeWorker> {
|
17
|
+
return new Promise<MaybeWorker>((resolve) => {
|
18
|
+
this.queue.push({ browser, gridUrl, retry, resolve });
|
19
|
+
|
20
|
+
void this.process();
|
21
|
+
});
|
22
|
+
}
|
23
|
+
|
24
|
+
private async process() {
|
25
|
+
if (this.useQueue && this.isProcessing) return;
|
26
|
+
|
27
|
+
const { browser, gridUrl, retry, resolve } = this.queue.pop() ?? {};
|
28
|
+
|
29
|
+
if (browser == undefined || retry == undefined || resolve == undefined) return;
|
30
|
+
|
31
|
+
if (isShuttingDown.current) {
|
32
|
+
resolve({ error: 'Master process is shutting down' });
|
33
|
+
return;
|
34
|
+
}
|
35
|
+
|
36
|
+
this.isProcessing = true;
|
37
|
+
|
38
|
+
cluster.setupPrimary({
|
39
|
+
args: ['--browser', browser, ...(gridUrl ? ['--gridUrl', gridUrl] : []), ...process.argv.slice(2)],
|
40
|
+
});
|
41
|
+
const worker = cluster.fork();
|
42
|
+
const message = await new Promise((resolve: (value: WorkerMessage) => void) => {
|
43
|
+
const readyHandler = (message: unknown): void => {
|
44
|
+
if (!isWorkerMessage(message) || message.type == 'port') return;
|
45
|
+
worker.off('message', readyHandler);
|
46
|
+
resolve(message);
|
47
|
+
};
|
48
|
+
worker.on('message', readyHandler);
|
49
|
+
});
|
50
|
+
|
51
|
+
if (message.type == 'error') {
|
52
|
+
gracefullyKill(worker);
|
53
|
+
|
54
|
+
if (retry == FORK_RETRIES) resolve(message.payload);
|
55
|
+
else this.queue.push({ browser, gridUrl, retry: retry + 1, resolve });
|
56
|
+
} else {
|
57
|
+
resolve(worker);
|
58
|
+
}
|
59
|
+
|
60
|
+
this.isProcessing = false;
|
61
|
+
|
62
|
+
setImmediate(() => void this.process());
|
63
|
+
}
|
64
|
+
}
|