ava 6.0.1 → 6.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/internal.d.mts +1 -1
- package/entrypoints/main.d.mts +8 -0
- package/entrypoints/main.mjs +1 -0
- package/lib/api.js +3 -1
- package/lib/assert.js +0 -7
- package/lib/run-status.js +5 -0
- package/lib/runner.js +1 -5
- package/lib/test.js +1 -5
- package/lib/watcher.js +3 -2
- package/lib/worker/base.js +10 -4
- package/lib/worker/completion-handlers.js +13 -0
- package/lib/worker/state.cjs +1 -0
- package/package.json +11 -11
- package/readme.md +2 -2
package/entrypoints/main.d.mts
CHANGED
|
@@ -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};
|
package/entrypoints/main.mjs
CHANGED
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
|
-
|
|
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 (
|
|
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 (
|
|
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;
|
|
@@ -106,7 +106,8 @@ async function * plan({api, filter, globs, projectDir, providers, stdin, abortSi
|
|
|
106
106
|
case 'uncaught-exception':
|
|
107
107
|
case 'unhandled-rejection':
|
|
108
108
|
case 'worker-failed': {
|
|
109
|
-
|
|
109
|
+
const path = nodePath.relative(projectDir, evt.testFile);
|
|
110
|
+
failureCounts.set(path, 1 + (failureCounts.get(path) ?? 0));
|
|
110
111
|
break;
|
|
111
112
|
}
|
|
112
113
|
|
package/lib/worker/base.js
CHANGED
|
@@ -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
|
|
27
|
+
let expectingExit = false;
|
|
27
28
|
|
|
28
29
|
const forceExit = () => {
|
|
29
|
-
|
|
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 (!
|
|
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
|
+
}
|
package/lib/worker/state.cjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ava",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "Node.js test runner that lets you develop with confidence.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "avajs/ava",
|
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
"typescript"
|
|
84
84
|
],
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@vercel/nft": "^0.
|
|
87
|
-
"acorn": "^8.11.
|
|
88
|
-
"acorn-walk": "^8.3.
|
|
86
|
+
"@vercel/nft": "^0.26.2",
|
|
87
|
+
"acorn": "^8.11.3",
|
|
88
|
+
"acorn-walk": "^8.3.2",
|
|
89
89
|
"ansi-styles": "^6.2.1",
|
|
90
90
|
"arrgv": "^1.0.2",
|
|
91
91
|
"arrify": "^3.0.0",
|
|
@@ -111,11 +111,11 @@
|
|
|
111
111
|
"matcher": "^5.0.0",
|
|
112
112
|
"memoize": "^10.0.0",
|
|
113
113
|
"ms": "^2.1.3",
|
|
114
|
-
"p-map": "^
|
|
114
|
+
"p-map": "^7.0.1",
|
|
115
115
|
"package-config": "^5.0.0",
|
|
116
116
|
"picomatch": "^3.0.1",
|
|
117
117
|
"plur": "^5.1.0",
|
|
118
|
-
"pretty-ms": "^
|
|
118
|
+
"pretty-ms": "^9.0.0",
|
|
119
119
|
"resolve-cwd": "^3.0.0",
|
|
120
120
|
"stack-utils": "^2.0.6",
|
|
121
121
|
"strip-ansi": "^7.1.0",
|
|
@@ -128,16 +128,16 @@
|
|
|
128
128
|
"@ava/test": "github:avajs/test",
|
|
129
129
|
"@ava/typescript": "^4.1.0",
|
|
130
130
|
"@sindresorhus/tsconfig": "^5.0.0",
|
|
131
|
-
"@types/node": "^20.10
|
|
131
|
+
"@types/node": "^20.11.10",
|
|
132
132
|
"ansi-escapes": "^6.2.0",
|
|
133
|
-
"c8": "^
|
|
133
|
+
"c8": "^9.1.0",
|
|
134
134
|
"execa": "^8.0.1",
|
|
135
135
|
"expect": "^29.7.0",
|
|
136
136
|
"sinon": "^17.0.1",
|
|
137
|
-
"tap": "^18.
|
|
137
|
+
"tap": "^18.7.0",
|
|
138
138
|
"tempy": "^3.1.0",
|
|
139
|
-
"tsd": "^0.
|
|
140
|
-
"typescript": "~5.3.
|
|
139
|
+
"tsd": "^0.30.4",
|
|
140
|
+
"typescript": "~5.3.3",
|
|
141
141
|
"xo": "^0.56.0",
|
|
142
142
|
"zen-observable": "^0.10.0"
|
|
143
143
|
},
|
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
|
|
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.
|
|
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
|
|