ava 6.0.1 → 6.1.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.
@@ -1,4 +1,4 @@
1
- import type {StateChangeEvent} from '../types/state-change-events.d';
1
+ import type {StateChangeEvent} from '../types/state-change-events.d.cts';
2
2
 
3
3
  export type Event = StateChangeEvent;
4
4
 
@@ -10,3 +10,11 @@ declare const test: TestFn;
10
10
 
11
11
  /** Call to declare a test, or chain to declare hooks or test modifiers */
12
12
  export default test;
13
+
14
+ /**
15
+ * Register a function to be called when AVA has completed a test run without uncaught exceptions or unhandled rejections.
16
+ *
17
+ * Completion handlers are invoked in order of registration. Results are not awaited.
18
+ */
19
+ declare const registerCompletionHandler: (handler: () => void) => void;
20
+ export {registerCompletionHandler};
@@ -1 +1,2 @@
1
1
  export {default} from '../lib/worker/main.cjs';
2
+ export {registerCompletionHandler} from '../lib/worker/completion-handlers.js';
package/lib/api.js CHANGED
@@ -303,7 +303,9 @@ export default class Api extends Emittery {
303
303
  // Allow shared workers to clean up before the run ends.
304
304
  await Promise.all(deregisteredSharedWorkers);
305
305
  const files = scheduler.storeFailedTestFiles(runStatus, this.options.cacheEnabled === false ? null : this._createCacheDir());
306
- runStatus.emitStateChange({type: 'touched-files', files});
306
+ if (files) {
307
+ runStatus.emitStateChange({type: 'touched-files', files});
308
+ }
307
309
  } catch (error) {
308
310
  runStatus.emitStateChange({type: 'internal-error', err: serializeError(error)});
309
311
  }
package/lib/assert.js CHANGED
@@ -626,13 +626,6 @@ export class Assertions {
626
626
  }));
627
627
  }
628
628
 
629
- if (message?.id !== undefined) {
630
- throw fail(new AssertionError('Since AVA 4, snapshot IDs are no longer supported', {
631
- assertion: 't.snapshot()',
632
- formattedDetails: [formatWithLabel('Called with id:', message.id)],
633
- }));
634
- }
635
-
636
629
  assertMessage(message, 't.snapshot()');
637
630
 
638
631
  if (message === '') {
package/lib/run-status.js CHANGED
@@ -38,6 +38,7 @@ export default class RunStatus extends Emittery {
38
38
  timeouts: 0,
39
39
  todoTests: 0,
40
40
  uncaughtExceptions: 0,
41
+ unexpectedProcessExits: 0,
41
42
  unhandledRejections: 0,
42
43
  };
43
44
  }
@@ -56,6 +57,7 @@ export default class RunStatus extends Emittery {
56
57
  skippedTests: 0,
57
58
  todoTests: 0,
58
59
  uncaughtExceptions: 0,
60
+ unexpectedProcessExits: 0,
59
61
  unhandledRejections: 0,
60
62
  ...stats,
61
63
  });
@@ -167,6 +169,8 @@ export default class RunStatus extends Emittery {
167
169
  }
168
170
 
169
171
  case 'process-exit': {
172
+ stats.unexpectedProcessExits++;
173
+ fileStats.unexpectedProcessExits++;
170
174
  event.pendingTests = this.pendingTests;
171
175
  event.pendingTestsLogs = this.pendingTestsLogs;
172
176
  this.pendingTests = new Map();
@@ -237,6 +241,7 @@ export default class RunStatus extends Emittery {
237
241
  || this.stats.sharedWorkerErrors > 0
238
242
  || this.stats.timeouts > 0
239
243
  || this.stats.uncaughtExceptions > 0
244
+ || this.stats.unexpectedProcessExits > 0
240
245
  || this.stats.unhandledRejections > 0
241
246
  ) {
242
247
  return 1;
package/lib/runner.js CHANGED
@@ -123,14 +123,10 @@ export default class Runner extends Emittery {
123
123
  todo: true,
124
124
  });
125
125
  } else {
126
- if (!implementation) {
126
+ if (typeof implementation !== 'function') {
127
127
  throw new TypeError('Expected an implementation. Use `test.todo()` for tests without an implementation.');
128
128
  }
129
129
 
130
- if (Array.isArray(implementation)) {
131
- throw new TypeError('AVA 4 no longer supports multiple implementations.');
132
- }
133
-
134
130
  if (title.isSet && !title.isValid) {
135
131
  throw new TypeError('Test & hook titles must be strings');
136
132
  }
package/lib/test.js CHANGED
@@ -99,14 +99,10 @@ class ExecutionContext extends Assertions {
99
99
 
100
100
  const {args, implementation, title} = parseTestArgs(attemptArgs);
101
101
 
102
- if (!implementation) {
102
+ if (typeof implementation !== 'function') {
103
103
  throw new TypeError('Expected an implementation.');
104
104
  }
105
105
 
106
- if (Array.isArray(implementation)) {
107
- throw new TypeError('AVA 4 no longer supports t.try() with multiple implementations.');
108
- }
109
-
110
106
  let attemptTitle;
111
107
  if (!title.isSet || title.isEmpty) {
112
108
  attemptTitle = `${test.title} ─ attempt ${test.attemptCount + 1}`;
package/lib/watcher.js CHANGED
@@ -20,7 +20,7 @@ const END_MESSAGE = chalk.gray('Type `r` and press enter to rerun tests\nType `u
20
20
 
21
21
  export function available(projectDir) {
22
22
  try {
23
- fs.watch(projectDir, {recursive: true, signal: AbortSignal.abort()});
23
+ fs.watch(projectDir, {persistent: false, recursive: true, signal: AbortSignal.abort()});
24
24
  } catch (error) {
25
25
  if (error.code === 'ERR_FEATURE_UNAVAILABLE_ON_PLATFORM') {
26
26
  return false;
@@ -15,6 +15,7 @@ import Runner from '../runner.js';
15
15
  import serializeError from '../serialize-error.js';
16
16
 
17
17
  import channel from './channel.cjs';
18
+ import {runCompletionHandlers} from './completion-handlers.js';
18
19
  import lineNumberSelection from './line-numbers.js';
19
20
  import {set as setOptions} from './options.cjs';
20
21
  import {flags, refs, sharedWorkerTeardowns} from './state.cjs';
@@ -23,17 +24,22 @@ import {isRunningInThread, isRunningInChildProcess} from './utils.cjs';
23
24
  const currentlyUnhandled = setUpCurrentlyUnhandled();
24
25
  let runner;
25
26
 
26
- let forcingExit = false;
27
+ let expectingExit = false;
27
28
 
28
29
  const forceExit = () => {
29
- forcingExit = true;
30
+ expectingExit = true;
30
31
  process.exit(1);
31
32
  };
32
33
 
34
+ const avaIsDone = () => {
35
+ expectingExit = true;
36
+ runCompletionHandlers();
37
+ };
38
+
33
39
  // Override process.exit with an undetectable replacement
34
40
  // to report when it is called from a test (which it should never be).
35
41
  const handleProcessExit = (target, thisArg, args) => {
36
- if (!forcingExit) {
42
+ if (!expectingExit) {
37
43
  const error = new Error('Unexpected process.exit()');
38
44
  Error.captureStackTrace(error, handleProcessExit);
39
45
  channel.send({type: 'process-exit', stack: error.stack});
@@ -118,7 +124,7 @@ const run = async options => {
118
124
  nowAndTimers.setImmediate(() => {
119
125
  const unhandled = currentlyUnhandled();
120
126
  if (unhandled.length === 0) {
121
- return;
127
+ return avaIsDone();
122
128
  }
123
129
 
124
130
  for (const rejection of unhandled) {
@@ -0,0 +1,13 @@
1
+ import process from 'node:process';
2
+
3
+ import state from './state.cjs';
4
+
5
+ export function runCompletionHandlers() {
6
+ for (const handler of state.completionHandlers) {
7
+ process.nextTick(() => handler());
8
+ }
9
+ }
10
+
11
+ export function registerCompletionHandler(handler) {
12
+ state.completionHandlers.push(handler);
13
+ }
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
  exports.flags = {loadedMain: false};
3
3
  exports.refs = {runnerChain: null};
4
+ exports.completionHandlers = [];
4
5
  exports.sharedWorkerTeardowns = [];
5
6
  exports.waitForReady = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ava",
3
- "version": "6.0.1",
3
+ "version": "6.1.0",
4
4
  "description": "Node.js test runner that lets you develop with confidence.",
5
5
  "license": "MIT",
6
6
  "repository": "avajs/ava",
package/readme.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # <img src="media/header.png" title="AVA" alt="AVA logo" width="530">
6
6
 
7
- AVA is a test runner for Node.js with a concise API, detailed error output, embrace of new language features and htread isolation that lets you develop with confidence 🚀
7
+ AVA is a test runner for Node.js with a concise API, detailed error output, embrace of new language features and thread isolation that lets you develop with confidence 🚀
8
8
 
9
9
  Watch this repository and follow the [Discussions](https://github.com/avajs/ava/discussions) for updates.
10
10
 
@@ -69,7 +69,7 @@ Alternatively you can install `ava` manually:
69
69
  npm install --save-dev ava
70
70
  ```
71
71
 
72
- *Make sure to install AVA locally. As of AVA 4 it can no longer be run globally.*
72
+ *Make sure to install AVA locally. AVA cannot be run globally.*
73
73
 
74
74
  Don't forget to configure the `test` script in your `package.json` as per above.
75
75