@wdio/local-runner 9.18.3 → 9.19.0
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/build/index.d.ts +10 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +80 -22
- package/build/worker.d.ts +6 -4
- package/build/worker.d.ts.map +1 -1
- package/package.json +5 -4
package/build/index.d.ts
CHANGED
|
@@ -8,17 +8,23 @@ export interface RunArgs extends Workers.WorkerRunPayload {
|
|
|
8
8
|
}
|
|
9
9
|
export default class LocalRunner {
|
|
10
10
|
private _options;
|
|
11
|
-
protected
|
|
11
|
+
protected config: WebdriverIO.Config;
|
|
12
12
|
workerPool: Record<string, WorkerInstance>;
|
|
13
|
+
private xvfbInitialized;
|
|
14
|
+
private xvfbManager;
|
|
13
15
|
stdout: WritableStreamBuffer;
|
|
14
16
|
stderr: WritableStreamBuffer;
|
|
15
|
-
constructor(_options: never,
|
|
17
|
+
constructor(_options: never, config: WebdriverIO.Config);
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* initialize local runner environment
|
|
18
20
|
*/
|
|
19
|
-
initialize(): void
|
|
21
|
+
initialize(): Promise<void>;
|
|
20
22
|
getWorkerCount(): number;
|
|
21
23
|
run({ command, args, ...workerOptions }: RunArgs): Promise<WorkerInstance>;
|
|
24
|
+
/**
|
|
25
|
+
* Initialize XVFB with capability-aware detection
|
|
26
|
+
*/
|
|
27
|
+
private initializeXvfb;
|
|
22
28
|
/**
|
|
23
29
|
* shutdown all worker processes
|
|
24
30
|
*
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,cAAc,MAAM,aAAa,CAAA;AAKxC,YAAY,EAAE,cAAc,EAAE,CAAA;AAE9B,MAAM,WAAW,OAAQ,SAAQ,OAAO,CAAC,gBAAgB;IACrD,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAA;CAClC;AAED,MAAM,CAAC,OAAO,OAAO,WAAW;IASxB,OAAO,CAAC,QAAQ;IAChB,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM;IATxC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAK;IAC/C,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,WAAW,CAAa;IAEhC,MAAM,uBAA2C;IACjD,MAAM,uBAA2C;gBAGrC,QAAQ,EAAE,KAAK,EACb,MAAM,EAAE,WAAW,CAAC,MAAM;IASxC;;OAEG;IACG,UAAU;IAIhB,cAAc;IAIR,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,EAAE,OAAO;IA4BtD;;OAEG;YACW,cAAc;IAsB5B;;;;;OAKG;IACG,QAAQ;CA0DjB"}
|
package/build/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import logger2 from "@wdio/logger";
|
|
3
3
|
import { WritableStreamBuffer } from "stream-buffers";
|
|
4
|
+
import { XvfbManager } from "@wdio/xvfb";
|
|
4
5
|
|
|
5
6
|
// src/worker.ts
|
|
6
7
|
import url from "node:url";
|
|
7
8
|
import path from "node:path";
|
|
8
|
-
import child from "node:child_process";
|
|
9
9
|
import { EventEmitter } from "node:events";
|
|
10
|
+
import { ProcessFactory } from "@wdio/xvfb";
|
|
10
11
|
import logger from "@wdio/logger";
|
|
11
12
|
|
|
12
13
|
// src/transformStream.ts
|
|
@@ -202,6 +203,7 @@ var WorkerInstance = class extends EventEmitter {
|
|
|
202
203
|
sessionId;
|
|
203
204
|
server;
|
|
204
205
|
logsAggregator = [];
|
|
206
|
+
#processFactory;
|
|
205
207
|
instances;
|
|
206
208
|
isMultiremote;
|
|
207
209
|
isBusy = false;
|
|
@@ -221,8 +223,9 @@ var WorkerInstance = class extends EventEmitter {
|
|
|
221
223
|
* @param {string[]} specs list of paths to test files to run in this worker
|
|
222
224
|
* @param {number} retries number of retries remaining
|
|
223
225
|
* @param {object} execArgv execution arguments for the test run
|
|
226
|
+
* @param {XvfbManager} xvfbManager configured XvfbManager instance
|
|
224
227
|
*/
|
|
225
|
-
constructor(config, { cid, configFile, caps, specs, execArgv, retries }, stdout, stderr) {
|
|
228
|
+
constructor(config, { cid, configFile, caps, specs, execArgv, retries }, stdout, stderr, xvfbManager) {
|
|
226
229
|
super();
|
|
227
230
|
this.cid = cid;
|
|
228
231
|
this.config = config;
|
|
@@ -234,6 +237,7 @@ var WorkerInstance = class extends EventEmitter {
|
|
|
234
237
|
this.retries = retries;
|
|
235
238
|
this.stdout = stdout;
|
|
236
239
|
this.stderr = stderr;
|
|
240
|
+
this.#processFactory = new ProcessFactory(xvfbManager);
|
|
237
241
|
this.isReady = new Promise((resolve) => {
|
|
238
242
|
this.isReadyResolver = resolve;
|
|
239
243
|
});
|
|
@@ -244,7 +248,7 @@ var WorkerInstance = class extends EventEmitter {
|
|
|
244
248
|
/**
|
|
245
249
|
* spawns process to kick of wdio-runner
|
|
246
250
|
*/
|
|
247
|
-
startProcess() {
|
|
251
|
+
async startProcess() {
|
|
248
252
|
const { cid, execArgv } = this;
|
|
249
253
|
const argv = process.argv.slice(2);
|
|
250
254
|
const runnerEnv = Object.assign({
|
|
@@ -258,12 +262,16 @@ var WorkerInstance = class extends EventEmitter {
|
|
|
258
262
|
}
|
|
259
263
|
runnerEnv.NODE_OPTIONS = process.env.NODE_OPTIONS + " " + (runnerEnv.NODE_OPTIONS || "");
|
|
260
264
|
log.info(`Start worker ${cid} with arg: ${argv.join(" ")}`);
|
|
261
|
-
const childProcess = this.childProcess =
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
const childProcess = this.childProcess = await this.#processFactory.createWorkerProcess(
|
|
266
|
+
path.join(__dirname, "run.js"),
|
|
267
|
+
argv,
|
|
268
|
+
{
|
|
269
|
+
cwd: process.cwd(),
|
|
270
|
+
env: runnerEnv,
|
|
271
|
+
execArgv,
|
|
272
|
+
stdio: ["inherit", "pipe", "pipe", "ipc"]
|
|
273
|
+
}
|
|
274
|
+
);
|
|
267
275
|
childProcess.on("message", this._handleMessage.bind(this));
|
|
268
276
|
childProcess.on("error", this._handleError.bind(this));
|
|
269
277
|
childProcess.on("exit", this._handleExit.bind(this));
|
|
@@ -333,13 +341,13 @@ var WorkerInstance = class extends EventEmitter {
|
|
|
333
341
|
* @param command method to run in wdio-runner
|
|
334
342
|
* @param args arguments for functions to call
|
|
335
343
|
*/
|
|
336
|
-
postMessage(command, args, requiresSetup = false) {
|
|
344
|
+
async postMessage(command, args, requiresSetup = false) {
|
|
337
345
|
const { cid, configFile, capabilities, specs, retries, isBusy } = this;
|
|
338
346
|
if (isBusy && !ACCEPTABLE_BUSY_COMMANDS.includes(command)) {
|
|
339
347
|
return log.info(`worker with cid ${cid} already busy and can't take new commands`);
|
|
340
348
|
}
|
|
341
349
|
if (!this.childProcess) {
|
|
342
|
-
this.childProcess = this.startProcess();
|
|
350
|
+
this.childProcess = await this.startProcess();
|
|
343
351
|
}
|
|
344
352
|
const cmd = { cid, command, configFile, args, caps: capabilities, specs, retries };
|
|
345
353
|
log.debug(`Send command ${command} to worker with cid "${cid}"`);
|
|
@@ -356,42 +364,86 @@ var WorkerInstance = class extends EventEmitter {
|
|
|
356
364
|
// src/index.ts
|
|
357
365
|
var log2 = logger2("@wdio/local-runner");
|
|
358
366
|
var LocalRunner = class {
|
|
359
|
-
constructor(_options,
|
|
367
|
+
constructor(_options, config) {
|
|
360
368
|
this._options = _options;
|
|
361
|
-
this.
|
|
369
|
+
this.config = config;
|
|
370
|
+
this.xvfbManager = new XvfbManager({
|
|
371
|
+
xvfbMaxRetries: this.config.xvfbMaxRetries,
|
|
372
|
+
xvfbRetryDelay: this.config.xvfbRetryDelay
|
|
373
|
+
});
|
|
362
374
|
}
|
|
363
375
|
workerPool = {};
|
|
376
|
+
xvfbInitialized = false;
|
|
377
|
+
xvfbManager;
|
|
364
378
|
stdout = new WritableStreamBuffer(BUFFER_OPTIONS);
|
|
365
379
|
stderr = new WritableStreamBuffer(BUFFER_OPTIONS);
|
|
366
380
|
/**
|
|
367
|
-
*
|
|
381
|
+
* initialize local runner environment
|
|
368
382
|
*/
|
|
369
|
-
initialize() {
|
|
383
|
+
async initialize() {
|
|
370
384
|
}
|
|
371
385
|
getWorkerCount() {
|
|
372
386
|
return Object.keys(this.workerPool).length;
|
|
373
387
|
}
|
|
374
388
|
async run({ command, args, ...workerOptions }) {
|
|
389
|
+
if (!this.xvfbInitialized) {
|
|
390
|
+
await this.initializeXvfb(workerOptions);
|
|
391
|
+
this.xvfbInitialized = true;
|
|
392
|
+
}
|
|
375
393
|
const workerCnt = this.getWorkerCount();
|
|
376
394
|
if (workerCnt >= process.stdout.getMaxListeners() - 2) {
|
|
377
395
|
process.stdout.setMaxListeners(workerCnt + 2);
|
|
378
396
|
process.stderr.setMaxListeners(workerCnt + 2);
|
|
379
397
|
}
|
|
380
|
-
const worker = new WorkerInstance(
|
|
398
|
+
const worker = new WorkerInstance(
|
|
399
|
+
this.config,
|
|
400
|
+
workerOptions,
|
|
401
|
+
this.stdout,
|
|
402
|
+
this.stderr,
|
|
403
|
+
this.xvfbManager
|
|
404
|
+
);
|
|
381
405
|
this.workerPool[workerOptions.cid] = worker;
|
|
382
|
-
worker.postMessage(command, args);
|
|
406
|
+
await worker.postMessage(command, args);
|
|
383
407
|
return worker;
|
|
384
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Initialize XVFB with capability-aware detection
|
|
411
|
+
*/
|
|
412
|
+
async initializeXvfb(workerOptions) {
|
|
413
|
+
if (this.config.autoXvfb === false) {
|
|
414
|
+
log2.info("Skipping automatic Xvfb initialization (disabled by config)");
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
try {
|
|
418
|
+
const capabilities = workerOptions.caps;
|
|
419
|
+
const xvfbInitialized = await this.xvfbManager.init(capabilities);
|
|
420
|
+
if (xvfbInitialized) {
|
|
421
|
+
log2.info("Xvfb is ready for use");
|
|
422
|
+
}
|
|
423
|
+
} catch (error) {
|
|
424
|
+
log2.warn(
|
|
425
|
+
"Failed to initialize Xvfb, continuing without virtual display:",
|
|
426
|
+
error
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
385
430
|
/**
|
|
386
431
|
* shutdown all worker processes
|
|
387
432
|
*
|
|
388
433
|
* @return {Promise} resolves when all worker have been shutdown or
|
|
389
434
|
* a timeout was reached
|
|
390
435
|
*/
|
|
391
|
-
shutdown() {
|
|
436
|
+
async shutdown() {
|
|
392
437
|
log2.info("Shutting down spawned worker");
|
|
393
438
|
for (const [cid, worker] of Object.entries(this.workerPool)) {
|
|
394
|
-
const {
|
|
439
|
+
const {
|
|
440
|
+
capabilities,
|
|
441
|
+
server,
|
|
442
|
+
sessionId,
|
|
443
|
+
config,
|
|
444
|
+
isMultiremote,
|
|
445
|
+
instances
|
|
446
|
+
} = worker;
|
|
395
447
|
let payload = {};
|
|
396
448
|
if (config && config.watch && (sessionId || isMultiremote)) {
|
|
397
449
|
payload = {
|
|
@@ -405,12 +457,14 @@ var LocalRunner = class {
|
|
|
405
457
|
delete this.workerPool[cid];
|
|
406
458
|
continue;
|
|
407
459
|
}
|
|
408
|
-
worker.postMessage("endSession", payload);
|
|
460
|
+
await worker.postMessage("endSession", payload);
|
|
409
461
|
}
|
|
410
|
-
|
|
462
|
+
const shutdownResult = await new Promise((resolve) => {
|
|
411
463
|
const timeout = setTimeout(resolve, SHUTDOWN_TIMEOUT);
|
|
412
464
|
const interval = setInterval(() => {
|
|
413
|
-
const busyWorker = Object.entries(this.workerPool).filter(
|
|
465
|
+
const busyWorker = Object.entries(this.workerPool).filter(
|
|
466
|
+
([, worker]) => worker.isBusy
|
|
467
|
+
).length;
|
|
414
468
|
log2.info(`Waiting for ${busyWorker} to shut down gracefully`);
|
|
415
469
|
if (busyWorker === 0) {
|
|
416
470
|
clearTimeout(timeout);
|
|
@@ -420,6 +474,10 @@ var LocalRunner = class {
|
|
|
420
474
|
}
|
|
421
475
|
}, 250);
|
|
422
476
|
});
|
|
477
|
+
if (this.xvfbManager.shouldRun()) {
|
|
478
|
+
log2.info("Xvfb cleanup handled automatically by xvfb-run");
|
|
479
|
+
}
|
|
480
|
+
return shutdownResult;
|
|
423
481
|
}
|
|
424
482
|
};
|
|
425
483
|
export {
|
package/build/worker.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import child from 'node:child_process';
|
|
2
1
|
import { EventEmitter } from 'node:events';
|
|
3
2
|
import type { ChildProcess } from 'node:child_process';
|
|
4
3
|
import type { WritableStreamBuffer } from 'stream-buffers';
|
|
4
|
+
import { type XvfbManager } from '@wdio/xvfb';
|
|
5
5
|
import type { Workers } from '@wdio/types';
|
|
6
6
|
/**
|
|
7
7
|
* WorkerInstance
|
|
@@ -9,6 +9,7 @@ import type { Workers } from '@wdio/types';
|
|
|
9
9
|
* session lifetime.
|
|
10
10
|
*/
|
|
11
11
|
export default class WorkerInstance extends EventEmitter implements Workers.Worker {
|
|
12
|
+
#private;
|
|
12
13
|
cid: string;
|
|
13
14
|
config: WebdriverIO.Config;
|
|
14
15
|
configFile: string;
|
|
@@ -42,12 +43,13 @@ export default class WorkerInstance extends EventEmitter implements Workers.Work
|
|
|
42
43
|
* @param {string[]} specs list of paths to test files to run in this worker
|
|
43
44
|
* @param {number} retries number of retries remaining
|
|
44
45
|
* @param {object} execArgv execution arguments for the test run
|
|
46
|
+
* @param {XvfbManager} xvfbManager configured XvfbManager instance
|
|
45
47
|
*/
|
|
46
|
-
constructor(config: WebdriverIO.Config, { cid, configFile, caps, specs, execArgv, retries }: Workers.WorkerRunPayload, stdout: WritableStreamBuffer, stderr: WritableStreamBuffer);
|
|
48
|
+
constructor(config: WebdriverIO.Config, { cid, configFile, caps, specs, execArgv, retries }: Workers.WorkerRunPayload, stdout: WritableStreamBuffer, stderr: WritableStreamBuffer, xvfbManager: XvfbManager);
|
|
47
49
|
/**
|
|
48
50
|
* spawns process to kick of wdio-runner
|
|
49
51
|
*/
|
|
50
|
-
startProcess():
|
|
52
|
+
startProcess(): Promise<ChildProcess>;
|
|
51
53
|
private _handleMessage;
|
|
52
54
|
private _handleError;
|
|
53
55
|
private _handleExit;
|
|
@@ -56,6 +58,6 @@ export default class WorkerInstance extends EventEmitter implements Workers.Work
|
|
|
56
58
|
* @param command method to run in wdio-runner
|
|
57
59
|
* @param args arguments for functions to call
|
|
58
60
|
*/
|
|
59
|
-
postMessage(command: string, args: Workers.WorkerMessageArgs, requiresSetup?: boolean): void
|
|
61
|
+
postMessage(command: string, args: Workers.WorkerMessageArgs, requiresSetup?: boolean): Promise<void>;
|
|
60
62
|
}
|
|
61
63
|
//# sourceMappingURL=worker.d.ts.map
|
package/build/worker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAmB1C;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,YAAa,YAAW,OAAO,CAAC,MAAM;;IAC9E,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,WAAW,CAAC,MAAM,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAElB,IAAI,EAAE,WAAW,CAAC,YAAY,CAAA;IAE9B,YAAY,EAAE,WAAW,CAAC,YAAY,CAAA;IACtC,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,oBAAoB,CAAA;IAC5B,MAAM,EAAE,oBAAoB,CAAA;IAC5B,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,cAAc,EAAE,MAAM,EAAE,CAAK;IAG7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjD,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB,MAAM,UAAQ;IACd,QAAQ,UAAQ;IAChB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;IACzB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;IACzB,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,IAAI,CAAW;IAC3E,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,IAAI,CAAW;IAE3E;;;;;;;;;;OAUG;gBAEC,MAAM,EAAE,WAAW,CAAC,MAAM,EAC1B,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,gBAAgB,EAC7E,MAAM,EAAE,oBAAoB,EAC5B,MAAM,EAAE,oBAAoB,EAC5B,WAAW,EAAE,WAAW;IAmB5B;;OAEG;IACG,YAAY;IA2DlB,OAAO,CAAC,cAAc;IAsDtB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,WAAW;IAkBnB;;;;OAIG;IACG,WAAW,CAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,aAAa,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CA0B7G"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wdio/local-runner",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.19.0",
|
|
4
4
|
"description": "A WebdriverIO runner to run tests locally",
|
|
5
5
|
"author": "Christian Bromann <mail@bromann.dev>",
|
|
6
6
|
"homepage": "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-local-runner",
|
|
@@ -39,8 +39,9 @@
|
|
|
39
39
|
"@types/node": "^20.1.0",
|
|
40
40
|
"@wdio/logger": "9.18.0",
|
|
41
41
|
"@wdio/repl": "9.16.2",
|
|
42
|
-
"@wdio/runner": "9.
|
|
43
|
-
"@wdio/types": "9.
|
|
42
|
+
"@wdio/runner": "9.19.0",
|
|
43
|
+
"@wdio/types": "9.19.0",
|
|
44
|
+
"@wdio/xvfb": "9.19.0",
|
|
44
45
|
"exit-hook": "^4.0.0",
|
|
45
46
|
"expect-webdriverio": "^5.3.4",
|
|
46
47
|
"split2": "^4.1.0",
|
|
@@ -52,5 +53,5 @@
|
|
|
52
53
|
"publishConfig": {
|
|
53
54
|
"access": "public"
|
|
54
55
|
},
|
|
55
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "be9a42358a6646d48c3ce5a341761f55aa605b24"
|
|
56
57
|
}
|