ava 5.3.1 → 6.0.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/entrypoints/internal.d.mts +7 -0
- package/lib/api-event-iterator.js +12 -0
- package/lib/api.js +14 -23
- package/lib/assert.js +289 -444
- package/lib/cli.js +95 -61
- package/lib/code-excerpt.js +2 -2
- package/lib/eslint-plugin-helper-worker.js +3 -3
- package/lib/fork.js +3 -13
- package/lib/glob-helpers.cjs +1 -9
- package/lib/globs.js +7 -3
- package/lib/line-numbers.js +1 -1
- package/lib/load-config.js +3 -3
- package/lib/parse-test-args.js +3 -3
- package/lib/plugin-support/shared-workers.js +4 -4
- package/lib/provider-manager.js +11 -13
- package/lib/reporters/beautify-stack.js +0 -1
- package/lib/reporters/default.js +92 -45
- package/lib/reporters/format-serialized-error.js +6 -6
- package/lib/reporters/improper-usage-messages.js +5 -5
- package/lib/reporters/tap.js +30 -30
- package/lib/run-status.js +9 -0
- package/lib/runner.js +7 -7
- package/lib/scheduler.js +14 -1
- package/lib/serialize-error.js +44 -116
- package/lib/slash.cjs +1 -1
- package/lib/snapshot-manager.js +14 -8
- package/lib/test.js +90 -81
- package/lib/watcher.js +494 -365
- package/lib/worker/base.js +90 -51
- package/lib/worker/channel.cjs +9 -53
- package/license +1 -1
- package/package.json +36 -42
- package/readme.md +6 -12
- package/types/assertions.d.cts +107 -49
- package/types/shared-worker.d.cts +0 -2
- package/types/state-change-events.d.cts +143 -0
- package/types/test-fn.d.cts +10 -5
- package/lib/worker/dependency-tracker.js +0 -48
- /package/entrypoints/{main.d.ts → main.d.mts} +0 -0
- /package/entrypoints/{plugin.d.ts → plugin.d.mts} +0 -0
package/lib/reporters/default.js
CHANGED
|
@@ -25,7 +25,7 @@ class LineWriter extends stream.Writable {
|
|
|
25
25
|
super();
|
|
26
26
|
|
|
27
27
|
this.dest = dest;
|
|
28
|
-
this.columns = dest.columns
|
|
28
|
+
this.columns = dest.columns ?? 80;
|
|
29
29
|
this.lastLineIsEmpty = false;
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -91,7 +91,7 @@ export default class Reporter {
|
|
|
91
91
|
this.consumeStateChange = decorateWriter(this.consumeStateChange);
|
|
92
92
|
this.endRun = decorateWriter(this.endRun);
|
|
93
93
|
|
|
94
|
-
this.durationThreshold = durationThreshold
|
|
94
|
+
this.durationThreshold = durationThreshold ?? 100;
|
|
95
95
|
this.lineWriter = new LineWriter(this.reportStream);
|
|
96
96
|
|
|
97
97
|
this.reset();
|
|
@@ -148,7 +148,7 @@ export default class Reporter {
|
|
|
148
148
|
this.consumeStateChange(evt);
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
-
if (this.watching && plan.
|
|
151
|
+
if (this.watching && !plan.firstRun) {
|
|
152
152
|
this.lineWriter.write(chalk.gray.dim('\u2500'.repeat(this.lineWriter.columns)) + os.EOL);
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -208,9 +208,7 @@ export default class Reporter {
|
|
|
208
208
|
this.write(colors.error(`${figures.cross} Internal error`));
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
this.
|
|
212
|
-
this.lineWriter.writeLine(colors.errorStack(event.err.stack));
|
|
213
|
-
this.lineWriter.writeLine();
|
|
211
|
+
this.writeSerializedError(event.err);
|
|
214
212
|
this.lineWriter.writeLine();
|
|
215
213
|
|
|
216
214
|
break;
|
|
@@ -221,8 +219,7 @@ export default class Reporter {
|
|
|
221
219
|
|
|
222
220
|
this.write(colors.information(`${figures.warning} Could not parse ${this.relativeFile(event.testFile)} for line number selection`));
|
|
223
221
|
this.lineWriter.writeLine();
|
|
224
|
-
this.
|
|
225
|
-
this.lineWriter.writeLine();
|
|
222
|
+
this.writeSerializedError(event.err);
|
|
226
223
|
break;
|
|
227
224
|
}
|
|
228
225
|
|
|
@@ -268,7 +265,7 @@ export default class Reporter {
|
|
|
268
265
|
this.lineWriter.ensureEmptyLine();
|
|
269
266
|
this.lineWriter.writeLine(colors.error(`${figures.cross} Error in shared worker`));
|
|
270
267
|
this.lineWriter.writeLine();
|
|
271
|
-
this.
|
|
268
|
+
this.writeSerializedError(event.err);
|
|
272
269
|
|
|
273
270
|
break;
|
|
274
271
|
}
|
|
@@ -279,7 +276,7 @@ export default class Reporter {
|
|
|
279
276
|
this.lineWriter.ensureEmptyLine();
|
|
280
277
|
this.lineWriter.writeLine(colors.title(`Uncaught exception in ${this.relativeFile(event.testFile)}`));
|
|
281
278
|
this.lineWriter.writeLine();
|
|
282
|
-
this.
|
|
279
|
+
this.writeSerializedError(event.err);
|
|
283
280
|
|
|
284
281
|
break;
|
|
285
282
|
}
|
|
@@ -290,7 +287,7 @@ export default class Reporter {
|
|
|
290
287
|
this.lineWriter.ensureEmptyLine();
|
|
291
288
|
this.lineWriter.writeLine(colors.title(`Unhandled rejection in ${this.relativeFile(event.testFile)}`));
|
|
292
289
|
this.lineWriter.writeLine();
|
|
293
|
-
this.
|
|
290
|
+
this.writeSerializedError(event.err);
|
|
294
291
|
|
|
295
292
|
break;
|
|
296
293
|
}
|
|
@@ -304,7 +301,7 @@ export default class Reporter {
|
|
|
304
301
|
if (event.err) {
|
|
305
302
|
this.lineWriter.writeLine(colors.error(`${figures.cross} ${this.relativeFile(event.testFile)} exited due to an error:`));
|
|
306
303
|
this.lineWriter.writeLine();
|
|
307
|
-
this.
|
|
304
|
+
this.writeSerializedError(event.err);
|
|
308
305
|
} else if (event.nonZeroExitCode) {
|
|
309
306
|
this.lineWriter.writeLine(colors.error(`${figures.cross} ${this.relativeFile(event.testFile)} exited with a non-zero exit code: ${event.nonZeroExitCode}`));
|
|
310
307
|
} else {
|
|
@@ -341,7 +338,7 @@ export default class Reporter {
|
|
|
341
338
|
// we multiplex stdout and stderr into a single stream. However as
|
|
342
339
|
// long as stdStream is different from reportStream users can read
|
|
343
340
|
// their original output by redirecting the streams.
|
|
344
|
-
if (event.chunk
|
|
341
|
+
if (event.chunk.at(-1) !== 0x0A) {
|
|
345
342
|
this.reportStream.write(os.EOL);
|
|
346
343
|
}
|
|
347
344
|
|
|
@@ -356,7 +353,7 @@ export default class Reporter {
|
|
|
356
353
|
// we multiplex stdout and stderr into a single stream. However as
|
|
357
354
|
// long as stdStream is different from reportStream users can read
|
|
358
355
|
// their original output by redirecting the streams.
|
|
359
|
-
if (event.chunk
|
|
356
|
+
if (event.chunk.at(-1) !== 0x0A) {
|
|
360
357
|
this.reportStream.write(os.EOL);
|
|
361
358
|
}
|
|
362
359
|
}
|
|
@@ -366,6 +363,7 @@ export default class Reporter {
|
|
|
366
363
|
writePendingTests(evt) {
|
|
367
364
|
for (const [file, testsInFile] of evt.pendingTests) {
|
|
368
365
|
if (testsInFile.size === 0) {
|
|
366
|
+
this.lineWriter.writeLine(`Failed to exit when running ${this.relativeFile(file)}\n`);
|
|
369
367
|
continue;
|
|
370
368
|
}
|
|
371
369
|
|
|
@@ -390,7 +388,7 @@ export default class Reporter {
|
|
|
390
388
|
return this.lineWriter.writeLine(string);
|
|
391
389
|
}
|
|
392
390
|
|
|
393
|
-
string
|
|
391
|
+
string ??= '';
|
|
394
392
|
if (string !== '') {
|
|
395
393
|
string += os.EOL;
|
|
396
394
|
}
|
|
@@ -427,16 +425,32 @@ export default class Reporter {
|
|
|
427
425
|
this.lineWriter.writeLine(string);
|
|
428
426
|
}
|
|
429
427
|
|
|
430
|
-
|
|
431
|
-
if (
|
|
432
|
-
|
|
428
|
+
writeSerializedError(error) { // eslint-disable-line complexity
|
|
429
|
+
if (error.type === 'aggregate') {
|
|
430
|
+
for (const error_ of error.errors) {
|
|
431
|
+
this.writeSerializedError(error_);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (error.type === 'unknown') {
|
|
438
|
+
this.lineWriter.writeLine(error.formattedError);
|
|
433
439
|
this.lineWriter.writeLine();
|
|
434
440
|
return;
|
|
435
441
|
}
|
|
436
442
|
|
|
437
|
-
if (
|
|
438
|
-
this.lineWriter.writeLine(colors.
|
|
439
|
-
|
|
443
|
+
if (error.type === 'native' && error.name === 'TSError' && error.originalError.diagnosticText) {
|
|
444
|
+
this.lineWriter.writeLine(colors.errorStack(error.originalError.diagnosticText));
|
|
445
|
+
this.lineWriter.writeLine();
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const hasSource = error.source !== null;
|
|
450
|
+
if (hasSource) {
|
|
451
|
+
const {source} = error;
|
|
452
|
+
this.lineWriter.writeLine(colors.errorSource(`${this.relativeFile(source.file)}:${source.line}`));
|
|
453
|
+
const excerpt = codeExcerpt(source, {maxWidth: this.reportStream.columns - 2});
|
|
440
454
|
if (excerpt) {
|
|
441
455
|
this.lineWriter.writeLine();
|
|
442
456
|
this.lineWriter.writeLine(excerpt);
|
|
@@ -444,10 +458,47 @@ export default class Reporter {
|
|
|
444
458
|
}
|
|
445
459
|
}
|
|
446
460
|
|
|
447
|
-
|
|
448
|
-
|
|
461
|
+
let summary = '';
|
|
462
|
+
let printStack = true;
|
|
463
|
+
if (error.type === 'native') {
|
|
464
|
+
const lines = error.stack.split('\n');
|
|
465
|
+
|
|
466
|
+
// SyntaxError stacks may begin with the offending code. Write all stack
|
|
467
|
+
// lines up to and including one that begins with SyntaxError.
|
|
468
|
+
if (error.name === 'SyntaxError') {
|
|
469
|
+
for (const line of lines) {
|
|
470
|
+
summary += line + '\n';
|
|
471
|
+
if (line.startsWith('SyntaxError')) {
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
printStack = summary === '';
|
|
477
|
+
} else {
|
|
478
|
+
// Handle multi-line error messages.
|
|
479
|
+
for (let index = 0; index < lines.length; index++) {
|
|
480
|
+
if (/^\s+at/.test(lines[index])) {
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const next = index + 1;
|
|
485
|
+
const end = next === lines.length || /^\s+at/.test(lines[next]);
|
|
486
|
+
summary += end ? lines[index] : lines[index] + '\n';
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
if (summary !== '') {
|
|
491
|
+
this.lineWriter.writeLine(summary.trim());
|
|
492
|
+
this.lineWriter.writeLine();
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (error.type === 'ava') {
|
|
497
|
+
const {formattedDetails, improperUsage, message} = error;
|
|
498
|
+
|
|
499
|
+
const result = formatSerializedError(formattedDetails, message);
|
|
449
500
|
if (result.printMessage) {
|
|
450
|
-
this.lineWriter.writeLine(
|
|
501
|
+
this.lineWriter.writeLine(message);
|
|
451
502
|
this.lineWriter.writeLine();
|
|
452
503
|
}
|
|
453
504
|
|
|
@@ -456,33 +507,29 @@ export default class Reporter {
|
|
|
456
507
|
this.lineWriter.writeLine();
|
|
457
508
|
}
|
|
458
509
|
|
|
459
|
-
const
|
|
460
|
-
if (
|
|
461
|
-
this.lineWriter.writeLine(
|
|
510
|
+
const usageMessage = improperUsageMessage(improperUsage);
|
|
511
|
+
if (usageMessage) {
|
|
512
|
+
this.lineWriter.writeLine(usageMessage);
|
|
462
513
|
this.lineWriter.writeLine();
|
|
463
514
|
}
|
|
464
|
-
} else if (event.err.nonErrorObject) {
|
|
465
|
-
this.lineWriter.writeLine(event.err.formatted);
|
|
466
|
-
this.lineWriter.writeLine();
|
|
467
|
-
} else {
|
|
468
|
-
this.lineWriter.writeLine(event.err.summary);
|
|
469
|
-
this.lineWriter.writeLine();
|
|
470
515
|
}
|
|
471
516
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
517
|
+
if (printStack) {
|
|
518
|
+
const formattedStack = this.formatErrorStack(error.stack, hasSource);
|
|
519
|
+
if (formattedStack.length > 0) {
|
|
520
|
+
this.lineWriter.writeLine(formattedStack.join('\n'));
|
|
521
|
+
this.lineWriter.writeLine();
|
|
522
|
+
}
|
|
476
523
|
}
|
|
477
524
|
}
|
|
478
525
|
|
|
479
|
-
formatErrorStack(
|
|
480
|
-
if (
|
|
526
|
+
formatErrorStack(stack, hasSource) {
|
|
527
|
+
if (stack === '') {
|
|
481
528
|
return [];
|
|
482
529
|
}
|
|
483
530
|
|
|
484
|
-
if (
|
|
485
|
-
return beautifyStack(
|
|
531
|
+
if (hasSource) {
|
|
532
|
+
return beautifyStack(stack).map(line => {
|
|
486
533
|
if (nodeInternals.some(internal => internal.test(line))) {
|
|
487
534
|
return colors.errorStackInternal(`${figures.pointerSmall} ${line}`);
|
|
488
535
|
}
|
|
@@ -491,11 +538,11 @@ export default class Reporter {
|
|
|
491
538
|
});
|
|
492
539
|
}
|
|
493
540
|
|
|
494
|
-
return [
|
|
541
|
+
return [colors.errorStack(stack)];
|
|
495
542
|
}
|
|
496
543
|
|
|
497
544
|
writeLogs(event, surroundLines) {
|
|
498
|
-
if (event.logs
|
|
545
|
+
if (event.logs?.length > 0) {
|
|
499
546
|
if (surroundLines) {
|
|
500
547
|
this.lineWriter.writeLine();
|
|
501
548
|
}
|
|
@@ -551,7 +598,7 @@ export default class Reporter {
|
|
|
551
598
|
this.lineWriter.writeLine();
|
|
552
599
|
}
|
|
553
600
|
|
|
554
|
-
this.
|
|
601
|
+
this.writeSerializedError(event.err);
|
|
555
602
|
}
|
|
556
603
|
|
|
557
604
|
endRun() {// eslint-disable-line complexity
|
|
@@ -602,7 +649,7 @@ export default class Reporter {
|
|
|
602
649
|
this.lineWriter.writeLine();
|
|
603
650
|
|
|
604
651
|
if (this.failures.length > 0) {
|
|
605
|
-
const lastFailure = this.failures
|
|
652
|
+
const lastFailure = this.failures.at(-1);
|
|
606
653
|
for (const event of this.failures) {
|
|
607
654
|
this.writeFailure(event);
|
|
608
655
|
if (event !== lastFailure) {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export default function formatSerializedError(
|
|
2
|
-
const printMessage =
|
|
3
|
-
? Boolean(
|
|
4
|
-
: !
|
|
1
|
+
export default function formatSerializedError(formattedDetails, message) {
|
|
2
|
+
const printMessage = formattedDetails.length === 0
|
|
3
|
+
? Boolean(message)
|
|
4
|
+
: !formattedDetails[0].label.startsWith(message);
|
|
5
5
|
|
|
6
|
-
if (
|
|
6
|
+
if (formattedDetails.length === 0) {
|
|
7
7
|
return {formatted: null, printMessage};
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
let formatted = '';
|
|
11
|
-
for (const value of
|
|
11
|
+
for (const value of formattedDetails) {
|
|
12
12
|
formatted += `${value.label}\n\n${value.formatted}\n\n`;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {chalk} from '../chalk.js';
|
|
2
2
|
import pkg from '../pkg.cjs';
|
|
3
3
|
|
|
4
|
-
export default function buildMessage(
|
|
5
|
-
if (!
|
|
4
|
+
export default function buildMessage(improperUsage) {
|
|
5
|
+
if (!improperUsage) {
|
|
6
6
|
return null;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
const {assertion} =
|
|
9
|
+
const {assertion} = improperUsage;
|
|
10
10
|
if (assertion === 'throws' || assertion === 'notThrows') {
|
|
11
11
|
return `Try wrapping the first argument to \`t.${assertion}()\` in a function:
|
|
12
12
|
|
|
@@ -18,7 +18,7 @@ Visit the following URL for more details:
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
if (assertion === 'snapshot') {
|
|
21
|
-
const {name, snapPath} =
|
|
21
|
+
const {name, snapPath} = improperUsage;
|
|
22
22
|
|
|
23
23
|
if (name === 'ChecksumError' || name === 'InvalidSnapshotError') {
|
|
24
24
|
return `The snapshot file is corrupted.
|
|
@@ -37,7 +37,7 @@ Please run AVA again with the ${chalk.cyan('--update-snapshots')} flag to upgrad
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if (name === 'VersionMismatchError') {
|
|
40
|
-
const {snapVersion, expectedVersion} =
|
|
40
|
+
const {snapVersion, expectedVersion} = improperUsage;
|
|
41
41
|
const upgradeMessage = snapVersion < expectedVersion
|
|
42
42
|
? `Please run AVA again with the ${chalk.cyan('--update-snapshots')} flag to upgrade.`
|
|
43
43
|
: 'You should upgrade AVA.';
|
package/lib/reporters/tap.js
CHANGED
|
@@ -6,43 +6,42 @@ import plur from 'plur';
|
|
|
6
6
|
import stripAnsi from 'strip-ansi';
|
|
7
7
|
import * as supertap from 'supertap';
|
|
8
8
|
|
|
9
|
-
import beautifyStack from './beautify-stack.js';
|
|
10
9
|
import prefixTitle from './prefix-title.js';
|
|
11
10
|
|
|
12
|
-
function dumpError(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
function dumpError({
|
|
12
|
+
assertion,
|
|
13
|
+
formattedDetails,
|
|
14
|
+
formattedError,
|
|
15
|
+
name,
|
|
16
|
+
originalError, // A structured clone, so some details are missing.
|
|
17
|
+
stack,
|
|
18
|
+
type,
|
|
19
|
+
}, sanitizeStackOutput) {
|
|
20
|
+
if (type === 'unknown') {
|
|
21
|
+
return {
|
|
22
|
+
message: 'Non-native error',
|
|
23
|
+
formatted: stripAnsi(formattedError),
|
|
24
|
+
};
|
|
16
25
|
}
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
object.message = error.message;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (error.avaAssertionError) {
|
|
23
|
-
if (error.assertion) {
|
|
24
|
-
object.assertion = error.assertion;
|
|
25
|
-
}
|
|
27
|
+
originalError.name = name; // Restore the original name.
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if (type === 'ava') {
|
|
30
|
+
if (assertion) {
|
|
31
|
+
originalError.assertion = assertion;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
if (
|
|
32
|
-
|
|
34
|
+
if (formattedDetails.length > 0) {
|
|
35
|
+
originalError.details = Object.fromEntries(formattedDetails.map(({label, formatted}) => [
|
|
36
|
+
stripAnsi(label),
|
|
37
|
+
stripAnsi(formatted),
|
|
38
|
+
]));
|
|
33
39
|
}
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
object.message = 'Non-error object';
|
|
38
|
-
object.formatted = stripAnsi(error.formatted);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (error.stack) {
|
|
42
|
-
object.at = error.shouldBeautifyStack ? beautifyStack(error.stack).join('\n') : error.stack;
|
|
43
|
-
}
|
|
42
|
+
originalError.stack = sanitizeStackOutput?.(stack || originalError.stack) ?? (stack || originalError.stack);
|
|
44
43
|
|
|
45
|
-
return
|
|
44
|
+
return originalError;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
export default class TapReporter {
|
|
@@ -52,6 +51,7 @@ export default class TapReporter {
|
|
|
52
51
|
this.extensions = options.extensions;
|
|
53
52
|
this.stdStream = options.stdStream;
|
|
54
53
|
this.reportStream = options.reportStream;
|
|
54
|
+
this.sanitizeStackOutput = options.sanitizeStackOutput;
|
|
55
55
|
|
|
56
56
|
this.crashCount = 0;
|
|
57
57
|
this.filesWithMissingAvaImports = new Set();
|
|
@@ -98,7 +98,7 @@ export default class TapReporter {
|
|
|
98
98
|
writeTest(evt, flags) {
|
|
99
99
|
this.reportStream.write(supertap.test(this.prefixTitle(evt.testFile, evt.title), {
|
|
100
100
|
comment: evt.logs,
|
|
101
|
-
error: evt.err ? dumpError(evt.err) : null,
|
|
101
|
+
error: evt.err ? dumpError(evt.err, this.sanitizeStackOutput) : null,
|
|
102
102
|
index: ++this.i,
|
|
103
103
|
passed: flags.passed,
|
|
104
104
|
skip: flags.skip,
|
|
@@ -108,9 +108,9 @@ export default class TapReporter {
|
|
|
108
108
|
|
|
109
109
|
writeCrash(evt, title) {
|
|
110
110
|
this.crashCount++;
|
|
111
|
-
this.reportStream.write(supertap.test(title
|
|
111
|
+
this.reportStream.write(supertap.test(title ?? evt.err.stack?.split('\n')[0].trim() ?? evt.err.message ?? evt.type, {
|
|
112
112
|
comment: evt.logs,
|
|
113
|
-
error: evt.err ? dumpError(evt.err) : null,
|
|
113
|
+
error: evt.err ? dumpError(evt.err, this.sanitizeStackOutput) : null,
|
|
114
114
|
index: ++this.i,
|
|
115
115
|
passed: false,
|
|
116
116
|
skip: false,
|
|
@@ -122,7 +122,7 @@ export default class TapReporter {
|
|
|
122
122
|
this.reportStream.write(`# ${stripAnsi(title)}${os.EOL}`);
|
|
123
123
|
if (evt.logs) {
|
|
124
124
|
for (const log of evt.logs) {
|
|
125
|
-
const logLines = indentString(log, 4).
|
|
125
|
+
const logLines = indentString(log, 4).replaceAll(/^ {4}/gm, '# ');
|
|
126
126
|
this.reportStream.write(`${logLines}${os.EOL}`);
|
|
127
127
|
}
|
|
128
128
|
}
|
package/lib/run-status.js
CHANGED
|
@@ -193,6 +193,10 @@ export default class RunStatus extends Emittery {
|
|
|
193
193
|
|
|
194
194
|
case 'worker-finished': {
|
|
195
195
|
stats.finishedWorkers++;
|
|
196
|
+
if (this.pendingTests.get(event.testFile)?.size === 0) {
|
|
197
|
+
this.pendingTests.delete(event.testFile);
|
|
198
|
+
}
|
|
199
|
+
|
|
196
200
|
break;
|
|
197
201
|
}
|
|
198
202
|
|
|
@@ -209,6 +213,11 @@ export default class RunStatus extends Emittery {
|
|
|
209
213
|
this.emit('stateChange', event);
|
|
210
214
|
}
|
|
211
215
|
|
|
216
|
+
end() {
|
|
217
|
+
this.emitStateChange({type: 'end'});
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
|
|
212
221
|
suggestExitCode(circumstances) {
|
|
213
222
|
if (this.emptyParallelRun) {
|
|
214
223
|
return 0;
|
package/lib/runner.js
CHANGED
|
@@ -17,12 +17,12 @@ export default class Runner extends Emittery {
|
|
|
17
17
|
constructor(options = {}) {
|
|
18
18
|
super();
|
|
19
19
|
|
|
20
|
-
this.experiments = options.experiments
|
|
20
|
+
this.experiments = options.experiments ?? {};
|
|
21
21
|
this.failFast = options.failFast === true;
|
|
22
22
|
this.failWithoutAssertions = options.failWithoutAssertions !== false;
|
|
23
23
|
this.file = options.file;
|
|
24
24
|
this.checkSelectedByLineNumbers = options.checkSelectedByLineNumbers;
|
|
25
|
-
this.match = options.match
|
|
25
|
+
this.match = options.match ?? [];
|
|
26
26
|
this.projectDir = options.projectDir;
|
|
27
27
|
this.recordNewSnapshots = options.recordNewSnapshots === true;
|
|
28
28
|
this.runOnlyExclusive = options.runOnlyExclusive === true;
|
|
@@ -151,7 +151,7 @@ export default class Runner extends Emittery {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
const task = {
|
|
154
|
-
title: title.value
|
|
154
|
+
title: title.value ?? fallbackTitle,
|
|
155
155
|
implementation,
|
|
156
156
|
args,
|
|
157
157
|
metadata: {...metadata},
|
|
@@ -209,7 +209,7 @@ export default class Runner extends Emittery {
|
|
|
209
209
|
updating: this.updateSnapshots,
|
|
210
210
|
});
|
|
211
211
|
if (snapshots.snapPath !== undefined) {
|
|
212
|
-
this.emit('
|
|
212
|
+
this.emit('accessed-snapshots', snapshots.snapPath);
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
this._snapshots = snapshots;
|
|
@@ -301,7 +301,7 @@ export default class Runner extends Emittery {
|
|
|
301
301
|
skipSnapshot: this.boundSkipSnapshot,
|
|
302
302
|
updateSnapshots: this.updateSnapshots,
|
|
303
303
|
metadata: task.metadata,
|
|
304
|
-
title: `${task.title}${titleSuffix
|
|
304
|
+
title: `${task.title}${titleSuffix ?? ''}`,
|
|
305
305
|
isHook: true,
|
|
306
306
|
testPassed,
|
|
307
307
|
notifyTimeoutUpdate: this.notifyTimeoutUpdate,
|
|
@@ -319,7 +319,7 @@ export default class Runner extends Emittery {
|
|
|
319
319
|
this.emit('stateChange', {
|
|
320
320
|
type: 'hook-failed',
|
|
321
321
|
title: result.title,
|
|
322
|
-
err: serializeError(
|
|
322
|
+
err: serializeError(result.error, {testFile: this.file}),
|
|
323
323
|
duration: result.duration,
|
|
324
324
|
logs: result.logs,
|
|
325
325
|
});
|
|
@@ -387,7 +387,7 @@ export default class Runner extends Emittery {
|
|
|
387
387
|
this.emit('stateChange', {
|
|
388
388
|
type: 'test-failed',
|
|
389
389
|
title: result.title,
|
|
390
|
-
err: serializeError(
|
|
390
|
+
err: serializeError(result.error, {testFile: this.file}),
|
|
391
391
|
duration: result.duration,
|
|
392
392
|
knownFailing: result.metadata.failing,
|
|
393
393
|
logs: result.logs,
|
package/lib/scheduler.js
CHANGED
|
@@ -13,9 +13,22 @@ const scheduler = {
|
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
const filename = path.join(cacheDir, FILENAME);
|
|
17
|
+
// Given that we're writing to a cache directory, consider this file
|
|
18
|
+
// temporary.
|
|
19
|
+
const temporaryFiles = [filename];
|
|
16
20
|
try {
|
|
17
|
-
writeFileAtomic.sync(
|
|
21
|
+
writeFileAtomic.sync(filename, JSON.stringify(runStatus.getFailedTestFiles()), {
|
|
22
|
+
tmpfileCreated(tmpfile) {
|
|
23
|
+
temporaryFiles.push(tmpfile);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
18
26
|
} catch {}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
changedFiles: [],
|
|
30
|
+
temporaryFiles,
|
|
31
|
+
};
|
|
19
32
|
},
|
|
20
33
|
|
|
21
34
|
// Order test-files, so that files with failing tests come first
|