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.
Files changed (40) hide show
  1. package/entrypoints/internal.d.mts +7 -0
  2. package/lib/api-event-iterator.js +12 -0
  3. package/lib/api.js +14 -23
  4. package/lib/assert.js +289 -444
  5. package/lib/cli.js +95 -61
  6. package/lib/code-excerpt.js +2 -2
  7. package/lib/eslint-plugin-helper-worker.js +3 -3
  8. package/lib/fork.js +3 -13
  9. package/lib/glob-helpers.cjs +1 -9
  10. package/lib/globs.js +7 -3
  11. package/lib/line-numbers.js +1 -1
  12. package/lib/load-config.js +3 -3
  13. package/lib/parse-test-args.js +3 -3
  14. package/lib/plugin-support/shared-workers.js +4 -4
  15. package/lib/provider-manager.js +11 -13
  16. package/lib/reporters/beautify-stack.js +0 -1
  17. package/lib/reporters/default.js +92 -45
  18. package/lib/reporters/format-serialized-error.js +6 -6
  19. package/lib/reporters/improper-usage-messages.js +5 -5
  20. package/lib/reporters/tap.js +30 -30
  21. package/lib/run-status.js +9 -0
  22. package/lib/runner.js +7 -7
  23. package/lib/scheduler.js +14 -1
  24. package/lib/serialize-error.js +44 -116
  25. package/lib/slash.cjs +1 -1
  26. package/lib/snapshot-manager.js +14 -8
  27. package/lib/test.js +90 -81
  28. package/lib/watcher.js +494 -365
  29. package/lib/worker/base.js +90 -51
  30. package/lib/worker/channel.cjs +9 -53
  31. package/license +1 -1
  32. package/package.json +36 -42
  33. package/readme.md +6 -12
  34. package/types/assertions.d.cts +107 -49
  35. package/types/shared-worker.d.cts +0 -2
  36. package/types/state-change-events.d.cts +143 -0
  37. package/types/test-fn.d.cts +10 -5
  38. package/lib/worker/dependency-tracker.js +0 -48
  39. /package/entrypoints/{main.d.ts → main.d.mts} +0 -0
  40. /package/entrypoints/{plugin.d.ts → plugin.d.mts} +0 -0
@@ -25,7 +25,7 @@ class LineWriter extends stream.Writable {
25
25
  super();
26
26
 
27
27
  this.dest = dest;
28
- this.columns = dest.columns || 80;
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 || 100;
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.runVector > 1) {
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.lineWriter.writeLine(colors.stack(event.err.summary));
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.lineWriter.writeLine(colors.errorStack(event.err.stack));
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.writeErr(event);
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.writeErr(event);
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.writeErr(event);
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.writeErr(event);
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[event.chunk.length - 1] !== 0x0A) {
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[event.chunk.length - 1] !== 0x0A) {
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 = 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
- writeErr(event) {
431
- if (event.err.name === 'TSError' && event.err.object && event.err.object.diagnosticText) {
432
- this.lineWriter.writeLine(colors.errorStack(event.err.object.diagnosticText));
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 (event.err.source) {
438
- this.lineWriter.writeLine(colors.errorSource(`${this.relativeFile(event.err.source.file)}:${event.err.source.line}`));
439
- const excerpt = codeExcerpt(event.err.source, {maxWidth: this.reportStream.columns - 2});
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
- if (event.err.avaAssertionError) {
448
- const result = formatSerializedError(event.err);
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(event.err.message);
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 message = improperUsageMessage(event.err);
460
- if (message) {
461
- this.lineWriter.writeLine(message);
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
- const formatted = this.formatErrorStack(event.err);
473
- if (formatted.length > 0) {
474
- this.lineWriter.writeLine(formatted.join('\n'));
475
- this.lineWriter.writeLine();
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(error) {
480
- if (!error.stack) {
526
+ formatErrorStack(stack, hasSource) {
527
+ if (stack === '') {
481
528
  return [];
482
529
  }
483
530
 
484
- if (error.shouldBeautifyStack) {
485
- return beautifyStack(error.stack).map(line => {
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 [error.stack];
541
+ return [colors.errorStack(stack)];
495
542
  }
496
543
 
497
544
  writeLogs(event, surroundLines) {
498
- if (event.logs && event.logs.length > 0) {
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.writeErr(event);
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[this.failures.length - 1];
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(error) {
2
- const printMessage = error.values.length === 0
3
- ? Boolean(error.message)
4
- : !error.values[0].label.startsWith(error.message);
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 (error.values.length === 0) {
6
+ if (formattedDetails.length === 0) {
7
7
  return {formatted: null, printMessage};
8
8
  }
9
9
 
10
10
  let formatted = '';
11
- for (const value of error.values) {
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(error) {
5
- if (!error.improperUsage) {
4
+ export default function buildMessage(improperUsage) {
5
+ if (!improperUsage) {
6
6
  return null;
7
7
  }
8
8
 
9
- const {assertion} = error;
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} = error.improperUsage;
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} = error.improperUsage;
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.';
@@ -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(error) {
13
- const object = {...error.object};
14
- if (error.name) {
15
- object.name = error.name;
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
- if (error.message) {
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
- if (error.operator) {
28
- object.operator = error.operator;
29
+ if (type === 'ava') {
30
+ if (assertion) {
31
+ originalError.assertion = assertion;
29
32
  }
30
33
 
31
- if (error.values.length > 0) {
32
- object.values = Object.fromEntries(error.values.map(({label, formatted}) => [stripAnsi(label), stripAnsi(formatted)]));
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
- if (error.nonErrorObject) {
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 object;
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 || evt.err.summary || evt.type, {
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).replace(/^ {4}/gm, '# ');
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 || fallbackTitle,
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('dependency', snapshots.snapPath);
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('Hook failure', true, result.error),
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('Test failure', true, result.error, this.file),
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(path.join(cacheDir, FILENAME), JSON.stringify(runStatus.getFailedTestFiles()));
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