@cucumber/cucumber 10.9.0 → 11.0.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/lib/api/run_cucumber.js +8 -10
- package/lib/api/run_cucumber.js.map +1 -1
- package/lib/{runtime → assemble}/assemble_test_cases.d.ts +4 -6
- package/lib/{runtime → assemble}/assemble_test_cases.js +9 -8
- package/lib/assemble/assemble_test_cases.js.map +1 -0
- package/lib/assemble/index.d.ts +2 -0
- package/lib/assemble/index.js +19 -0
- package/lib/assemble/index.js.map +1 -0
- package/lib/assemble/types.d.ts +10 -0
- package/lib/{runtime/parallel/command_types.js → assemble/types.js} +1 -1
- package/lib/assemble/types.js.map +1 -0
- package/lib/cli/helpers.d.ts +0 -23
- package/lib/cli/helpers.js +1 -33
- package/lib/cli/helpers.js.map +1 -1
- package/lib/index.d.ts +0 -16
- package/lib/index.js +1 -16
- package/lib/index.js.map +1 -1
- package/lib/runtime/coordinator.d.ts +16 -0
- package/lib/runtime/coordinator.js +42 -0
- package/lib/runtime/coordinator.js.map +1 -0
- package/lib/runtime/helpers.d.ts +3 -3
- package/lib/runtime/helpers.js.map +1 -1
- package/lib/runtime/index.d.ts +2 -41
- package/lib/runtime/index.js +14 -81
- package/lib/runtime/index.js.map +1 -1
- package/lib/runtime/make_runtime.d.ts +17 -0
- package/lib/runtime/make_runtime.js +14 -0
- package/lib/runtime/make_runtime.js.map +1 -0
- package/lib/runtime/parallel/adapter.d.ts +48 -0
- package/lib/runtime/parallel/adapter.js +152 -0
- package/lib/runtime/parallel/adapter.js.map +1 -0
- package/lib/runtime/parallel/run_worker.js +2 -5
- package/lib/runtime/parallel/run_worker.js.map +1 -1
- package/lib/runtime/parallel/types.d.ts +32 -0
- package/lib/runtime/parallel/types.js +3 -0
- package/lib/runtime/parallel/types.js.map +1 -0
- package/lib/runtime/parallel/worker.d.ts +8 -9
- package/lib/runtime/parallel/worker.js +28 -44
- package/lib/runtime/parallel/worker.js.map +1 -1
- package/lib/runtime/serial/adapter.d.ts +13 -0
- package/lib/runtime/serial/adapter.js +24 -0
- package/lib/runtime/serial/adapter.js.map +1 -0
- package/lib/runtime/stopwatch.d.ts +2 -2
- package/lib/runtime/stopwatch.js +3 -4
- package/lib/runtime/stopwatch.js.map +1 -1
- package/lib/runtime/test_case_runner.d.ts +1 -4
- package/lib/runtime/test_case_runner.js +6 -7
- package/lib/runtime/test_case_runner.js.map +1 -1
- package/lib/runtime/types.d.ts +17 -0
- package/lib/runtime/types.js +3 -0
- package/lib/runtime/types.js.map +1 -0
- package/lib/runtime/worker.d.ts +18 -0
- package/lib/runtime/worker.js +57 -0
- package/lib/runtime/worker.js.map +1 -0
- package/lib/support_code_library_builder/index.d.ts +2 -3
- package/lib/support_code_library_builder/index.js.map +1 -1
- package/lib/support_code_library_builder/types.d.ts +5 -0
- package/lib/support_code_library_builder/types.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/version.js.map +1 -1
- package/lib/wrapper.mjs +1 -3
- package/package.json +4 -4
- package/lib/api/runtime.d.ts +0 -18
- package/lib/api/runtime.js +0 -33
- package/lib/api/runtime.js.map +0 -1
- package/lib/runtime/assemble_test_cases.js.map +0 -1
- package/lib/runtime/parallel/command_types.d.ts +0 -31
- package/lib/runtime/parallel/command_types.js.map +0 -1
- package/lib/runtime/parallel/coordinator.d.ts +0 -66
- package/lib/runtime/parallel/coordinator.js +0 -209
- package/lib/runtime/parallel/coordinator.js.map +0 -1
package/lib/runtime/index.js
CHANGED
|
@@ -1,85 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
4
15
|
};
|
|
5
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
const helpers_1 = require("./helpers");
|
|
8
|
-
const run_test_run_hooks_1 = require("./run_test_run_hooks");
|
|
9
|
-
const stopwatch_1 = require("./stopwatch");
|
|
10
|
-
const test_case_runner_1 = __importDefault(require("./test_case_runner"));
|
|
11
|
-
class Runtime {
|
|
12
|
-
eventBroadcaster;
|
|
13
|
-
eventDataCollector;
|
|
14
|
-
stopwatch;
|
|
15
|
-
newId;
|
|
16
|
-
options;
|
|
17
|
-
pickleIds;
|
|
18
|
-
supportCodeLibrary;
|
|
19
|
-
success;
|
|
20
|
-
runTestRunHooks;
|
|
21
|
-
constructor({ eventBroadcaster, eventDataCollector, newId, options, pickleIds, supportCodeLibrary, }) {
|
|
22
|
-
this.eventBroadcaster = eventBroadcaster;
|
|
23
|
-
this.eventDataCollector = eventDataCollector;
|
|
24
|
-
this.stopwatch = (0, stopwatch_1.create)();
|
|
25
|
-
this.newId = newId;
|
|
26
|
-
this.options = options;
|
|
27
|
-
this.pickleIds = pickleIds;
|
|
28
|
-
this.supportCodeLibrary = supportCodeLibrary;
|
|
29
|
-
this.success = true;
|
|
30
|
-
this.runTestRunHooks = (0, run_test_run_hooks_1.makeRunTestRunHooks)(this.options.dryRun, this.supportCodeLibrary.defaultTimeout, this.options.worldParameters, (name, location) => `${name} hook errored, process exiting: ${location}`);
|
|
31
|
-
}
|
|
32
|
-
async runTestCase(pickleId, testCase) {
|
|
33
|
-
const pickle = this.eventDataCollector.getPickle(pickleId);
|
|
34
|
-
const retries = (0, helpers_1.retriesForPickle)(pickle, this.options);
|
|
35
|
-
const skip = this.options.dryRun || (this.options.failFast && !this.success);
|
|
36
|
-
const testCaseRunner = new test_case_runner_1.default({
|
|
37
|
-
eventBroadcaster: this.eventBroadcaster,
|
|
38
|
-
stopwatch: this.stopwatch,
|
|
39
|
-
gherkinDocument: this.eventDataCollector.getGherkinDocument(pickle.uri),
|
|
40
|
-
newId: this.newId,
|
|
41
|
-
pickle,
|
|
42
|
-
testCase,
|
|
43
|
-
retries,
|
|
44
|
-
skip,
|
|
45
|
-
filterStackTraces: this.options.filterStacktraces,
|
|
46
|
-
supportCodeLibrary: this.supportCodeLibrary,
|
|
47
|
-
worldParameters: this.options.worldParameters,
|
|
48
|
-
});
|
|
49
|
-
const status = await testCaseRunner.run();
|
|
50
|
-
if ((0, helpers_1.shouldCauseFailure)(status, this.options)) {
|
|
51
|
-
this.success = false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
async start() {
|
|
55
|
-
const testRunStarted = {
|
|
56
|
-
testRunStarted: {
|
|
57
|
-
timestamp: this.stopwatch.timestamp(),
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
this.eventBroadcaster.emit('envelope', testRunStarted);
|
|
61
|
-
this.stopwatch.start();
|
|
62
|
-
await this.runTestRunHooks(this.supportCodeLibrary.beforeTestRunHookDefinitions, 'a BeforeAll');
|
|
63
|
-
const assembledTestCases = await (0, assemble_test_cases_1.assembleTestCases)({
|
|
64
|
-
eventBroadcaster: this.eventBroadcaster,
|
|
65
|
-
newId: this.newId,
|
|
66
|
-
pickles: this.pickleIds.map((pickleId) => this.eventDataCollector.getPickle(pickleId)),
|
|
67
|
-
supportCodeLibrary: this.supportCodeLibrary,
|
|
68
|
-
});
|
|
69
|
-
for (const pickleId of this.pickleIds) {
|
|
70
|
-
await this.runTestCase(pickleId, assembledTestCases[pickleId]);
|
|
71
|
-
}
|
|
72
|
-
await this.runTestRunHooks(this.supportCodeLibrary.afterTestRunHookDefinitions.slice(0).reverse(), 'an AfterAll');
|
|
73
|
-
this.stopwatch.stop();
|
|
74
|
-
const testRunFinished = {
|
|
75
|
-
testRunFinished: {
|
|
76
|
-
timestamp: this.stopwatch.timestamp(),
|
|
77
|
-
success: this.success,
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
this.eventBroadcaster.emit('envelope', testRunFinished);
|
|
81
|
-
return this.success;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
exports.default = Runtime;
|
|
17
|
+
__exportStar(require("./make_runtime"), exports);
|
|
85
18
|
//# sourceMappingURL=index.js.map
|
package/lib/runtime/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA8B","sourcesContent":["export * from './make_runtime'\nexport { Runtime, RuntimeOptions } from './types'\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import { IdGenerator } from '@cucumber/messages';
|
|
4
|
+
import { IRunEnvironment, IRunOptionsRuntime } from '../api';
|
|
5
|
+
import { ILogger } from '../logger';
|
|
6
|
+
import { SourcedPickle } from '../assemble';
|
|
7
|
+
import { SupportCodeLibrary } from '../support_code_library_builder/types';
|
|
8
|
+
import { Runtime } from './types';
|
|
9
|
+
export declare function makeRuntime({ environment, logger, eventBroadcaster, sourcedPickles, newId, supportCodeLibrary, options, }: {
|
|
10
|
+
environment: IRunEnvironment;
|
|
11
|
+
logger: ILogger;
|
|
12
|
+
eventBroadcaster: EventEmitter;
|
|
13
|
+
newId: IdGenerator.NewId;
|
|
14
|
+
sourcedPickles: ReadonlyArray<SourcedPickle>;
|
|
15
|
+
supportCodeLibrary: SupportCodeLibrary;
|
|
16
|
+
options: IRunOptionsRuntime;
|
|
17
|
+
}): Promise<Runtime>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeRuntime = void 0;
|
|
4
|
+
const adapter_1 = require("./parallel/adapter");
|
|
5
|
+
const adapter_2 = require("./serial/adapter");
|
|
6
|
+
const coordinator_1 = require("./coordinator");
|
|
7
|
+
async function makeRuntime({ environment, logger, eventBroadcaster, sourcedPickles, newId, supportCodeLibrary, options, }) {
|
|
8
|
+
const adapter = options.parallel > 0
|
|
9
|
+
? new adapter_1.ChildProcessAdapter(environment, logger, eventBroadcaster, options, supportCodeLibrary)
|
|
10
|
+
: new adapter_2.InProcessAdapter(eventBroadcaster, newId, options, supportCodeLibrary);
|
|
11
|
+
return new coordinator_1.Coordinator(eventBroadcaster, newId, sourcedPickles, supportCodeLibrary, adapter);
|
|
12
|
+
}
|
|
13
|
+
exports.makeRuntime = makeRuntime;
|
|
14
|
+
//# sourceMappingURL=make_runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"make_runtime.js","sourceRoot":"","sources":["../../src/runtime/make_runtime.ts"],"names":[],"mappings":";;;AAOA,gDAAwD;AACxD,8CAAmD;AACnD,+CAA2C;AAEpC,KAAK,UAAU,WAAW,CAAC,EAChC,WAAW,EACX,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,KAAK,EACL,kBAAkB,EAClB,OAAO,GASR;IACC,MAAM,OAAO,GACX,OAAO,CAAC,QAAQ,GAAG,CAAC;QAClB,CAAC,CAAC,IAAI,6BAAmB,CACrB,WAAW,EACX,MAAM,EACN,gBAAgB,EAChB,OAAO,EACP,kBAAkB,CACnB;QACH,CAAC,CAAC,IAAI,0BAAgB,CAClB,gBAAgB,EAChB,KAAK,EACL,OAAO,EACP,kBAAkB,CACnB,CAAA;IACP,OAAO,IAAI,yBAAW,CACpB,gBAAgB,EAChB,KAAK,EACL,cAAc,EACd,kBAAkB,EAClB,OAAO,CACR,CAAA;AACH,CAAC;AAvCD,kCAuCC","sourcesContent":["import { EventEmitter } from 'node:events'\nimport { IdGenerator } from '@cucumber/messages'\nimport { IRunEnvironment, IRunOptionsRuntime } from '../api'\nimport { ILogger } from '../logger'\nimport { SourcedPickle } from '../assemble'\nimport { SupportCodeLibrary } from '../support_code_library_builder/types'\nimport { Runtime, RuntimeAdapter } from './types'\nimport { ChildProcessAdapter } from './parallel/adapter'\nimport { InProcessAdapter } from './serial/adapter'\nimport { Coordinator } from './coordinator'\n\nexport async function makeRuntime({\n environment,\n logger,\n eventBroadcaster,\n sourcedPickles,\n newId,\n supportCodeLibrary,\n options,\n}: {\n environment: IRunEnvironment\n logger: ILogger\n eventBroadcaster: EventEmitter\n newId: IdGenerator.NewId\n sourcedPickles: ReadonlyArray<SourcedPickle>\n supportCodeLibrary: SupportCodeLibrary\n options: IRunOptionsRuntime\n}): Promise<Runtime> {\n const adapter: RuntimeAdapter =\n options.parallel > 0\n ? new ChildProcessAdapter(\n environment,\n logger,\n eventBroadcaster,\n options,\n supportCodeLibrary\n )\n : new InProcessAdapter(\n eventBroadcaster,\n newId,\n options,\n supportCodeLibrary\n )\n return new Coordinator(\n eventBroadcaster,\n newId,\n sourcedPickles,\n supportCodeLibrary,\n adapter\n )\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { ChildProcess } from 'node:child_process';
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
import { SupportCodeLibrary } from '../../support_code_library_builder/types';
|
|
6
|
+
import { AssembledTestCase } from '../../assemble';
|
|
7
|
+
import { ILogger } from '../../logger';
|
|
8
|
+
import { RuntimeAdapter } from '../types';
|
|
9
|
+
import { IRunEnvironment, IRunOptionsRuntime } from '../../api';
|
|
10
|
+
import { WorkerToCoordinatorEvent } from './types';
|
|
11
|
+
declare const enum WorkerState {
|
|
12
|
+
'idle' = 0,
|
|
13
|
+
'closed' = 1,
|
|
14
|
+
'running' = 2,
|
|
15
|
+
'new' = 3
|
|
16
|
+
}
|
|
17
|
+
interface ManagedWorker {
|
|
18
|
+
state: WorkerState;
|
|
19
|
+
process: ChildProcess;
|
|
20
|
+
id: string;
|
|
21
|
+
}
|
|
22
|
+
interface WorkPlacement {
|
|
23
|
+
index: number;
|
|
24
|
+
item: AssembledTestCase;
|
|
25
|
+
}
|
|
26
|
+
export declare class ChildProcessAdapter implements RuntimeAdapter {
|
|
27
|
+
private readonly environment;
|
|
28
|
+
private readonly logger;
|
|
29
|
+
private readonly eventBroadcaster;
|
|
30
|
+
private readonly options;
|
|
31
|
+
private readonly supportCodeLibrary;
|
|
32
|
+
private idleInterventions;
|
|
33
|
+
private failing;
|
|
34
|
+
private onFinish;
|
|
35
|
+
private todo;
|
|
36
|
+
private readonly inProgress;
|
|
37
|
+
private readonly workers;
|
|
38
|
+
constructor(environment: IRunEnvironment, logger: ILogger, eventBroadcaster: EventEmitter, options: IRunOptionsRuntime, supportCodeLibrary: SupportCodeLibrary);
|
|
39
|
+
parseWorkerMessage(worker: ManagedWorker, message: WorkerToCoordinatorEvent): void;
|
|
40
|
+
awakenWorkers(triggeringWorker: ManagedWorker): void;
|
|
41
|
+
startWorker(id: string, total: number): void;
|
|
42
|
+
onWorkerProcessClose(exitCode: number): void;
|
|
43
|
+
run(assembledTestCases: ReadonlyArray<AssembledTestCase>): Promise<boolean>;
|
|
44
|
+
nextWorkPlacement(): WorkPlacement;
|
|
45
|
+
placementAt(index: number): WorkPlacement;
|
|
46
|
+
giveWork(worker: ManagedWorker, force?: boolean): void;
|
|
47
|
+
}
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ChildProcessAdapter = void 0;
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const runWorkerPath = node_path_1.default.resolve(__dirname, 'run_worker.js');
|
|
10
|
+
class ChildProcessAdapter {
|
|
11
|
+
environment;
|
|
12
|
+
logger;
|
|
13
|
+
eventBroadcaster;
|
|
14
|
+
options;
|
|
15
|
+
supportCodeLibrary;
|
|
16
|
+
idleInterventions = 0;
|
|
17
|
+
failing = false;
|
|
18
|
+
onFinish;
|
|
19
|
+
todo = [];
|
|
20
|
+
inProgress = {};
|
|
21
|
+
workers = {};
|
|
22
|
+
constructor(environment, logger, eventBroadcaster, options, supportCodeLibrary) {
|
|
23
|
+
this.environment = environment;
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
this.eventBroadcaster = eventBroadcaster;
|
|
26
|
+
this.options = options;
|
|
27
|
+
this.supportCodeLibrary = supportCodeLibrary;
|
|
28
|
+
}
|
|
29
|
+
parseWorkerMessage(worker, message) {
|
|
30
|
+
switch (message.type) {
|
|
31
|
+
case 'READY':
|
|
32
|
+
worker.state = 0 /* WorkerState.idle */;
|
|
33
|
+
this.awakenWorkers(worker);
|
|
34
|
+
break;
|
|
35
|
+
case 'ENVELOPE':
|
|
36
|
+
this.eventBroadcaster.emit('envelope', message.envelope);
|
|
37
|
+
break;
|
|
38
|
+
case 'FINISHED':
|
|
39
|
+
if (!message.success) {
|
|
40
|
+
this.failing = true;
|
|
41
|
+
}
|
|
42
|
+
delete this.inProgress[worker.id];
|
|
43
|
+
worker.state = 0 /* WorkerState.idle */;
|
|
44
|
+
this.awakenWorkers(worker);
|
|
45
|
+
break;
|
|
46
|
+
default:
|
|
47
|
+
throw new Error(`Unexpected message from worker: ${JSON.stringify(message)}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
awakenWorkers(triggeringWorker) {
|
|
51
|
+
Object.values(this.workers).forEach((worker) => {
|
|
52
|
+
if (worker.state === 0 /* WorkerState.idle */) {
|
|
53
|
+
this.giveWork(worker);
|
|
54
|
+
}
|
|
55
|
+
return worker.state !== 0 /* WorkerState.idle */;
|
|
56
|
+
});
|
|
57
|
+
if (Object.keys(this.inProgress).length == 0 && this.todo.length > 0) {
|
|
58
|
+
this.giveWork(triggeringWorker, true);
|
|
59
|
+
this.idleInterventions++;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
startWorker(id, total) {
|
|
63
|
+
const workerProcess = (0, node_child_process_1.fork)(runWorkerPath, [], {
|
|
64
|
+
cwd: this.environment.cwd,
|
|
65
|
+
env: {
|
|
66
|
+
...this.environment.env,
|
|
67
|
+
CUCUMBER_PARALLEL: 'true',
|
|
68
|
+
CUCUMBER_TOTAL_WORKERS: total.toString(),
|
|
69
|
+
CUCUMBER_WORKER_ID: id,
|
|
70
|
+
},
|
|
71
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
72
|
+
});
|
|
73
|
+
const worker = { state: 3 /* WorkerState.new */, process: workerProcess, id };
|
|
74
|
+
this.workers[id] = worker;
|
|
75
|
+
worker.process.on('message', (message) => {
|
|
76
|
+
this.parseWorkerMessage(worker, message);
|
|
77
|
+
});
|
|
78
|
+
worker.process.on('close', (exitCode) => {
|
|
79
|
+
worker.state = 1 /* WorkerState.closed */;
|
|
80
|
+
this.onWorkerProcessClose(exitCode);
|
|
81
|
+
});
|
|
82
|
+
worker.process.send({
|
|
83
|
+
type: 'INITIALIZE',
|
|
84
|
+
supportCodeCoordinates: this.supportCodeLibrary.originalCoordinates,
|
|
85
|
+
supportCodeIds: {
|
|
86
|
+
stepDefinitionIds: this.supportCodeLibrary.stepDefinitions.map((s) => s.id),
|
|
87
|
+
beforeTestCaseHookDefinitionIds: this.supportCodeLibrary.beforeTestCaseHookDefinitions.map((h) => h.id),
|
|
88
|
+
afterTestCaseHookDefinitionIds: this.supportCodeLibrary.afterTestCaseHookDefinitions.map((h) => h.id),
|
|
89
|
+
},
|
|
90
|
+
options: this.options,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
onWorkerProcessClose(exitCode) {
|
|
94
|
+
if (exitCode !== 0) {
|
|
95
|
+
this.failing = true;
|
|
96
|
+
}
|
|
97
|
+
if (Object.values(this.workers).every((x) => x.state === 1 /* WorkerState.closed */)) {
|
|
98
|
+
this.onFinish(!this.failing);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async run(assembledTestCases) {
|
|
102
|
+
this.todo = Array.from(assembledTestCases);
|
|
103
|
+
return await new Promise((resolve) => {
|
|
104
|
+
for (let i = 0; i < this.options.parallel; i++) {
|
|
105
|
+
this.startWorker(i.toString(), this.options.parallel);
|
|
106
|
+
}
|
|
107
|
+
this.onFinish = (status) => {
|
|
108
|
+
if (this.idleInterventions > 0) {
|
|
109
|
+
this.logger.warn(`WARNING: All workers went idle ${this.idleInterventions} time(s). Consider revising handler passed to setParallelCanAssign.`);
|
|
110
|
+
}
|
|
111
|
+
resolve(status);
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
nextWorkPlacement() {
|
|
116
|
+
for (let index = 0; index < this.todo.length; index++) {
|
|
117
|
+
const placement = this.placementAt(index);
|
|
118
|
+
if (this.supportCodeLibrary.parallelCanAssign(placement.item.pickle, Object.values(this.inProgress).map(({ pickle }) => pickle))) {
|
|
119
|
+
return placement;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
placementAt(index) {
|
|
125
|
+
return {
|
|
126
|
+
index,
|
|
127
|
+
item: this.todo[index],
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
giveWork(worker, force = false) {
|
|
131
|
+
if (this.todo.length < 1) {
|
|
132
|
+
worker.state = 2 /* WorkerState.running */;
|
|
133
|
+
worker.process.send({ type: 'FINALIZE' });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const workPlacement = force ? this.placementAt(0) : this.nextWorkPlacement();
|
|
137
|
+
if (workPlacement === null) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const { index: nextIndex, item } = workPlacement;
|
|
141
|
+
this.todo.splice(nextIndex, 1);
|
|
142
|
+
this.inProgress[worker.id] = item;
|
|
143
|
+
worker.state = 2 /* WorkerState.running */;
|
|
144
|
+
worker.process.send({
|
|
145
|
+
type: 'RUN',
|
|
146
|
+
assembledTestCase: item,
|
|
147
|
+
failing: this.failing,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.ChildProcessAdapter = ChildProcessAdapter;
|
|
152
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/runtime/parallel/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChildProcess, fork } from 'node:child_process'\nimport path from 'node:path'\nimport { EventEmitter } from 'node:events'\nimport { SupportCodeLibrary } from '../../support_code_library_builder/types'\nimport { AssembledTestCase } from '../../assemble'\nimport { ILogger } from '../../logger'\nimport { RuntimeAdapter } from '../types'\nimport { IRunEnvironment, IRunOptionsRuntime } from '../../api'\nimport {\n FinalizeCommand,\n InitializeCommand,\n RunCommand,\n WorkerToCoordinatorEvent,\n} from './types'\n\nconst runWorkerPath = path.resolve(__dirname, 'run_worker.js')\n\nconst enum WorkerState {\n 'idle',\n 'closed',\n 'running',\n 'new',\n}\n\ninterface ManagedWorker {\n state: WorkerState\n process: ChildProcess\n id: string\n}\n\ninterface WorkPlacement {\n index: number\n item: AssembledTestCase\n}\n\nexport class ChildProcessAdapter implements RuntimeAdapter {\n private idleInterventions: number = 0\n private failing: boolean = false\n private onFinish: (success: boolean) => void\n private todo: Array<AssembledTestCase> = []\n private readonly inProgress: Record<string, AssembledTestCase> = {}\n private readonly workers: Record<string, ManagedWorker> = {}\n\n constructor(\n private readonly environment: IRunEnvironment,\n private readonly logger: ILogger,\n private readonly eventBroadcaster: EventEmitter,\n private readonly options: IRunOptionsRuntime,\n private readonly supportCodeLibrary: SupportCodeLibrary\n ) {}\n\n parseWorkerMessage(\n worker: ManagedWorker,\n message: WorkerToCoordinatorEvent\n ): void {\n switch (message.type) {\n case 'READY':\n worker.state = WorkerState.idle\n this.awakenWorkers(worker)\n break\n case 'ENVELOPE':\n this.eventBroadcaster.emit('envelope', message.envelope)\n break\n case 'FINISHED':\n if (!message.success) {\n this.failing = true\n }\n delete this.inProgress[worker.id]\n worker.state = WorkerState.idle\n this.awakenWorkers(worker)\n break\n default:\n throw new Error(\n `Unexpected message from worker: ${JSON.stringify(message)}`\n )\n }\n }\n\n awakenWorkers(triggeringWorker: ManagedWorker): void {\n Object.values(this.workers).forEach((worker) => {\n if (worker.state === WorkerState.idle) {\n this.giveWork(worker)\n }\n return worker.state !== WorkerState.idle\n })\n\n if (Object.keys(this.inProgress).length == 0 && this.todo.length > 0) {\n this.giveWork(triggeringWorker, true)\n this.idleInterventions++\n }\n }\n\n startWorker(id: string, total: number): void {\n const workerProcess = fork(runWorkerPath, [], {\n cwd: this.environment.cwd,\n env: {\n ...this.environment.env,\n CUCUMBER_PARALLEL: 'true',\n CUCUMBER_TOTAL_WORKERS: total.toString(),\n CUCUMBER_WORKER_ID: id,\n },\n stdio: ['inherit', 'inherit', 'inherit', 'ipc'],\n })\n const worker = { state: WorkerState.new, process: workerProcess, id }\n this.workers[id] = worker\n worker.process.on('message', (message: WorkerToCoordinatorEvent) => {\n this.parseWorkerMessage(worker, message)\n })\n worker.process.on('close', (exitCode) => {\n worker.state = WorkerState.closed\n this.onWorkerProcessClose(exitCode)\n })\n worker.process.send({\n type: 'INITIALIZE',\n supportCodeCoordinates: this.supportCodeLibrary.originalCoordinates,\n supportCodeIds: {\n stepDefinitionIds: this.supportCodeLibrary.stepDefinitions.map(\n (s) => s.id\n ),\n beforeTestCaseHookDefinitionIds:\n this.supportCodeLibrary.beforeTestCaseHookDefinitions.map(\n (h) => h.id\n ),\n afterTestCaseHookDefinitionIds:\n this.supportCodeLibrary.afterTestCaseHookDefinitions.map((h) => h.id),\n },\n options: this.options,\n } satisfies InitializeCommand)\n }\n\n onWorkerProcessClose(exitCode: number): void {\n if (exitCode !== 0) {\n this.failing = true\n }\n\n if (\n Object.values(this.workers).every((x) => x.state === WorkerState.closed)\n ) {\n this.onFinish(!this.failing)\n }\n }\n\n async run(\n assembledTestCases: ReadonlyArray<AssembledTestCase>\n ): Promise<boolean> {\n this.todo = Array.from(assembledTestCases)\n return await new Promise<boolean>((resolve) => {\n for (let i = 0; i < this.options.parallel; i++) {\n this.startWorker(i.toString(), this.options.parallel)\n }\n this.onFinish = (status) => {\n if (this.idleInterventions > 0) {\n this.logger.warn(\n `WARNING: All workers went idle ${this.idleInterventions} time(s). Consider revising handler passed to setParallelCanAssign.`\n )\n }\n\n resolve(status)\n }\n })\n }\n\n nextWorkPlacement(): WorkPlacement {\n for (let index = 0; index < this.todo.length; index++) {\n const placement = this.placementAt(index)\n if (\n this.supportCodeLibrary.parallelCanAssign(\n placement.item.pickle,\n Object.values(this.inProgress).map(({ pickle }) => pickle)\n )\n ) {\n return placement\n }\n }\n\n return null\n }\n\n placementAt(index: number): WorkPlacement {\n return {\n index,\n item: this.todo[index],\n }\n }\n\n giveWork(worker: ManagedWorker, force: boolean = false): void {\n if (this.todo.length < 1) {\n worker.state = WorkerState.running\n worker.process.send({ type: 'FINALIZE' } satisfies FinalizeCommand)\n return\n }\n\n const workPlacement = force ? this.placementAt(0) : this.nextWorkPlacement()\n\n if (workPlacement === null) {\n return\n }\n\n const { index: nextIndex, item } = workPlacement\n\n this.todo.splice(nextIndex, 1)\n this.inProgress[worker.id] = item\n worker.state = WorkerState.running\n worker.process.send({\n type: 'RUN',\n assembledTestCase: item,\n failing: this.failing,\n } satisfies RunCommand)\n }\n}\n"]}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
const value_checker_1 = require("../../value_checker");
|
|
7
|
-
const worker_1 =
|
|
4
|
+
const worker_1 = require("./worker");
|
|
8
5
|
function run() {
|
|
9
6
|
const exit = (exitCode, error, message) => {
|
|
10
7
|
if ((0, value_checker_1.doesHaveValue)(error)) {
|
|
@@ -12,7 +9,7 @@ function run() {
|
|
|
12
9
|
}
|
|
13
10
|
process.exit(exitCode);
|
|
14
11
|
};
|
|
15
|
-
const worker = new worker_1.
|
|
12
|
+
const worker = new worker_1.ChildProcessWorker({
|
|
16
13
|
id: process.env.CUCUMBER_WORKER_ID,
|
|
17
14
|
sendMessage: (message) => process.send(message),
|
|
18
15
|
cwd: process.cwd(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run_worker.js","sourceRoot":"","sources":["../../../src/runtime/parallel/run_worker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run_worker.js","sourceRoot":"","sources":["../../../src/runtime/parallel/run_worker.ts"],"names":[],"mappings":";;AAAA,uDAAmD;AACnD,qCAA6C;AAE7C,SAAS,GAAG;IACV,MAAM,IAAI,GAAG,CAAC,QAAgB,EAAE,KAAa,EAAE,OAAgB,EAAQ,EAAE;QACvE,IAAI,IAAA,6BAAa,EAAC,KAAK,CAAC,EAAE;YACxB,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA,CAAC,iCAAiC;SACtF;QACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACxB,CAAC,CAAA;IACD,MAAM,MAAM,GAAG,IAAI,2BAAkB,CAAC;QACpC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAClC,WAAW,EAAE,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QACpD,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,IAAI;KACL,CAAC,CAAA;IACF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,CAAM,EAAQ,EAAE;QACrC,MAAM;aACH,cAAc,CAAC,CAAC,CAAC;aACjB,KAAK,CAAC,CAAC,KAAY,EAAE,EAAE,CACtB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,2CAA2C,CAAC,CAC5D,CAAA;IACL,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,GAAG,EAAE,CAAA","sourcesContent":["import { doesHaveValue } from '../../value_checker'\nimport { ChildProcessWorker } from './worker'\n\nfunction run(): void {\n const exit = (exitCode: number, error?: Error, message?: string): void => {\n if (doesHaveValue(error)) {\n console.error(new Error(message, { cause: error })) // eslint-disable-line no-console\n }\n process.exit(exitCode)\n }\n const worker = new ChildProcessWorker({\n id: process.env.CUCUMBER_WORKER_ID,\n sendMessage: (message: any) => process.send(message),\n cwd: process.cwd(),\n exit,\n })\n process.on('message', (m: any): void => {\n worker\n .receiveMessage(m)\n .catch((error: Error) =>\n exit(1, error, 'Unexpected error on worker.receiveMessage')\n )\n })\n}\n\nrun()\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Envelope } from '@cucumber/messages';
|
|
2
|
+
import { RuntimeOptions } from '../index';
|
|
3
|
+
import { ISupportCodeCoordinates } from '../../api';
|
|
4
|
+
import { AssembledTestCase } from '../../assemble';
|
|
5
|
+
import { CanonicalSupportCodeIds } from '../../support_code_library_builder/types';
|
|
6
|
+
export type CoordinatorToWorkerCommand = InitializeCommand | RunCommand | FinalizeCommand;
|
|
7
|
+
export interface InitializeCommand {
|
|
8
|
+
type: 'INITIALIZE';
|
|
9
|
+
supportCodeCoordinates: ISupportCodeCoordinates;
|
|
10
|
+
supportCodeIds: CanonicalSupportCodeIds;
|
|
11
|
+
options: RuntimeOptions;
|
|
12
|
+
}
|
|
13
|
+
export interface RunCommand {
|
|
14
|
+
type: 'RUN';
|
|
15
|
+
assembledTestCase: AssembledTestCase;
|
|
16
|
+
failing: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface FinalizeCommand {
|
|
19
|
+
type: 'FINALIZE';
|
|
20
|
+
}
|
|
21
|
+
export type WorkerToCoordinatorEvent = ReadyEvent | EnvelopeEvent | FinishedEvent;
|
|
22
|
+
export interface ReadyEvent {
|
|
23
|
+
type: 'READY';
|
|
24
|
+
}
|
|
25
|
+
export interface EnvelopeEvent {
|
|
26
|
+
type: 'ENVELOPE';
|
|
27
|
+
envelope: Envelope;
|
|
28
|
+
}
|
|
29
|
+
export interface FinishedEvent {
|
|
30
|
+
type: 'FINISHED';
|
|
31
|
+
success: boolean;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/runtime/parallel/types.ts"],"names":[],"mappings":"","sourcesContent":["import { Envelope } from '@cucumber/messages'\nimport { RuntimeOptions } from '../index'\nimport { ISupportCodeCoordinates } from '../../api'\nimport { AssembledTestCase } from '../../assemble'\nimport { CanonicalSupportCodeIds } from '../../support_code_library_builder/types'\n\n// Messages from Coordinator to Worker\n\nexport type CoordinatorToWorkerCommand =\n | InitializeCommand\n | RunCommand\n | FinalizeCommand\n\nexport interface InitializeCommand {\n type: 'INITIALIZE'\n supportCodeCoordinates: ISupportCodeCoordinates\n supportCodeIds: CanonicalSupportCodeIds\n options: RuntimeOptions\n}\n\nexport interface RunCommand {\n type: 'RUN'\n assembledTestCase: AssembledTestCase\n failing: boolean\n}\n\nexport interface FinalizeCommand {\n type: 'FINALIZE'\n}\n\n// Messages from Worker to Coordinator\n\nexport type WorkerToCoordinatorEvent =\n | ReadyEvent\n | EnvelopeEvent\n | FinishedEvent\n\nexport interface ReadyEvent {\n type: 'READY'\n}\n\nexport interface EnvelopeEvent {\n type: 'ENVELOPE'\n envelope: Envelope\n}\n\nexport interface FinishedEvent {\n type: 'FINISHED'\n success: boolean\n}\n"]}
|
|
@@ -1,26 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WorkerToCoordinatorEvent, CoordinatorToWorkerCommand, InitializeCommand, RunCommand } from './types';
|
|
2
2
|
type IExitFunction = (exitCode: number, error?: Error, message?: string) => void;
|
|
3
|
-
type IMessageSender = (command:
|
|
4
|
-
export
|
|
3
|
+
type IMessageSender = (command: WorkerToCoordinatorEvent) => void;
|
|
4
|
+
export declare class ChildProcessWorker {
|
|
5
5
|
private readonly cwd;
|
|
6
6
|
private readonly exit;
|
|
7
7
|
private readonly id;
|
|
8
8
|
private readonly eventBroadcaster;
|
|
9
|
-
private filterStacktraces;
|
|
10
9
|
private readonly newId;
|
|
11
10
|
private readonly sendMessage;
|
|
11
|
+
private options;
|
|
12
12
|
private supportCodeLibrary;
|
|
13
|
-
private
|
|
14
|
-
private runTestRunHooks;
|
|
13
|
+
private worker;
|
|
15
14
|
constructor({ cwd, exit, id, sendMessage, }: {
|
|
16
15
|
cwd: string;
|
|
17
16
|
exit: IExitFunction;
|
|
18
17
|
id: string;
|
|
19
18
|
sendMessage: IMessageSender;
|
|
20
19
|
});
|
|
21
|
-
initialize({ supportCodeCoordinates, supportCodeIds, options, }:
|
|
20
|
+
initialize({ supportCodeCoordinates, supportCodeIds, options, }: InitializeCommand): Promise<void>;
|
|
22
21
|
finalize(): Promise<void>;
|
|
23
|
-
receiveMessage(
|
|
24
|
-
runTestCase(
|
|
22
|
+
receiveMessage(command: CoordinatorToWorkerCommand): Promise<void>;
|
|
23
|
+
runTestCase(command: RunCommand): Promise<void>;
|
|
25
24
|
}
|
|
26
25
|
export {};
|
|
@@ -3,28 +3,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ChildProcessWorker = void 0;
|
|
6
7
|
const node_events_1 = require("node:events");
|
|
7
8
|
const node_url_1 = require("node:url");
|
|
8
9
|
const node_module_1 = require("node:module");
|
|
9
10
|
const messages_1 = require("@cucumber/messages");
|
|
10
11
|
const support_code_library_builder_1 = __importDefault(require("../../support_code_library_builder"));
|
|
11
|
-
const value_checker_1 = require("../../value_checker");
|
|
12
|
-
const run_test_run_hooks_1 = require("../run_test_run_hooks");
|
|
13
|
-
const stopwatch_1 = require("../stopwatch");
|
|
14
|
-
const test_case_runner_1 = __importDefault(require("../test_case_runner"));
|
|
15
12
|
const try_require_1 = __importDefault(require("../../try_require"));
|
|
13
|
+
const worker_1 = require("../worker");
|
|
16
14
|
const { uuid } = messages_1.IdGenerator;
|
|
17
|
-
class
|
|
15
|
+
class ChildProcessWorker {
|
|
18
16
|
cwd;
|
|
19
17
|
exit;
|
|
20
18
|
id;
|
|
21
19
|
eventBroadcaster;
|
|
22
|
-
filterStacktraces;
|
|
23
20
|
newId;
|
|
24
21
|
sendMessage;
|
|
22
|
+
options;
|
|
25
23
|
supportCodeLibrary;
|
|
26
|
-
|
|
27
|
-
runTestRunHooks;
|
|
24
|
+
worker;
|
|
28
25
|
constructor({ cwd, exit, id, sendMessage, }) {
|
|
29
26
|
this.id = id;
|
|
30
27
|
this.newId = uuid();
|
|
@@ -32,9 +29,7 @@ class Worker {
|
|
|
32
29
|
this.exit = exit;
|
|
33
30
|
this.sendMessage = sendMessage;
|
|
34
31
|
this.eventBroadcaster = new node_events_1.EventEmitter();
|
|
35
|
-
this.eventBroadcaster.on('envelope', (envelope) => {
|
|
36
|
-
this.sendMessage({ jsonEnvelope: envelope });
|
|
37
|
-
});
|
|
32
|
+
this.eventBroadcaster.on('envelope', (envelope) => this.sendMessage({ type: 'ENVELOPE', envelope }));
|
|
38
33
|
}
|
|
39
34
|
async initialize({ supportCodeCoordinates, supportCodeIds, options, }) {
|
|
40
35
|
support_code_library_builder_1.default.reset(this.cwd, this.newId, supportCodeCoordinates);
|
|
@@ -47,46 +42,35 @@ class Worker {
|
|
|
47
42
|
await import((0, node_url_1.pathToFileURL)(path).toString());
|
|
48
43
|
}
|
|
49
44
|
this.supportCodeLibrary = support_code_library_builder_1.default.finalize(supportCodeIds);
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.sendMessage({ ready: true });
|
|
45
|
+
this.options = options;
|
|
46
|
+
this.worker = new worker_1.Worker(this.id, this.eventBroadcaster, this.newId, this.options, this.supportCodeLibrary);
|
|
47
|
+
await this.worker.runBeforeAllHooks();
|
|
48
|
+
this.sendMessage({ type: 'READY' });
|
|
55
49
|
}
|
|
56
50
|
async finalize() {
|
|
57
|
-
await this.
|
|
51
|
+
await this.worker.runAfterAllHooks();
|
|
58
52
|
this.exit(0);
|
|
59
53
|
}
|
|
60
|
-
async receiveMessage(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
async receiveMessage(command) {
|
|
55
|
+
switch (command.type) {
|
|
56
|
+
case 'INITIALIZE':
|
|
57
|
+
await this.initialize(command);
|
|
58
|
+
break;
|
|
59
|
+
case 'RUN':
|
|
60
|
+
await this.runTestCase(command);
|
|
61
|
+
break;
|
|
62
|
+
case 'FINALIZE':
|
|
63
|
+
await this.finalize();
|
|
64
|
+
break;
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
|
-
async runTestCase(
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
stopwatch,
|
|
77
|
-
gherkinDocument,
|
|
78
|
-
newId: this.newId,
|
|
79
|
-
pickle,
|
|
80
|
-
testCase,
|
|
81
|
-
retries,
|
|
82
|
-
skip,
|
|
83
|
-
filterStackTraces: this.filterStacktraces,
|
|
84
|
-
supportCodeLibrary: this.supportCodeLibrary,
|
|
85
|
-
worldParameters: this.worldParameters,
|
|
67
|
+
async runTestCase(command) {
|
|
68
|
+
const success = await this.worker.runTestCase(command.assembledTestCase, command.failing);
|
|
69
|
+
this.sendMessage({
|
|
70
|
+
type: 'FINISHED',
|
|
71
|
+
success,
|
|
86
72
|
});
|
|
87
|
-
await testCaseRunner.run();
|
|
88
|
-
this.sendMessage({ ready: true });
|
|
89
73
|
}
|
|
90
74
|
}
|
|
91
|
-
exports.
|
|
75
|
+
exports.ChildProcessWorker = ChildProcessWorker;
|
|
92
76
|
//# sourceMappingURL=worker.js.map
|