ava 5.0.1 → 5.1.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/entrypoints/eslint-plugin-helper.cjs +4 -4
- package/lib/assert.js +6 -3
- package/lib/cli.js +2 -2
- package/lib/eslint-plugin-helper-worker.js +2 -2
- package/lib/fork.js +8 -3
- package/lib/glob-helpers.cjs +2 -2
- package/lib/load-config.js +13 -7
- package/lib/module-types.js +22 -8
- package/lib/now-and-timers.cjs +1 -1
- package/lib/plugin-support/shared-worker-loader.js +6 -7
- package/lib/plugin-support/shared-workers.js +34 -24
- package/lib/reporters/default.js +3 -0
- package/lib/reporters/tap.js +50 -17
- package/lib/run-status.js +61 -15
- package/lib/runner.js +6 -0
- package/lib/watcher.js +5 -2
- package/lib/worker/base.js +9 -3
- package/lib/worker/channel.cjs +5 -5
- package/lib/worker/guard-environment.cjs +2 -2
- package/lib/worker/main.cjs +1 -1
- package/lib/worker/utils.cjs +2 -2
- package/package.json +20 -21
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const url = require('url');
|
|
4
|
-
const v8 = require('v8');
|
|
5
|
-
const {Worker} = require('worker_threads');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const url = require('node:url');
|
|
4
|
+
const v8 = require('node:v8');
|
|
5
|
+
const {Worker} = require('node:worker_threads');
|
|
6
6
|
|
|
7
7
|
const {
|
|
8
8
|
classify,
|
package/lib/assert.js
CHANGED
|
@@ -50,7 +50,7 @@ export class AssertionError extends Error {
|
|
|
50
50
|
// use the values for custom diff views
|
|
51
51
|
this.raw = options.raw;
|
|
52
52
|
|
|
53
|
-
this.savedError = options.savedError
|
|
53
|
+
this.savedError = options.savedError || getErrorWithLongStackTrace();
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -143,14 +143,17 @@ function validateExpectations(assertion, expectations, numberArgs) { // eslint-d
|
|
|
143
143
|
case 'is':
|
|
144
144
|
case 'message':
|
|
145
145
|
case 'name':
|
|
146
|
-
case 'code':
|
|
146
|
+
case 'code': {
|
|
147
147
|
continue;
|
|
148
|
-
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
default: {
|
|
149
151
|
throw new AssertionError({
|
|
150
152
|
assertion,
|
|
151
153
|
message: `The second argument to \`t.${assertion}()\` contains unexpected properties`,
|
|
152
154
|
values: [formatWithLabel('Called with:', expectations)],
|
|
153
155
|
});
|
|
156
|
+
}
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
}
|
package/lib/cli.js
CHANGED
|
@@ -250,8 +250,8 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
250
250
|
setChalk(chalkOptions);
|
|
251
251
|
|
|
252
252
|
if (confError) {
|
|
253
|
-
if (confError.
|
|
254
|
-
exit(`${confError.message}\n\n${chalk.gray(
|
|
253
|
+
if (confError.cause) {
|
|
254
|
+
exit(`${confError.message}\n\n${chalk.gray(confError.cause?.stack ?? confError.cause)}`);
|
|
255
255
|
} else {
|
|
256
256
|
exit(confError.message);
|
|
257
257
|
}
|
|
@@ -33,7 +33,7 @@ const buildGlobs = ({conf, providers, projectDir, overrideExtensions, overrideFi
|
|
|
33
33
|
cwd: projectDir,
|
|
34
34
|
...normalizeGlobs({
|
|
35
35
|
extensions,
|
|
36
|
-
files: overrideFiles
|
|
36
|
+
files: overrideFiles || conf.files,
|
|
37
37
|
providers,
|
|
38
38
|
}),
|
|
39
39
|
};
|
|
@@ -69,5 +69,5 @@ const handleMessage = async ({projectDir, overrideExtensions, overrideFiles}) =>
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
parentPort.on('message', handleMessage);
|
|
72
|
-
handleMessage(workerData.firstMessage);
|
|
72
|
+
handleMessage(workerData.firstMessage); // eslint-disable-line unicorn/prefer-top-level-await
|
|
73
73
|
delete workerData.firstMessage;
|
package/lib/fork.js
CHANGED
|
@@ -109,9 +109,11 @@ export default function loadFork(file, options, execArgv = process.execArgv) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
switch (message.ava.type) {
|
|
112
|
-
case 'ready-for-options':
|
|
112
|
+
case 'ready-for-options': {
|
|
113
113
|
send({type: 'options', options});
|
|
114
114
|
break;
|
|
115
|
+
}
|
|
116
|
+
|
|
115
117
|
case 'shared-worker-connect': {
|
|
116
118
|
const {channelId, filename, initialData, port} = message.ava;
|
|
117
119
|
emitter.emit('connectSharedWorker', {
|
|
@@ -125,11 +127,14 @@ export default function loadFork(file, options, execArgv = process.execArgv) {
|
|
|
125
127
|
break;
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
case 'ping':
|
|
130
|
+
case 'ping': {
|
|
129
131
|
send({type: 'pong'});
|
|
130
132
|
break;
|
|
131
|
-
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
default: {
|
|
132
136
|
emitStateChange(message.ava);
|
|
137
|
+
}
|
|
133
138
|
}
|
|
134
139
|
});
|
|
135
140
|
|
package/lib/glob-helpers.cjs
CHANGED
package/lib/load-config.js
CHANGED
|
@@ -29,17 +29,13 @@ const loadConfigFile = async ({projectDir, configFile}) => {
|
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {
|
|
32
|
+
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {cause: error});
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
function resolveConfigFile(configFile) {
|
|
37
37
|
if (configFile) {
|
|
38
38
|
configFile = path.resolve(configFile); // Relative to CWD
|
|
39
|
-
|
|
40
|
-
if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) {
|
|
41
|
-
throw new Error('Config files must have .js, .cjs or .mjs extensions');
|
|
42
|
-
}
|
|
43
39
|
}
|
|
44
40
|
|
|
45
41
|
return configFile;
|
|
@@ -78,7 +74,7 @@ async function checkJsonFile(searchDir) {
|
|
|
78
74
|
}
|
|
79
75
|
}
|
|
80
76
|
|
|
81
|
-
export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) {
|
|
77
|
+
export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { // eslint-disable-line complexity
|
|
82
78
|
let packageConf = await packageConfig('ava', {cwd: resolveFrom});
|
|
83
79
|
const filepath = packageJsonPath(packageConf);
|
|
84
80
|
const projectDir = filepath === undefined ? resolveFrom : path.dirname(filepath);
|
|
@@ -94,7 +90,17 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
|
|
|
94
90
|
let fileForErrorMessage;
|
|
95
91
|
let conflicting = [];
|
|
96
92
|
if (configFile) {
|
|
97
|
-
|
|
93
|
+
let loaded;
|
|
94
|
+
try {
|
|
95
|
+
loaded = await loadConfigFile({projectDir, configFile});
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) {
|
|
98
|
+
throw Object.assign(new Error('Could not load config file; it should have .js, .cjs or .mjs extension'), {cause: error});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
|
|
98
104
|
if (loaded !== null) {
|
|
99
105
|
({config: fileConf, fileForErrorMessage} = loaded);
|
|
100
106
|
}
|
package/lib/module-types.js
CHANGED
|
@@ -6,21 +6,28 @@ const requireTrueValue = value => {
|
|
|
6
6
|
|
|
7
7
|
const normalize = (extension, type, defaultModuleType) => {
|
|
8
8
|
switch (extension) {
|
|
9
|
-
case 'cjs':
|
|
9
|
+
case 'cjs': {
|
|
10
10
|
requireTrueValue(type);
|
|
11
11
|
return 'commonjs';
|
|
12
|
-
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
case 'mjs': {
|
|
13
15
|
requireTrueValue(type);
|
|
14
16
|
return 'module';
|
|
15
|
-
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
case 'js': {
|
|
16
20
|
requireTrueValue(type);
|
|
17
21
|
return defaultModuleType;
|
|
18
|
-
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
default: {
|
|
19
25
|
if (type !== 'commonjs' && type !== 'module') {
|
|
20
26
|
throw new TypeError(`Module type for ’${extension}’ must be ’commonjs’ or ’module’`);
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
return type;
|
|
30
|
+
}
|
|
24
31
|
}
|
|
25
32
|
};
|
|
26
33
|
|
|
@@ -37,17 +44,24 @@ const deriveFromArray = (extensions, defaultModuleType) => {
|
|
|
37
44
|
const moduleTypes = {};
|
|
38
45
|
for (const extension of extensions) {
|
|
39
46
|
switch (extension) {
|
|
40
|
-
case 'cjs':
|
|
47
|
+
case 'cjs': {
|
|
41
48
|
moduleTypes.cjs = 'commonjs';
|
|
42
49
|
break;
|
|
43
|
-
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
case 'mjs': {
|
|
44
53
|
moduleTypes.mjs = 'module';
|
|
45
54
|
break;
|
|
46
|
-
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
case 'js': {
|
|
47
58
|
moduleTypes.js = defaultModuleType;
|
|
48
59
|
break;
|
|
49
|
-
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
default: {
|
|
50
63
|
moduleTypes[extension] = 'commonjs';
|
|
64
|
+
}
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
67
|
|
package/lib/now-and-timers.cjs
CHANGED
|
@@ -166,7 +166,8 @@ let signalAvailable = () => {
|
|
|
166
166
|
};
|
|
167
167
|
|
|
168
168
|
let fatal;
|
|
169
|
-
|
|
169
|
+
try {
|
|
170
|
+
const factory = await loadFactory(workerData.filename);
|
|
170
171
|
if (typeof factory !== 'function') {
|
|
171
172
|
throw new TypeError(`Missing default factory function export for shared worker plugin at ${workerData.filename}`);
|
|
172
173
|
}
|
|
@@ -236,14 +237,12 @@ loadFactory(workerData.filename).then(factory => {
|
|
|
236
237
|
};
|
|
237
238
|
},
|
|
238
239
|
});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
}).finally(() => {
|
|
240
|
+
} catch (error) {
|
|
241
|
+
fatal = fatal ?? error;
|
|
242
|
+
} finally {
|
|
244
243
|
if (fatal !== undefined) {
|
|
245
244
|
process.nextTick(() => {
|
|
246
245
|
throw fatal;
|
|
247
246
|
});
|
|
248
247
|
}
|
|
249
|
-
}
|
|
248
|
+
}
|
|
@@ -49,35 +49,54 @@ function launchWorker(filename, initialData) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export async function observeWorkerProcess(fork, runStatus) {
|
|
52
|
-
let
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
52
|
+
let signalDone;
|
|
53
|
+
|
|
54
|
+
const done = new Promise(resolve => {
|
|
55
|
+
signalDone = () => {
|
|
56
|
+
resolve();
|
|
57
|
+
};
|
|
56
58
|
});
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
const activeInstances = new Set();
|
|
61
|
+
|
|
62
|
+
const removeInstance = instance => {
|
|
63
|
+
instance.worker.unref();
|
|
64
|
+
activeInstances.delete(instance);
|
|
65
|
+
|
|
66
|
+
if (activeInstances.size === 0) {
|
|
67
|
+
signalDone();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const removeAllInstances = () => {
|
|
72
|
+
if (activeInstances.size === 0) {
|
|
73
|
+
signalDone();
|
|
74
|
+
return;
|
|
61
75
|
}
|
|
76
|
+
|
|
77
|
+
for (const instance of activeInstances) {
|
|
78
|
+
removeInstance(instance);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
fork.promise.finally(() => {
|
|
83
|
+
removeAllInstances();
|
|
62
84
|
});
|
|
63
85
|
|
|
64
86
|
fork.onConnectSharedWorker(async ({filename, initialData, port, signalError}) => {
|
|
65
87
|
const launched = launchWorker(filename, initialData);
|
|
88
|
+
activeInstances.add(launched);
|
|
66
89
|
|
|
67
90
|
const handleWorkerMessage = async message => {
|
|
68
91
|
if (message.type === 'deregistered-test-worker' && message.id === fork.threadId) {
|
|
69
92
|
launched.worker.off('message', handleWorkerMessage);
|
|
70
|
-
|
|
71
|
-
registrationCount--;
|
|
72
|
-
if (registrationCount === 0) {
|
|
73
|
-
signalDeregistered();
|
|
74
|
-
}
|
|
93
|
+
removeInstance(launched);
|
|
75
94
|
}
|
|
76
95
|
};
|
|
77
96
|
|
|
78
97
|
launched.statePromises.error.then(error => {
|
|
79
|
-
signalDeregistered();
|
|
80
98
|
launched.worker.off('message', handleWorkerMessage);
|
|
99
|
+
removeAllInstances();
|
|
81
100
|
runStatus.emitStateChange({type: 'shared-worker-error', err: serializeError('Shared worker error', true, error)});
|
|
82
101
|
signalError();
|
|
83
102
|
});
|
|
@@ -85,8 +104,6 @@ export async function observeWorkerProcess(fork, runStatus) {
|
|
|
85
104
|
try {
|
|
86
105
|
await launched.statePromises.available;
|
|
87
106
|
|
|
88
|
-
registrationCount++;
|
|
89
|
-
|
|
90
107
|
port.postMessage({type: 'ready'});
|
|
91
108
|
|
|
92
109
|
launched.worker.postMessage({
|
|
@@ -104,15 +121,8 @@ export async function observeWorkerProcess(fork, runStatus) {
|
|
|
104
121
|
});
|
|
105
122
|
|
|
106
123
|
launched.worker.on('message', handleWorkerMessage);
|
|
107
|
-
} catch {
|
|
108
|
-
return;
|
|
109
|
-
} finally {
|
|
110
|
-
// Attaching listeners has the side-effect of referencing the worker.
|
|
111
|
-
// Explicitly unreference it now so it does not prevent the main process
|
|
112
|
-
// from exiting.
|
|
113
|
-
launched.worker.unref();
|
|
114
|
-
}
|
|
124
|
+
} catch {}
|
|
115
125
|
});
|
|
116
126
|
|
|
117
|
-
return
|
|
127
|
+
return done;
|
|
118
128
|
}
|
package/lib/reporters/default.js
CHANGED
|
@@ -370,8 +370,11 @@ export default class Reporter {
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
this.lineWriter.writeLine(`${testsInFile.size} tests were pending in ${this.relativeFile(file)}\n`);
|
|
373
|
+
const testTitleToLogs = evt.pendingTestsLogs.get(file);
|
|
373
374
|
for (const title of testsInFile) {
|
|
375
|
+
const logs = testTitleToLogs?.get(title);
|
|
374
376
|
this.lineWriter.writeLine(`${figures.circleDotted} ${this.prefixTitle(file, title)}`);
|
|
377
|
+
this.writeLogs({logs});
|
|
375
378
|
}
|
|
376
379
|
|
|
377
380
|
this.lineWriter.writeLine('');
|
package/lib/reporters/tap.js
CHANGED
|
@@ -153,26 +153,38 @@ export default class TapReporter {
|
|
|
153
153
|
const fileStats = this.stats && evt.testFile ? this.stats.byFile.get(evt.testFile) : null;
|
|
154
154
|
|
|
155
155
|
switch (evt.type) {
|
|
156
|
-
case 'declared-test':
|
|
156
|
+
case 'declared-test': {
|
|
157
157
|
// Ignore
|
|
158
158
|
break;
|
|
159
|
-
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
case 'hook-failed': {
|
|
160
162
|
this.writeTest(evt, {passed: false, todo: false, skip: false});
|
|
161
163
|
break;
|
|
162
|
-
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
case 'hook-finished': {
|
|
163
167
|
this.writeComment(evt, {});
|
|
164
168
|
break;
|
|
165
|
-
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
case 'internal-error': {
|
|
166
172
|
this.writeCrash(evt);
|
|
167
173
|
break;
|
|
168
|
-
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
case 'missing-ava-import': {
|
|
169
177
|
this.filesWithMissingAvaImports.add(evt.testFile);
|
|
170
178
|
this.writeCrash(evt, `No tests found in ${this.relativeFile(evt.testFile)}, make sure to import "ava" at the top of your test file`);
|
|
171
179
|
break;
|
|
172
|
-
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
case 'process-exit': {
|
|
173
183
|
this.writeProcessExit(evt);
|
|
174
184
|
break;
|
|
175
|
-
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
case 'selected-test': {
|
|
176
188
|
if (evt.skip) {
|
|
177
189
|
this.writeTest(evt, {passed: true, todo: false, skip: true});
|
|
178
190
|
} else if (evt.todo) {
|
|
@@ -180,25 +192,39 @@ export default class TapReporter {
|
|
|
180
192
|
}
|
|
181
193
|
|
|
182
194
|
break;
|
|
183
|
-
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
case 'stats': {
|
|
184
198
|
this.stats = evt.stats;
|
|
185
199
|
break;
|
|
186
|
-
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
case 'test-failed': {
|
|
187
203
|
this.writeTest(evt, {passed: false, todo: false, skip: false});
|
|
188
204
|
break;
|
|
189
|
-
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
case 'test-passed': {
|
|
190
208
|
this.writeTest(evt, {passed: true, todo: false, skip: false});
|
|
191
209
|
break;
|
|
192
|
-
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
case 'timeout': {
|
|
193
213
|
this.writeTimeout(evt);
|
|
194
214
|
break;
|
|
195
|
-
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
case 'uncaught-exception': {
|
|
196
218
|
this.writeCrash(evt);
|
|
197
219
|
break;
|
|
198
|
-
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
case 'unhandled-rejection': {
|
|
199
223
|
this.writeCrash(evt);
|
|
200
224
|
break;
|
|
201
|
-
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
case 'worker-failed': {
|
|
202
228
|
if (!this.filesWithMissingAvaImports.has(evt.testFile)) {
|
|
203
229
|
if (evt.nonZeroExitCode) {
|
|
204
230
|
this.writeCrash(evt, `${this.relativeFile(evt.testFile)} exited with a non-zero exit code: ${evt.nonZeroExitCode}`);
|
|
@@ -208,7 +234,9 @@ export default class TapReporter {
|
|
|
208
234
|
}
|
|
209
235
|
|
|
210
236
|
break;
|
|
211
|
-
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
case 'worker-finished': {
|
|
212
240
|
if (!evt.forcedExit && !this.filesWithMissingAvaImports.has(evt.testFile)) {
|
|
213
241
|
if (fileStats.declaredTests === 0) {
|
|
214
242
|
this.writeCrash(evt, `No tests found in ${this.relativeFile(evt.testFile)}`);
|
|
@@ -218,12 +246,17 @@ export default class TapReporter {
|
|
|
218
246
|
}
|
|
219
247
|
|
|
220
248
|
break;
|
|
249
|
+
}
|
|
250
|
+
|
|
221
251
|
case 'worker-stderr':
|
|
222
|
-
case 'worker-stdout':
|
|
252
|
+
case 'worker-stdout': {
|
|
223
253
|
this.stdStream.write(evt.chunk);
|
|
224
254
|
break;
|
|
225
|
-
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
default: {
|
|
226
258
|
break;
|
|
259
|
+
}
|
|
227
260
|
}
|
|
228
261
|
}
|
|
229
262
|
}
|
package/lib/run-status.js
CHANGED
|
@@ -9,6 +9,7 @@ export default class RunStatus extends Emittery {
|
|
|
9
9
|
super();
|
|
10
10
|
|
|
11
11
|
this.pendingTests = new Map();
|
|
12
|
+
this.pendingTestsLogs = new Map();
|
|
12
13
|
|
|
13
14
|
this.emptyParallelRun = parallelRuns
|
|
14
15
|
&& parallelRuns.currentFileCount === 0
|
|
@@ -60,6 +61,7 @@ export default class RunStatus extends Emittery {
|
|
|
60
61
|
});
|
|
61
62
|
|
|
62
63
|
this.pendingTests.set(testFile, new Set());
|
|
64
|
+
this.pendingTestsLogs.set(testFile, new Map());
|
|
63
65
|
worker.onStateChange(data => this.emitStateChange(data));
|
|
64
66
|
}
|
|
65
67
|
|
|
@@ -70,22 +72,28 @@ export default class RunStatus extends Emittery {
|
|
|
70
72
|
|
|
71
73
|
let changedStats = true;
|
|
72
74
|
switch (event.type) {
|
|
73
|
-
case 'declared-test':
|
|
75
|
+
case 'declared-test': {
|
|
74
76
|
stats.declaredTests++;
|
|
75
77
|
fileStats.declaredTests++;
|
|
76
78
|
break;
|
|
77
|
-
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
case 'hook-failed': {
|
|
78
82
|
stats.failedHooks++;
|
|
79
83
|
fileStats.failedHooks++;
|
|
80
84
|
break;
|
|
81
|
-
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
case 'internal-error': {
|
|
82
88
|
stats.internalErrors++;
|
|
83
89
|
if (event.testFile) {
|
|
84
90
|
fileStats.internalErrors++;
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
break;
|
|
88
|
-
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
case 'selected-test': {
|
|
89
97
|
stats.selectedTests++;
|
|
90
98
|
fileStats.selectedTests++;
|
|
91
99
|
if (event.skip) {
|
|
@@ -101,17 +109,23 @@ export default class RunStatus extends Emittery {
|
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
break;
|
|
104
|
-
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
case 'shared-worker-error': {
|
|
105
115
|
stats.sharedWorkerErrors++;
|
|
106
116
|
break;
|
|
107
|
-
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
case 'test-failed': {
|
|
108
120
|
stats.failedTests++;
|
|
109
121
|
fileStats.failedTests++;
|
|
110
122
|
stats.remainingTests--;
|
|
111
123
|
fileStats.remainingTests--;
|
|
112
124
|
this.removePendingTest(event);
|
|
113
125
|
break;
|
|
114
|
-
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
case 'test-passed': {
|
|
115
129
|
if (event.knownFailing) {
|
|
116
130
|
stats.passedKnownFailingTests++;
|
|
117
131
|
fileStats.passedKnownFailingTests++;
|
|
@@ -124,40 +138,68 @@ export default class RunStatus extends Emittery {
|
|
|
124
138
|
fileStats.remainingTests--;
|
|
125
139
|
this.removePendingTest(event);
|
|
126
140
|
break;
|
|
127
|
-
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
case 'test-register-log-reference': {
|
|
144
|
+
this.addPendingTestLogs(event);
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
case 'timeout': {
|
|
128
149
|
stats.timeouts++;
|
|
129
150
|
event.pendingTests = this.pendingTests;
|
|
151
|
+
event.pendingTestsLogs = this.pendingTestsLogs;
|
|
130
152
|
this.pendingTests = new Map();
|
|
153
|
+
this.pendingTestsLogs = new Map();
|
|
131
154
|
for (const testsInFile of event.pendingTests.values()) {
|
|
132
155
|
stats.timedOutTests += testsInFile.size;
|
|
133
156
|
}
|
|
134
157
|
|
|
135
158
|
break;
|
|
136
|
-
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
case 'interrupt': {
|
|
137
162
|
event.pendingTests = this.pendingTests;
|
|
163
|
+
event.pendingTestsLogs = this.pendingTestsLogs;
|
|
138
164
|
this.pendingTests = new Map();
|
|
165
|
+
this.pendingTestsLogs = new Map();
|
|
139
166
|
break;
|
|
140
|
-
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
case 'process-exit': {
|
|
141
170
|
event.pendingTests = this.pendingTests;
|
|
171
|
+
event.pendingTestsLogs = this.pendingTestsLogs;
|
|
142
172
|
this.pendingTests = new Map();
|
|
173
|
+
this.pendingTestsLogs = new Map();
|
|
143
174
|
break;
|
|
144
|
-
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
case 'uncaught-exception': {
|
|
145
178
|
stats.uncaughtExceptions++;
|
|
146
179
|
fileStats.uncaughtExceptions++;
|
|
147
180
|
break;
|
|
148
|
-
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
case 'unhandled-rejection': {
|
|
149
184
|
stats.unhandledRejections++;
|
|
150
185
|
fileStats.unhandledRejections++;
|
|
151
186
|
break;
|
|
152
|
-
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
case 'worker-failed': {
|
|
153
190
|
stats.failedWorkers++;
|
|
154
191
|
break;
|
|
155
|
-
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
case 'worker-finished': {
|
|
156
195
|
stats.finishedWorkers++;
|
|
157
196
|
break;
|
|
158
|
-
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
default: {
|
|
159
200
|
changedStats = false;
|
|
160
201
|
break;
|
|
202
|
+
}
|
|
161
203
|
}
|
|
162
204
|
|
|
163
205
|
if (changedStats) {
|
|
@@ -198,6 +240,10 @@ export default class RunStatus extends Emittery {
|
|
|
198
240
|
return 0;
|
|
199
241
|
}
|
|
200
242
|
|
|
243
|
+
addPendingTestLogs(event) {
|
|
244
|
+
this.pendingTestsLogs.get(event.testFile)?.set(event.title, event.logs);
|
|
245
|
+
}
|
|
246
|
+
|
|
201
247
|
addPendingTest(event) {
|
|
202
248
|
if (this.pendingTests.has(event.testFile)) {
|
|
203
249
|
this.pendingTests.get(event.testFile).add(event.title);
|
package/lib/runner.js
CHANGED
|
@@ -358,6 +358,12 @@ export default class Runner extends Emittery {
|
|
|
358
358
|
notifyTimeoutUpdate: this.notifyTimeoutUpdate,
|
|
359
359
|
});
|
|
360
360
|
|
|
361
|
+
this.emit('stateChange', {
|
|
362
|
+
type: 'test-register-log-reference',
|
|
363
|
+
title: task.title,
|
|
364
|
+
logs: test.logs,
|
|
365
|
+
});
|
|
366
|
+
|
|
361
367
|
const result = await this.runSingle(test);
|
|
362
368
|
testOk = result.passed;
|
|
363
369
|
|
package/lib/watcher.js
CHANGED
|
@@ -298,11 +298,14 @@ export default class Watcher {
|
|
|
298
298
|
case 'test-failed':
|
|
299
299
|
case 'uncaught-exception':
|
|
300
300
|
case 'unhandled-rejection':
|
|
301
|
-
case 'worker-failed':
|
|
301
|
+
case 'worker-failed': {
|
|
302
302
|
this.countFailure(evt.testFile, currentVector);
|
|
303
303
|
break;
|
|
304
|
-
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
default: {
|
|
305
307
|
break;
|
|
308
|
+
}
|
|
306
309
|
}
|
|
307
310
|
});
|
|
308
311
|
});
|
package/lib/worker/base.js
CHANGED
|
@@ -222,12 +222,18 @@ const onError = error => {
|
|
|
222
222
|
});
|
|
223
223
|
};
|
|
224
224
|
|
|
225
|
+
let options;
|
|
225
226
|
if (isRunningInThread) {
|
|
226
227
|
channel.send({type: 'starting'}); // AVA won't terminate the worker thread until it's seen this message.
|
|
227
|
-
|
|
228
|
+
({options} = workerData);
|
|
228
229
|
delete workerData.options; // Don't allow user code access.
|
|
229
|
-
run(options).catch(onError);
|
|
230
230
|
} else if (isRunningInChildProcess) {
|
|
231
231
|
channel.send({type: 'ready-for-options'});
|
|
232
|
-
channel.options
|
|
232
|
+
options = await channel.options;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
await run(options);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
onError(error);
|
|
233
239
|
}
|
package/lib/worker/channel.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
const events = require('events');
|
|
3
|
-
const process = require('process');
|
|
4
|
-
const {MessageChannel, threadId} = require('worker_threads');
|
|
2
|
+
const events = require('node:events');
|
|
3
|
+
const process = require('node:process');
|
|
4
|
+
const {MessageChannel, threadId} = require('node:worker_threads');
|
|
5
5
|
|
|
6
6
|
const timers = require('../now-and-timers.cjs');
|
|
7
7
|
|
|
@@ -125,7 +125,7 @@ if (isRunningInChildProcess) {
|
|
|
125
125
|
const {controlFlow} = require('../ipc-flow-control.cjs');
|
|
126
126
|
handle = new IpcHandle(controlFlow(process));
|
|
127
127
|
} else if (isRunningInThread) {
|
|
128
|
-
const {parentPort} = require('worker_threads');
|
|
128
|
+
const {parentPort} = require('node:worker_threads');
|
|
129
129
|
handle = new MessagePortHandle(parentPort);
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -133,7 +133,7 @@ if (isRunningInChildProcess) {
|
|
|
133
133
|
// Node.js. In order to keep track, explicitly reference before attaching.
|
|
134
134
|
handle.ref();
|
|
135
135
|
|
|
136
|
-
exports.options = pEvent(handle.channel, 'message', selectAvaMessage('options')).then(message => message.ava.options);
|
|
136
|
+
exports.options = pEvent(handle.channel, 'message', selectAvaMessage('options')).then(message => message.ava.options); // eslint-disable-line unicorn/prefer-top-level-await
|
|
137
137
|
exports.peerFailed = pEvent(handle.channel, 'message', selectAvaMessage('peer-failed'));
|
|
138
138
|
exports.send = handle.send.bind(handle);
|
|
139
139
|
exports.unref = handle.unref.bind(handle);
|
package/lib/worker/main.cjs
CHANGED
package/lib/worker/utils.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
const process = require('process');
|
|
3
|
-
const {isMainThread} = require('worker_threads');
|
|
2
|
+
const process = require('node:process');
|
|
3
|
+
const {isMainThread} = require('node:worker_threads');
|
|
4
4
|
|
|
5
5
|
exports.isRunningInThread = isMainThread === false;
|
|
6
6
|
exports.isRunningInChildProcess = typeof process.send === 'function';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ava",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "Node.js test runner that lets you develop with confidence.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "avajs/ava",
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
"typescript"
|
|
82
82
|
],
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"acorn": "^8.8.
|
|
84
|
+
"acorn": "^8.8.1",
|
|
85
85
|
"acorn-walk": "^8.2.0",
|
|
86
|
-
"ansi-styles": "^6.
|
|
86
|
+
"ansi-styles": "^6.2.1",
|
|
87
87
|
"arrgv": "^1.0.2",
|
|
88
88
|
"arrify": "^3.0.0",
|
|
89
89
|
"callsites": "^4.0.0",
|
|
90
90
|
"cbor": "^8.1.0",
|
|
91
|
-
"chalk": "^5.0
|
|
91
|
+
"chalk": "^5.2.0",
|
|
92
92
|
"chokidar": "^3.5.3",
|
|
93
93
|
"chunkd": "^2.0.1",
|
|
94
|
-
"ci-info": "^3.
|
|
94
|
+
"ci-info": "^3.7.1",
|
|
95
95
|
"ci-parallel-vars": "^1.0.1",
|
|
96
96
|
"clean-yaml-object": "^0.1.0",
|
|
97
97
|
"cli-truncate": "^3.1.0",
|
|
@@ -101,9 +101,9 @@
|
|
|
101
101
|
"currently-unhandled": "^0.4.1",
|
|
102
102
|
"debug": "^4.3.4",
|
|
103
103
|
"del": "^7.0.0",
|
|
104
|
-
"emittery": "^1.0.
|
|
104
|
+
"emittery": "^1.0.1",
|
|
105
105
|
"figures": "^5.0.0",
|
|
106
|
-
"globby": "^13.1.
|
|
106
|
+
"globby": "^13.1.3",
|
|
107
107
|
"ignore-by-default": "^2.1.0",
|
|
108
108
|
"indent-string": "^5.0.0",
|
|
109
109
|
"is-error": "^2.2.2",
|
|
@@ -120,34 +120,33 @@
|
|
|
120
120
|
"pretty-ms": "^8.0.0",
|
|
121
121
|
"resolve-cwd": "^3.0.0",
|
|
122
122
|
"slash": "^3.0.0",
|
|
123
|
-
"stack-utils": "^2.0.
|
|
123
|
+
"stack-utils": "^2.0.6",
|
|
124
124
|
"strip-ansi": "^7.0.1",
|
|
125
125
|
"supertap": "^3.0.1",
|
|
126
|
-
"temp-dir": "^
|
|
127
|
-
"write-file-atomic": "^
|
|
128
|
-
"yargs": "^17.
|
|
126
|
+
"temp-dir": "^3.0.0",
|
|
127
|
+
"write-file-atomic": "^5.0.0",
|
|
128
|
+
"yargs": "^17.6.2"
|
|
129
129
|
},
|
|
130
130
|
"devDependencies": {
|
|
131
131
|
"@ava/test": "github:avajs/test",
|
|
132
132
|
"@ava/typescript": "^3.0.1",
|
|
133
133
|
"@sindresorhus/tsconfig": "^3.0.1",
|
|
134
|
-
"@sinonjs/fake-timers": "^9.1.2",
|
|
135
134
|
"ansi-escapes": "^6.0.0",
|
|
136
135
|
"c8": "^7.12.0",
|
|
137
136
|
"delay": "^5.0.0",
|
|
138
137
|
"execa": "^6.1.0",
|
|
139
|
-
"fs-extra": "^
|
|
138
|
+
"fs-extra": "^11.1.0",
|
|
140
139
|
"get-stream": "^6.0.1",
|
|
141
140
|
"replace-string": "^4.0.0",
|
|
142
|
-
"sinon": "^
|
|
143
|
-
"tap": "^16.3.
|
|
141
|
+
"sinon": "^15.0.1",
|
|
142
|
+
"tap": "^16.3.3",
|
|
144
143
|
"temp-write": "^5.0.0",
|
|
145
144
|
"tempy": "^3.0.0",
|
|
146
145
|
"touch": "^3.1.0",
|
|
147
|
-
"tsd": "^0.
|
|
148
|
-
"typescript": "^4.
|
|
149
|
-
"xo": "^0.
|
|
150
|
-
"zen-observable": "^0.
|
|
146
|
+
"tsd": "^0.25.0",
|
|
147
|
+
"typescript": "^4.9.4",
|
|
148
|
+
"xo": "^0.53.1",
|
|
149
|
+
"zen-observable": "^0.10.0"
|
|
151
150
|
},
|
|
152
151
|
"peerDependencies": {
|
|
153
152
|
"@ava/typescript": "*"
|
|
@@ -158,7 +157,7 @@
|
|
|
158
157
|
}
|
|
159
158
|
},
|
|
160
159
|
"volta": {
|
|
161
|
-
"node": "18.
|
|
162
|
-
"npm": "
|
|
160
|
+
"node": "18.13.0",
|
|
161
|
+
"npm": "9.3.0"
|
|
163
162
|
}
|
|
164
163
|
}
|