mocha 8.1.1 → 8.2.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/CHANGELOG.md +88 -0
- package/README.md +2 -0
- package/browser-entry.js +2 -2
- package/lib/cli/cli.js +19 -8
- package/lib/cli/index.js +0 -6
- package/lib/cli/lookup-files.js +37 -31
- package/lib/cli/node-flags.js +6 -7
- package/lib/cli/options.js +5 -4
- package/lib/cli/run-helpers.js +21 -56
- package/lib/cli/run-option-metadata.js +25 -2
- package/lib/cli/run.js +5 -9
- package/lib/cli/watch-run.js +55 -30
- package/lib/errors.js +142 -20
- package/lib/hook.js +14 -9
- package/lib/mocha.js +266 -66
- package/lib/nodejs/buffered-worker-pool.js +1 -3
- package/lib/nodejs/file-unloader.js +15 -0
- package/lib/nodejs/parallel-buffered-runner.js +156 -18
- package/lib/nodejs/reporters/parallel-buffered.js +61 -29
- package/lib/nodejs/serializer.js +15 -7
- package/lib/nodejs/worker.js +9 -12
- package/lib/plugin-loader.js +286 -0
- package/lib/reporters/json-stream.js +2 -1
- package/lib/reporters/json.js +1 -0
- package/lib/runnable.js +6 -0
- package/lib/runner.js +239 -110
- package/lib/suite.js +34 -15
- package/lib/test.js +6 -2
- package/lib/utils.js +151 -66
- package/mocha.js +7807 -3995
- package/mocha.js.map +1 -1
- package/package.json +68 -56
|
@@ -6,13 +6,31 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
const allSettled = require('promise
|
|
9
|
+
const allSettled = require('@ungap/promise-all-settled').bind(Promise);
|
|
10
10
|
const Runner = require('../runner');
|
|
11
11
|
const {EVENT_RUN_BEGIN, EVENT_RUN_END} = Runner.constants;
|
|
12
12
|
const debug = require('debug')('mocha:parallel:parallel-buffered-runner');
|
|
13
13
|
const {BufferedWorkerPool} = require('./buffered-worker-pool');
|
|
14
14
|
const {setInterval, clearInterval} = global;
|
|
15
|
-
const {createMap} = require('../utils');
|
|
15
|
+
const {createMap, constants} = require('../utils');
|
|
16
|
+
const {MOCHA_ID_PROP_NAME} = constants;
|
|
17
|
+
const {createFatalError} = require('../errors');
|
|
18
|
+
|
|
19
|
+
const DEFAULT_WORKER_REPORTER = require.resolve(
|
|
20
|
+
'./reporters/parallel-buffered'
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* List of options to _not_ serialize for transmission to workers
|
|
25
|
+
*/
|
|
26
|
+
const DENY_OPTIONS = [
|
|
27
|
+
'globalSetup',
|
|
28
|
+
'globalTeardown',
|
|
29
|
+
'parallel',
|
|
30
|
+
'p',
|
|
31
|
+
'jobs',
|
|
32
|
+
'j'
|
|
33
|
+
];
|
|
16
34
|
|
|
17
35
|
/**
|
|
18
36
|
* Outputs a debug statement with worker stats
|
|
@@ -56,7 +74,7 @@ const states = createMap({
|
|
|
56
74
|
/**
|
|
57
75
|
* This `Runner` delegates tests runs to worker threads. Does not execute any
|
|
58
76
|
* {@link Runnable}s by itself!
|
|
59
|
-
* @
|
|
77
|
+
* @public
|
|
60
78
|
*/
|
|
61
79
|
class ParallelBufferedRunner extends Runner {
|
|
62
80
|
constructor(...args) {
|
|
@@ -76,6 +94,10 @@ class ParallelBufferedRunner extends Runner {
|
|
|
76
94
|
}
|
|
77
95
|
});
|
|
78
96
|
|
|
97
|
+
this._workerReporter = DEFAULT_WORKER_REPORTER;
|
|
98
|
+
this._linkPartialObjects = false;
|
|
99
|
+
this._linkedObjectMap = new Map();
|
|
100
|
+
|
|
79
101
|
this.once(Runner.constants.EVENT_RUN_END, () => {
|
|
80
102
|
this._state = COMPLETE;
|
|
81
103
|
});
|
|
@@ -86,12 +108,68 @@ class ParallelBufferedRunner extends Runner {
|
|
|
86
108
|
* @param {BufferedWorkerPool} pool - Worker pool
|
|
87
109
|
* @param {Options} options - Mocha options
|
|
88
110
|
* @returns {FileRunner} Mapping function
|
|
111
|
+
* @private
|
|
89
112
|
*/
|
|
90
113
|
_createFileRunner(pool, options) {
|
|
114
|
+
/**
|
|
115
|
+
* Emits event and sets `BAILING` state, if necessary.
|
|
116
|
+
* @param {Object} event - Event having `eventName`, maybe `data` and maybe `error`
|
|
117
|
+
* @param {number} failureCount - Failure count
|
|
118
|
+
*/
|
|
119
|
+
const emitEvent = (event, failureCount) => {
|
|
120
|
+
this.emit(event.eventName, event.data, event.error);
|
|
121
|
+
if (
|
|
122
|
+
this._state !== BAILING &&
|
|
123
|
+
event.data &&
|
|
124
|
+
event.data._bail &&
|
|
125
|
+
(failureCount || event.error)
|
|
126
|
+
) {
|
|
127
|
+
debug('run(): nonzero failure count & found bail flag');
|
|
128
|
+
// we need to let the events complete for this file, as the worker
|
|
129
|
+
// should run any cleanup hooks
|
|
130
|
+
this._state = BAILING;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Given an event, recursively find any objects in its data that have ID's, and create object references to already-seen objects.
|
|
136
|
+
* @param {Object} event - Event having `eventName`, maybe `data` and maybe `error`
|
|
137
|
+
*/
|
|
138
|
+
const linkEvent = event => {
|
|
139
|
+
const stack = [{parent: event, prop: 'data'}];
|
|
140
|
+
while (stack.length) {
|
|
141
|
+
const {parent, prop} = stack.pop();
|
|
142
|
+
const obj = parent[prop];
|
|
143
|
+
let newObj;
|
|
144
|
+
if (obj && typeof obj === 'object') {
|
|
145
|
+
if (obj[MOCHA_ID_PROP_NAME]) {
|
|
146
|
+
const id = obj[MOCHA_ID_PROP_NAME];
|
|
147
|
+
newObj = this._linkedObjectMap.has(id)
|
|
148
|
+
? Object.assign(this._linkedObjectMap.get(id), obj)
|
|
149
|
+
: obj;
|
|
150
|
+
this._linkedObjectMap.set(id, newObj);
|
|
151
|
+
parent[prop] = newObj;
|
|
152
|
+
} else {
|
|
153
|
+
throw createFatalError(
|
|
154
|
+
'Object missing ID received in event data',
|
|
155
|
+
obj
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
Object.keys(newObj).forEach(key => {
|
|
160
|
+
const value = obj[key];
|
|
161
|
+
if (value && typeof value === 'object' && value[MOCHA_ID_PROP_NAME]) {
|
|
162
|
+
stack.push({obj: value, parent: newObj, prop: key});
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
91
168
|
return async file => {
|
|
92
169
|
debug('run(): enqueueing test file %s', file);
|
|
93
170
|
try {
|
|
94
171
|
const {failureCount, events} = await pool.run(file, options);
|
|
172
|
+
|
|
95
173
|
if (this._state === BAILED) {
|
|
96
174
|
// short-circuit after a graceful bail. if this happens,
|
|
97
175
|
// some other worker has bailed.
|
|
@@ -107,20 +185,18 @@ class ParallelBufferedRunner extends Runner {
|
|
|
107
185
|
);
|
|
108
186
|
this.failures += failureCount; // can this ever be non-numeric?
|
|
109
187
|
let event = events.shift();
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
event
|
|
115
|
-
event.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
this._state = BAILING;
|
|
188
|
+
|
|
189
|
+
if (this._linkPartialObjects) {
|
|
190
|
+
while (event) {
|
|
191
|
+
linkEvent(event);
|
|
192
|
+
emitEvent(event, failureCount);
|
|
193
|
+
event = events.shift();
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
while (event) {
|
|
197
|
+
emitEvent(event, failureCount);
|
|
198
|
+
event = events.shift();
|
|
122
199
|
}
|
|
123
|
-
event = events.shift();
|
|
124
200
|
}
|
|
125
201
|
if (this._state === BAILING) {
|
|
126
202
|
debug('run(): terminating pool due to "bail" flag');
|
|
@@ -154,6 +230,7 @@ class ParallelBufferedRunner extends Runner {
|
|
|
154
230
|
* Returns the listener for later call to `process.removeListener()`.
|
|
155
231
|
* @param {BufferedWorkerPool} pool - Worker pool
|
|
156
232
|
* @returns {SigIntListener} Listener
|
|
233
|
+
* @private
|
|
157
234
|
*/
|
|
158
235
|
_bindSigIntListener(pool) {
|
|
159
236
|
const sigIntListener = async () => {
|
|
@@ -197,15 +274,19 @@ class ParallelBufferedRunner extends Runner {
|
|
|
197
274
|
* @param {{files: string[], options: Options}} opts - Files to run and
|
|
198
275
|
* command-line options, respectively.
|
|
199
276
|
*/
|
|
200
|
-
run(callback, {files, options} = {}) {
|
|
277
|
+
run(callback, {files, options = {}} = {}) {
|
|
201
278
|
/**
|
|
202
279
|
* Listener on `Process.SIGINT` which tries to cleanly terminate the worker pool.
|
|
203
280
|
*/
|
|
204
281
|
let sigIntListener;
|
|
282
|
+
|
|
283
|
+
// assign the reporter the worker will use, which will be different than the
|
|
284
|
+
// main process' reporter
|
|
285
|
+
options = {...options, reporter: this._workerReporter};
|
|
286
|
+
|
|
205
287
|
// This function should _not_ return a `Promise`; its parent (`Runner#run`)
|
|
206
288
|
// returns this instance, so this should do the same. However, we want to make
|
|
207
289
|
// use of `async`/`await`, so we use this IIFE.
|
|
208
|
-
|
|
209
290
|
(async () => {
|
|
210
291
|
/**
|
|
211
292
|
* This is an interval that outputs stats about the worker pool every so often
|
|
@@ -235,6 +316,11 @@ class ParallelBufferedRunner extends Runner {
|
|
|
235
316
|
|
|
236
317
|
this.emit(EVENT_RUN_BEGIN);
|
|
237
318
|
|
|
319
|
+
options = {...options};
|
|
320
|
+
DENY_OPTIONS.forEach(opt => {
|
|
321
|
+
delete options[opt];
|
|
322
|
+
});
|
|
323
|
+
|
|
238
324
|
const results = await allSettled(
|
|
239
325
|
files.map(this._createFileRunner(pool, options))
|
|
240
326
|
);
|
|
@@ -257,6 +343,7 @@ class ParallelBufferedRunner extends Runner {
|
|
|
257
343
|
if (this._state === ABORTING) {
|
|
258
344
|
return;
|
|
259
345
|
}
|
|
346
|
+
|
|
260
347
|
this.emit(EVENT_RUN_END);
|
|
261
348
|
debug('run(): completing with failure count %d', this.failures);
|
|
262
349
|
callback(this.failures);
|
|
@@ -275,6 +362,57 @@ class ParallelBufferedRunner extends Runner {
|
|
|
275
362
|
})();
|
|
276
363
|
return this;
|
|
277
364
|
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Toggle partial object linking behavior; used for building object references from
|
|
368
|
+
* unique ID's.
|
|
369
|
+
* @param {boolean} [value] - If `true`, enable partial object linking, otherwise disable
|
|
370
|
+
* @returns {Runner}
|
|
371
|
+
* @chainable
|
|
372
|
+
* @public
|
|
373
|
+
* @example
|
|
374
|
+
* // this reporter needs proper object references when run in parallel mode
|
|
375
|
+
* class MyReporter() {
|
|
376
|
+
* constructor(runner) {
|
|
377
|
+
* this.runner.linkPartialObjects(true)
|
|
378
|
+
* .on(EVENT_SUITE_BEGIN, suite => {
|
|
379
|
+
// this Suite may be the same object...
|
|
380
|
+
* })
|
|
381
|
+
* .on(EVENT_TEST_BEGIN, test => {
|
|
382
|
+
* // ...as the `test.parent` property
|
|
383
|
+
* });
|
|
384
|
+
* }
|
|
385
|
+
* }
|
|
386
|
+
*/
|
|
387
|
+
linkPartialObjects(value) {
|
|
388
|
+
this._linkPartialObjects = Boolean(value);
|
|
389
|
+
return super.linkPartialObjects(value);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* If this class is the `Runner` in use, then this is going to return `true`.
|
|
394
|
+
*
|
|
395
|
+
* For use by reporters.
|
|
396
|
+
* @returns {true}
|
|
397
|
+
* @public
|
|
398
|
+
*/
|
|
399
|
+
isParallelMode() {
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Configures an alternate reporter for worker processes to use. Subclasses
|
|
405
|
+
* using worker processes should implement this.
|
|
406
|
+
* @public
|
|
407
|
+
* @param {string} path - Absolute path to alternate reporter for worker processes to use
|
|
408
|
+
* @returns {Runner}
|
|
409
|
+
* @throws When in serial mode
|
|
410
|
+
* @chainable
|
|
411
|
+
*/
|
|
412
|
+
workerReporter(reporter) {
|
|
413
|
+
this._workerReporter = reporter;
|
|
414
|
+
return this;
|
|
415
|
+
}
|
|
278
416
|
}
|
|
279
417
|
|
|
280
418
|
module.exports = ParallelBufferedRunner;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* "Buffered" reporter used internally by a worker process when running in parallel mode.
|
|
3
|
-
* @module reporters/parallel-buffered
|
|
4
|
-
* @
|
|
3
|
+
* @module nodejs/reporters/parallel-buffered
|
|
4
|
+
* @public
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
@@ -53,15 +53,16 @@ const EVENT_NAMES = [
|
|
|
53
53
|
const ONCE_EVENT_NAMES = [EVENT_DELAY_BEGIN, EVENT_DELAY_END];
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* The `ParallelBuffered` reporter is
|
|
57
|
-
* to `STDOUT`, etc., it retains a
|
|
58
|
-
*
|
|
59
|
-
* return the data to the main
|
|
60
|
-
*
|
|
56
|
+
* The `ParallelBuffered` reporter is used by each worker process in "parallel"
|
|
57
|
+
* mode, by default. Instead of reporting to to `STDOUT`, etc., it retains a
|
|
58
|
+
* list of events it receives and hands these off to the callback passed into
|
|
59
|
+
* {@link Mocha#run}. That callback will then return the data to the main
|
|
60
|
+
* process.
|
|
61
|
+
* @public
|
|
61
62
|
*/
|
|
62
63
|
class ParallelBuffered extends Base {
|
|
63
64
|
/**
|
|
64
|
-
*
|
|
65
|
+
* Calls {@link ParallelBuffered#createListeners}
|
|
65
66
|
* @param {Runner} runner
|
|
66
67
|
*/
|
|
67
68
|
constructor(runner, opts) {
|
|
@@ -70,50 +71,81 @@ class ParallelBuffered extends Base {
|
|
|
70
71
|
/**
|
|
71
72
|
* Retained list of events emitted from the {@link Runner} instance.
|
|
72
73
|
* @type {BufferedEvent[]}
|
|
73
|
-
* @
|
|
74
|
+
* @public
|
|
74
75
|
*/
|
|
75
|
-
|
|
76
|
+
this.events = [];
|
|
76
77
|
|
|
77
78
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
79
|
+
* Map of `Runner` event names to listeners (for later teardown)
|
|
80
|
+
* @public
|
|
81
|
+
* @type {Map<string,EventListener>}
|
|
80
82
|
*/
|
|
81
|
-
|
|
83
|
+
this.listeners = new Map();
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
85
|
+
this.createListeners(runner);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Returns a new listener which saves event data in memory to
|
|
90
|
+
* {@link ParallelBuffered#events}. Listeners are indexed by `eventName` and stored
|
|
91
|
+
* in {@link ParallelBuffered#listeners}. This is a defensive measure, so that we
|
|
92
|
+
* don't a) leak memory or b) remove _other_ listeners that may not be
|
|
93
|
+
* associated with this reporter.
|
|
94
|
+
*
|
|
95
|
+
* Subclasses could override this behavior.
|
|
96
|
+
*
|
|
97
|
+
* @public
|
|
98
|
+
* @param {string} eventName - Name of event to create listener for
|
|
99
|
+
* @returns {EventListener}
|
|
100
|
+
*/
|
|
101
|
+
createListener(eventName) {
|
|
102
|
+
const listener = (runnable, err) => {
|
|
103
|
+
this.events.push(SerializableEvent.create(eventName, runnable, err));
|
|
104
|
+
};
|
|
105
|
+
return this.listeners.set(eventName, listener).get(eventName);
|
|
106
|
+
}
|
|
95
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Creates event listeners (using {@link ParallelBuffered#createListener}) for each
|
|
110
|
+
* reporter-relevant event emitted by a {@link Runner}. This array is drained when
|
|
111
|
+
* {@link ParallelBuffered#done} is called by {@link Runner#run}.
|
|
112
|
+
*
|
|
113
|
+
* Subclasses could override this behavior.
|
|
114
|
+
* @public
|
|
115
|
+
* @param {Runner} runner - Runner instance
|
|
116
|
+
* @returns {ParallelBuffered}
|
|
117
|
+
* @chainable
|
|
118
|
+
*/
|
|
119
|
+
createListeners(runner) {
|
|
96
120
|
EVENT_NAMES.forEach(evt => {
|
|
97
|
-
runner.on(evt, createListener(evt));
|
|
121
|
+
runner.on(evt, this.createListener(evt));
|
|
98
122
|
});
|
|
99
123
|
ONCE_EVENT_NAMES.forEach(evt => {
|
|
100
|
-
runner.once(evt, createListener(evt));
|
|
124
|
+
runner.once(evt, this.createListener(evt));
|
|
101
125
|
});
|
|
102
126
|
|
|
103
127
|
runner.once(EVENT_RUN_END, () => {
|
|
104
128
|
debug('received EVENT_RUN_END');
|
|
105
|
-
listeners.forEach((listener, evt) => {
|
|
129
|
+
this.listeners.forEach((listener, evt) => {
|
|
106
130
|
runner.removeListener(evt, listener);
|
|
107
|
-
listeners.delete(evt);
|
|
131
|
+
this.listeners.delete(evt);
|
|
108
132
|
});
|
|
109
133
|
});
|
|
134
|
+
|
|
135
|
+
return this;
|
|
110
136
|
}
|
|
111
137
|
|
|
112
138
|
/**
|
|
113
139
|
* Calls the {@link Mocha#run} callback (`callback`) with the test failure
|
|
114
140
|
* count and the array of {@link BufferedEvent} objects. Resets the array.
|
|
141
|
+
*
|
|
142
|
+
* This is called directly by `Runner#run` and should not be called by any other consumer.
|
|
143
|
+
*
|
|
144
|
+
* Subclasses could override this.
|
|
145
|
+
*
|
|
115
146
|
* @param {number} failures - Number of failed tests
|
|
116
147
|
* @param {Function} callback - The callback passed to {@link Mocha#run}.
|
|
148
|
+
* @public
|
|
117
149
|
*/
|
|
118
150
|
done(failures, callback) {
|
|
119
151
|
callback(SerializableWorkerResult.create(this.events, failures));
|
package/lib/nodejs/serializer.js
CHANGED
|
@@ -56,7 +56,7 @@ class SerializableWorkerResult {
|
|
|
56
56
|
/**
|
|
57
57
|
* Instantiates a new {@link SerializableWorkerResult}.
|
|
58
58
|
* @param {...any} args - Args to constructor
|
|
59
|
-
* @returns {
|
|
59
|
+
* @returns {SerializableWorkerResult}
|
|
60
60
|
*/
|
|
61
61
|
static create(...args) {
|
|
62
62
|
return new SerializableWorkerResult(...args);
|
|
@@ -131,7 +131,11 @@ class SerializableEvent {
|
|
|
131
131
|
*/
|
|
132
132
|
constructor(eventName, originalValue, originalError) {
|
|
133
133
|
if (!eventName) {
|
|
134
|
-
throw
|
|
134
|
+
throw createInvalidArgumentTypeError(
|
|
135
|
+
'Empty `eventName` string argument',
|
|
136
|
+
'eventName',
|
|
137
|
+
'string'
|
|
138
|
+
);
|
|
135
139
|
}
|
|
136
140
|
/**
|
|
137
141
|
* The event name.
|
|
@@ -140,8 +144,10 @@ class SerializableEvent {
|
|
|
140
144
|
this.eventName = eventName;
|
|
141
145
|
const originalValueType = type(originalValue);
|
|
142
146
|
if (originalValueType !== 'object' && originalValueType !== 'undefined') {
|
|
143
|
-
throw
|
|
144
|
-
`
|
|
147
|
+
throw createInvalidArgumentTypeError(
|
|
148
|
+
`Expected object but received ${originalValueType}`,
|
|
149
|
+
'originalValue',
|
|
150
|
+
'object'
|
|
145
151
|
);
|
|
146
152
|
}
|
|
147
153
|
/**
|
|
@@ -190,7 +196,8 @@ class SerializableEvent {
|
|
|
190
196
|
parent[key] = Object.create(null);
|
|
191
197
|
return;
|
|
192
198
|
}
|
|
193
|
-
|
|
199
|
+
let _type = type(value);
|
|
200
|
+
if (_type === 'error') {
|
|
194
201
|
// we need to reference the stack prop b/c it's lazily-loaded.
|
|
195
202
|
// `__type` is necessary for deserialization to create an `Error` later.
|
|
196
203
|
// `message` is apparently not enumerable, so we must handle it specifically.
|
|
@@ -200,10 +207,11 @@ class SerializableEvent {
|
|
|
200
207
|
__type: 'Error'
|
|
201
208
|
});
|
|
202
209
|
parent[key] = value;
|
|
203
|
-
// after this, the result of type(value)
|
|
210
|
+
// after this, set the result of type(value) to be `object`, and we'll throw
|
|
204
211
|
// whatever other junk is in the original error into the new `value`.
|
|
212
|
+
_type = 'object';
|
|
205
213
|
}
|
|
206
|
-
switch (
|
|
214
|
+
switch (_type) {
|
|
207
215
|
case 'object':
|
|
208
216
|
if (type(value.serialize) === 'function') {
|
|
209
217
|
parent[key] = value.serialize();
|
package/lib/nodejs/worker.js
CHANGED
|
@@ -12,19 +12,13 @@ const {
|
|
|
12
12
|
} = require('../errors');
|
|
13
13
|
const workerpool = require('workerpool');
|
|
14
14
|
const Mocha = require('../mocha');
|
|
15
|
-
const {
|
|
16
|
-
handleRequires,
|
|
17
|
-
validatePlugin,
|
|
18
|
-
loadRootHooks
|
|
19
|
-
} = require('../cli/run-helpers');
|
|
15
|
+
const {handleRequires, validateLegacyPlugin} = require('../cli/run-helpers');
|
|
20
16
|
const d = require('debug');
|
|
21
17
|
const debug = d.debug(`mocha:parallel:worker:${process.pid}`);
|
|
22
18
|
const isDebugEnabled = d.enabled(`mocha:parallel:worker:${process.pid}`);
|
|
23
19
|
const {serialize} = require('./serializer');
|
|
24
20
|
const {setInterval, clearInterval} = global;
|
|
25
21
|
|
|
26
|
-
const BUFFERED_REPORTER_PATH = require.resolve('./reporters/parallel-buffered');
|
|
27
|
-
|
|
28
22
|
let rootHooks;
|
|
29
23
|
|
|
30
24
|
if (workerpool.isMainThread) {
|
|
@@ -45,9 +39,13 @@ if (workerpool.isMainThread) {
|
|
|
45
39
|
* @param {Options} argv - Command-line options
|
|
46
40
|
*/
|
|
47
41
|
let bootstrap = async argv => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
// globalSetup and globalTeardown do not run in workers
|
|
43
|
+
const plugins = await handleRequires(argv.require, {
|
|
44
|
+
ignoredPlugins: ['mochaGlobalSetup', 'mochaGlobalTeardown']
|
|
45
|
+
});
|
|
46
|
+
validateLegacyPlugin(argv, 'ui', Mocha.interfaces);
|
|
47
|
+
|
|
48
|
+
rootHooks = plugins.rootHooks;
|
|
51
49
|
bootstrap = () => {};
|
|
52
50
|
debug('bootstrap(): finished with args: %O', argv);
|
|
53
51
|
};
|
|
@@ -91,8 +89,6 @@ async function run(filepath, serializedOptions = '{}') {
|
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
const opts = Object.assign({ui: 'bdd'}, argv, {
|
|
94
|
-
// workers only use the `Buffered` reporter.
|
|
95
|
-
reporter: BUFFERED_REPORTER_PATH,
|
|
96
92
|
// if this was true, it would cause infinite recursion.
|
|
97
93
|
parallel: false,
|
|
98
94
|
// this doesn't work in parallel mode
|
|
@@ -125,6 +121,7 @@ async function run(filepath, serializedOptions = '{}') {
|
|
|
125
121
|
mocha.run(result => {
|
|
126
122
|
// Runner adds these; if we don't remove them, we'll get a leak.
|
|
127
123
|
process.removeAllListeners('uncaughtException');
|
|
124
|
+
process.removeAllListeners('unhandledRejection');
|
|
128
125
|
|
|
129
126
|
try {
|
|
130
127
|
const serialized = serialize(result);
|