ava 4.0.1 → 4.3.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/eslint-plugin-helper.cjs +1 -1
- package/entrypoints/index.d.cts +2 -0
- package/entrypoints/plugin.d.cts +1 -0
- package/index.d.ts +5 -5
- package/lib/api.js +9 -3
- package/lib/assert.js +20 -2
- package/lib/cli.js +22 -8
- package/lib/create-chain.js +7 -5
- package/lib/eslint-plugin-helper-worker.js +1 -1
- package/lib/load-config.js +27 -6
- package/lib/reporters/default.js +8 -8
- package/lib/reporters/tap.js +1 -1
- package/lib/run-status.js +4 -1
- package/lib/runner.js +1 -1
- package/lib/test.js +6 -6
- package/package.json +48 -32
- package/plugin.d.ts +1 -1
- package/readme.md +10 -7
- package/types/assertions.d.ts +15 -3
- package/types/{subscribable.ts → subscribable.d.ts} +0 -0
- package/types/test-fn.d.ts +5 -5
- package/types/try-fn.d.ts +1 -1
|
@@ -90,7 +90,7 @@ function load(projectDir, overrides) {
|
|
|
90
90
|
|
|
91
91
|
const helper = Object.freeze({
|
|
92
92
|
classifyFile: classifyForESLint,
|
|
93
|
-
classifyImport
|
|
93
|
+
classifyImport(importPath) {
|
|
94
94
|
if (hasExtension(globs.extensions, importPath)) {
|
|
95
95
|
// The importPath has one of the test file extensions: we can classify
|
|
96
96
|
// it directly.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../plugin.js'
|
package/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {TestFn} from './types/test-fn';
|
|
1
|
+
import type {TestFn} from './types/test-fn.js';
|
|
2
2
|
|
|
3
|
-
export * from './types/assertions';
|
|
4
|
-
export * from './types/try-fn';
|
|
5
|
-
export * from './types/test-fn';
|
|
6
|
-
export * from './types/subscribable';
|
|
3
|
+
export * from './types/assertions.js';
|
|
4
|
+
export * from './types/try-fn.js';
|
|
5
|
+
export * from './types/test-fn.js';
|
|
6
|
+
export * from './types/subscribable.js';
|
|
7
7
|
|
|
8
8
|
/** Call to declare a test, or chain to declare hooks or test modifiers */
|
|
9
9
|
declare const test: TestFn;
|
package/lib/api.js
CHANGED
|
@@ -177,13 +177,19 @@ export default class Api extends Emittery {
|
|
|
177
177
|
const fileCount = selectedFiles.length;
|
|
178
178
|
|
|
179
179
|
// The files must be in the same order across all runs, so sort them.
|
|
180
|
-
|
|
180
|
+
const defaultComparator = (a, b) => a.localeCompare(b, [], {numeric: true});
|
|
181
|
+
selectedFiles = selectedFiles.sort(this.options.sortTestFiles || defaultComparator);
|
|
181
182
|
selectedFiles = chunkd(selectedFiles, currentIndex, totalRuns);
|
|
182
183
|
|
|
183
184
|
const currentFileCount = selectedFiles.length;
|
|
184
185
|
|
|
185
186
|
runStatus = new RunStatus(fileCount, {currentFileCount, currentIndex, totalRuns}, selectionInsights);
|
|
186
187
|
} else {
|
|
188
|
+
// If a custom sorter was configured, use it.
|
|
189
|
+
if (this.options.sortTestFiles) {
|
|
190
|
+
selectedFiles = selectedFiles.sort(this.options.sortTestFiles);
|
|
191
|
+
}
|
|
192
|
+
|
|
187
193
|
runStatus = new RunStatus(selectedFiles.length, null, selectionInsights);
|
|
188
194
|
}
|
|
189
195
|
|
|
@@ -261,8 +267,8 @@ export default class Api extends Emittery {
|
|
|
261
267
|
}
|
|
262
268
|
|
|
263
269
|
const lineNumbers = getApplicableLineNumbers(globs.normalizeFileForMatching(apiOptions.projectDir, file), filter);
|
|
264
|
-
// Removing `providers`
|
|
265
|
-
const {providers, ...forkOptions} = apiOptions;
|
|
270
|
+
// Removing `providers` and `sortTestFiles` fields because they cannot be transferred to the worker threads.
|
|
271
|
+
const {providers, sortTestFiles, ...forkOptions} = apiOptions;
|
|
266
272
|
const options = {
|
|
267
273
|
...forkOptions,
|
|
268
274
|
providerStates,
|
package/lib/assert.js
CHANGED
|
@@ -106,10 +106,15 @@ function validateExpectations(assertion, expectations, numberArgs) { // eslint-d
|
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
if (
|
|
109
|
+
if (
|
|
110
|
+
hasOwnProperty(expectations, 'message')
|
|
111
|
+
&& typeof expectations.message !== 'string'
|
|
112
|
+
&& !(expectations.message instanceof RegExp)
|
|
113
|
+
&& !(typeof expectations.message === 'function')
|
|
114
|
+
) {
|
|
110
115
|
throw new AssertionError({
|
|
111
116
|
assertion,
|
|
112
|
-
message: `The \`message\` property of the second argument to \`t.${assertion}()\` must be a string or
|
|
117
|
+
message: `The \`message\` property of the second argument to \`t.${assertion}()\` must be a string, regular expression or a function`,
|
|
113
118
|
values: [formatWithLabel('Called with:', expectations)],
|
|
114
119
|
});
|
|
115
120
|
}
|
|
@@ -230,6 +235,19 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
|
|
|
230
235
|
});
|
|
231
236
|
}
|
|
232
237
|
|
|
238
|
+
if (typeof expectations.message === 'function' && expectations.message(actual.message) === false) {
|
|
239
|
+
throw new AssertionError({
|
|
240
|
+
assertion,
|
|
241
|
+
message,
|
|
242
|
+
savedError,
|
|
243
|
+
actualStack,
|
|
244
|
+
values: [
|
|
245
|
+
formatWithLabel(`${prefix} unexpected exception:`, actual),
|
|
246
|
+
formatWithLabel('Expected message to return true:', expectations.message),
|
|
247
|
+
],
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
233
251
|
if (typeof expectations.code !== 'undefined' && actual.code !== expectations.code) {
|
|
234
252
|
throw new AssertionError({
|
|
235
253
|
assertion,
|
package/lib/cli.js
CHANGED
|
@@ -21,6 +21,7 @@ import {splitPatternAndLineNumbers} from './line-numbers.js';
|
|
|
21
21
|
import {loadConfig} from './load-config.js';
|
|
22
22
|
import normalizeModuleTypes from './module-types.js';
|
|
23
23
|
import normalizeNodeArguments from './node-arguments.js';
|
|
24
|
+
import pkg from './pkg.cjs';
|
|
24
25
|
import providerManager from './provider-manager.js';
|
|
25
26
|
import DefaultReporter from './reporters/default.js';
|
|
26
27
|
import TapReporter from './reporters/tap.js';
|
|
@@ -102,8 +103,15 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
102
103
|
let conf;
|
|
103
104
|
let confError;
|
|
104
105
|
try {
|
|
105
|
-
const {argv: {config: configFile}} = yargs(hideBin(process.argv)).help(false);
|
|
106
|
-
|
|
106
|
+
const {argv: {config: configFile}} = yargs(hideBin(process.argv)).help(false).version(false);
|
|
107
|
+
const loaded = await loadConfig({configFile});
|
|
108
|
+
if (loaded.unsupportedFiles.length > 0) {
|
|
109
|
+
console.log(chalk.magenta(
|
|
110
|
+
` ${figures.warning} AVA does not support JSON config, ignoring:\n\n ${loaded.unsupportedFiles.join('\n ')}`,
|
|
111
|
+
));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
conf = loaded.config;
|
|
107
115
|
if (conf.configFile && path.basename(conf.configFile) !== path.relative(conf.projectDir, conf.configFile)) {
|
|
108
116
|
console.log(chalk.magenta(` ${figures.warning} Using configuration from ${conf.configFile}`));
|
|
109
117
|
}
|
|
@@ -132,6 +140,7 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
132
140
|
|
|
133
141
|
let resetCache = false;
|
|
134
142
|
const {argv} = yargs(hideBin(process.argv))
|
|
143
|
+
.version(pkg.version)
|
|
135
144
|
.parserConfiguration({
|
|
136
145
|
'boolean-negation': true,
|
|
137
146
|
'camel-case-expansion': false,
|
|
@@ -161,7 +170,7 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
161
170
|
})
|
|
162
171
|
.command('* [<pattern>...]', 'Run tests', yargs => yargs.options(FLAGS).positional('pattern', {
|
|
163
172
|
array: true,
|
|
164
|
-
describe: 'Select which test files to run. Leave empty if you want AVA to run all test files as per your configuration. Accepts glob patterns, directories that (recursively) contain test files, and file paths
|
|
173
|
+
describe: 'Select which test files to run. Leave empty if you want AVA to run all test files as per your configuration. Accepts glob patterns, directories that (recursively) contain test files, and file paths optionally suffixed with a colon and comma-separated numbers and/or ranges identifying the 1-based line(s) of specific tests to run',
|
|
165
174
|
type: 'string',
|
|
166
175
|
}), argv => {
|
|
167
176
|
if (activeInspector) {
|
|
@@ -188,7 +197,7 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
188
197
|
},
|
|
189
198
|
}).positional('pattern', {
|
|
190
199
|
demand: true,
|
|
191
|
-
describe: 'Glob
|
|
200
|
+
describe: 'Glob pattern to select a single test file to debug, optionally suffixed with a colon and comma-separated numbers and/or ranges identifying the 1-based line(s) of specific tests to run',
|
|
192
201
|
type: 'string',
|
|
193
202
|
}),
|
|
194
203
|
argv => {
|
|
@@ -319,16 +328,20 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
319
328
|
exit('’sources’ has been removed. Use ’ignoredByWatcher’ to provide glob patterns of files that the watcher should ignore.');
|
|
320
329
|
}
|
|
321
330
|
|
|
322
|
-
|
|
331
|
+
if (Reflect.has(conf, 'sortTestFiles') && typeof conf.sortTestFiles !== 'function') {
|
|
332
|
+
exit('’sortTestFiles’ must be a comparator function.');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
let projectPackageObject;
|
|
323
336
|
try {
|
|
324
|
-
|
|
337
|
+
projectPackageObject = JSON.parse(fs.readFileSync(path.resolve(projectDir, 'package.json')));
|
|
325
338
|
} catch (error) {
|
|
326
339
|
if (error.code !== 'ENOENT') {
|
|
327
340
|
throw error;
|
|
328
341
|
}
|
|
329
342
|
}
|
|
330
343
|
|
|
331
|
-
const {type: defaultModuleType = 'commonjs'} =
|
|
344
|
+
const {type: defaultModuleType = 'commonjs'} = projectPackageObject || {};
|
|
332
345
|
|
|
333
346
|
const providers = [];
|
|
334
347
|
if (Reflect.has(conf, 'typescript')) {
|
|
@@ -380,7 +393,7 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
380
393
|
}
|
|
381
394
|
|
|
382
395
|
let parallelRuns = null;
|
|
383
|
-
if (isCi && ciParallelVars) {
|
|
396
|
+
if (isCi && ciParallelVars && combined.utilizeParallelBuilds !== false) {
|
|
384
397
|
const {index: currentIndex, total: totalRuns} = ciParallelVars;
|
|
385
398
|
parallelRuns = {currentIndex, totalRuns};
|
|
386
399
|
}
|
|
@@ -411,6 +424,7 @@ export default async function loadCli() { // eslint-disable-line complexity
|
|
|
411
424
|
moduleTypes,
|
|
412
425
|
nodeArguments,
|
|
413
426
|
parallelRuns,
|
|
427
|
+
sortTestFiles: conf.sortTestFiles,
|
|
414
428
|
projectDir,
|
|
415
429
|
providers,
|
|
416
430
|
ranFromCli: true,
|
package/lib/create-chain.js
CHANGED
|
@@ -101,11 +101,13 @@ export default function createChain(fn, defaults, meta) {
|
|
|
101
101
|
|
|
102
102
|
root.meta = meta;
|
|
103
103
|
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
104
|
+
// The ESM and CJS type definitions export the chain (`test()` function) as
|
|
105
|
+
// the default. TypeScript's CJS output (when `esModuleInterop` is disabled)
|
|
106
|
+
// assume `require('ava').default` is available. The same goes for `import ava
|
|
107
|
+
// = require('ava')` syntax.
|
|
108
|
+
//
|
|
109
|
+
// Add `test.default` to make this work. Use a proxy to avoid
|
|
110
|
+
// `test.default.default` chains.
|
|
109
111
|
Object.defineProperty(root, 'default', {
|
|
110
112
|
configurable: false,
|
|
111
113
|
enumerable: false,
|
|
@@ -41,7 +41,7 @@ const buildGlobs = ({conf, providers, projectDir, overrideExtensions, overrideFi
|
|
|
41
41
|
|
|
42
42
|
const resolveGlobs = async (projectDir, overrideExtensions, overrideFiles) => {
|
|
43
43
|
if (!configCache.has(projectDir)) {
|
|
44
|
-
configCache.set(projectDir, loadConfig({resolveFrom: projectDir}).then(async conf => {
|
|
44
|
+
configCache.set(projectDir, loadConfig({resolveFrom: projectDir}).then(async ({config: conf}) => {
|
|
45
45
|
const providers = await collectProviders({conf, projectDir});
|
|
46
46
|
return {conf, providers};
|
|
47
47
|
}));
|
package/lib/load-config.js
CHANGED
|
@@ -20,14 +20,15 @@ const importConfig = async ({configFile, fileForErrorMessage}) => {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
const loadConfigFile = async ({projectDir, configFile}) => {
|
|
23
|
-
if (!fs.existsSync(configFile)) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
23
|
const fileForErrorMessage = path.relative(projectDir, configFile);
|
|
28
24
|
try {
|
|
25
|
+
await fs.promises.access(configFile);
|
|
29
26
|
return {config: await importConfig({configFile, fileForErrorMessage}), configFile, fileForErrorMessage};
|
|
30
27
|
} catch (error) {
|
|
28
|
+
if (error.code === 'ENOENT') {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
31
32
|
throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {parent: error});
|
|
32
33
|
}
|
|
33
34
|
};
|
|
@@ -63,6 +64,20 @@ async function findRepoRoot(fromDir) {
|
|
|
63
64
|
return root;
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
async function checkJsonFile(searchDir) {
|
|
68
|
+
const file = path.join(searchDir, 'ava.config.json');
|
|
69
|
+
try {
|
|
70
|
+
await fs.promises.access(file);
|
|
71
|
+
return file;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (error.code === 'ENOENT') {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
66
81
|
export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) {
|
|
67
82
|
let packageConf = await packageConfig('ava', {cwd: resolveFrom});
|
|
68
83
|
const filepath = packageJsonPath(packageConf);
|
|
@@ -74,6 +89,7 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
|
|
|
74
89
|
const allowConflictWithPackageJson = Boolean(configFile);
|
|
75
90
|
configFile = resolveConfigFile(configFile);
|
|
76
91
|
|
|
92
|
+
const unsupportedFiles = [];
|
|
77
93
|
let fileConf = NO_SUCH_FILE;
|
|
78
94
|
let fileForErrorMessage;
|
|
79
95
|
let conflicting = [];
|
|
@@ -86,12 +102,17 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
|
|
|
86
102
|
let searchDir = projectDir;
|
|
87
103
|
const stopAt = path.dirname(repoRoot);
|
|
88
104
|
do {
|
|
89
|
-
const results = await Promise.all([ // eslint-disable-line no-await-in-loop
|
|
105
|
+
const [jsonFile, ...results] = await Promise.all([ // eslint-disable-line no-await-in-loop
|
|
106
|
+
checkJsonFile(searchDir),
|
|
90
107
|
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.js')}),
|
|
91
108
|
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.cjs')}),
|
|
92
109
|
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.mjs')}),
|
|
93
110
|
]);
|
|
94
111
|
|
|
112
|
+
if (jsonFile !== null) {
|
|
113
|
+
unsupportedFiles.push(jsonFile);
|
|
114
|
+
}
|
|
115
|
+
|
|
95
116
|
[{config: fileConf, fileForErrorMessage, configFile} = {config: NO_SUCH_FILE, fileForErrorMessage: undefined}, ...conflicting] = results.filter(result => result !== null);
|
|
96
117
|
|
|
97
118
|
searchDir = path.dirname(searchDir);
|
|
@@ -139,5 +160,5 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
|
|
|
139
160
|
}
|
|
140
161
|
}
|
|
141
162
|
|
|
142
|
-
return config;
|
|
163
|
+
return {config, unsupportedFiles};
|
|
143
164
|
}
|
package/lib/reporters/default.js
CHANGED
|
@@ -231,7 +231,7 @@ export default class Reporter {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
case 'hook-finished': {
|
|
234
|
-
if (
|
|
234
|
+
if (event.logs.length > 0) {
|
|
235
235
|
this.lineWriter.writeLine(` ${this.prefixTitle(event.testFile, event.title)}`);
|
|
236
236
|
this.writeLogs(event);
|
|
237
237
|
}
|
|
@@ -312,7 +312,7 @@ export default class Reporter {
|
|
|
312
312
|
this.filesWithoutMatchedLineNumbers.add(event.testFile);
|
|
313
313
|
|
|
314
314
|
this.lineWriter.writeLine(colors.error(`${figures.cross} Line numbers for ${this.relativeFile(event.testFile)} did not match any tests`));
|
|
315
|
-
} else if (
|
|
315
|
+
} else if (!this.failFastEnabled && fileStats.remainingTests > 0) {
|
|
316
316
|
this.lineWriter.writeLine(colors.error(`${figures.cross} ${fileStats.remainingTests} ${plur('test', fileStats.remainingTests)} remaining in ${this.relativeFile(event.testFile)}`));
|
|
317
317
|
}
|
|
318
318
|
}
|
|
@@ -515,7 +515,8 @@ export default class Reporter {
|
|
|
515
515
|
|
|
516
516
|
writeFailure(event) {
|
|
517
517
|
this.lineWriter.writeLine(colors.title(this.prefixTitle(event.testFile, event.title)));
|
|
518
|
-
|
|
518
|
+
|
|
519
|
+
if (!event.logs || event.logs.length === 0) {
|
|
519
520
|
this.lineWriter.writeLine();
|
|
520
521
|
}
|
|
521
522
|
|
|
@@ -570,17 +571,12 @@ export default class Reporter {
|
|
|
570
571
|
this.lineWriter.writeLine();
|
|
571
572
|
|
|
572
573
|
if (this.failures.length > 0) {
|
|
573
|
-
const writeTrailingLines = this.internalErrors.length > 0 || this.sharedWorkerErrors.length > 0 || this.uncaughtExceptions.length > 0 || this.unhandledRejections.length > 0;
|
|
574
|
-
|
|
575
574
|
const lastFailure = this.failures[this.failures.length - 1];
|
|
576
575
|
for (const event of this.failures) {
|
|
577
576
|
this.writeFailure(event);
|
|
578
577
|
if (event !== lastFailure) {
|
|
579
578
|
this.lineWriter.writeLine();
|
|
580
579
|
this.lineWriter.writeLine();
|
|
581
|
-
} else if (!true && writeTrailingLines) {
|
|
582
|
-
this.lineWriter.writeLine();
|
|
583
|
-
this.lineWriter.writeLine();
|
|
584
580
|
}
|
|
585
581
|
}
|
|
586
582
|
|
|
@@ -659,6 +655,10 @@ export default class Reporter {
|
|
|
659
655
|
this.lineWriter.writeLine(colors.error(`${this.stats.uncaughtExceptions} uncaught ${plur('exception', this.stats.uncaughtExceptions)}`));
|
|
660
656
|
}
|
|
661
657
|
|
|
658
|
+
if (this.stats.timeouts > 0) {
|
|
659
|
+
this.lineWriter.writeLine(colors.error(`${this.stats.timeouts} ${plur('test', this.stats.timeouts)} remained pending after a timeout`));
|
|
660
|
+
}
|
|
661
|
+
|
|
662
662
|
if (this.previousFailures > 0) {
|
|
663
663
|
this.lineWriter.writeLine(colors.error(`${this.previousFailures} previous ${plur('failure', this.previousFailures)} in test files that were not rerun`));
|
|
664
664
|
}
|
package/lib/reporters/tap.js
CHANGED
|
@@ -4,7 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import indentString from 'indent-string';
|
|
5
5
|
import plur from 'plur';
|
|
6
6
|
import stripAnsi from 'strip-ansi';
|
|
7
|
-
import supertap from 'supertap';
|
|
7
|
+
import * as supertap from 'supertap';
|
|
8
8
|
|
|
9
9
|
import beautifyStack from './beautify-stack.js';
|
|
10
10
|
import prefixTitle from './prefix-title.js';
|
package/lib/run-status.js
CHANGED
|
@@ -125,7 +125,10 @@ export default class RunStatus extends Emittery {
|
|
|
125
125
|
case 'timeout':
|
|
126
126
|
event.pendingTests = this.pendingTests;
|
|
127
127
|
this.pendingTests = new Map();
|
|
128
|
-
|
|
128
|
+
for (const testsInFile of event.pendingTests.values()) {
|
|
129
|
+
stats.timeouts += testsInFile.size;
|
|
130
|
+
}
|
|
131
|
+
|
|
129
132
|
break;
|
|
130
133
|
case 'interrupt':
|
|
131
134
|
event.pendingTests = this.pendingTests;
|
package/lib/runner.js
CHANGED
|
@@ -524,7 +524,7 @@ export default class Runner extends Emittery {
|
|
|
524
524
|
// If a concurrent test fails, even if `failFast` is enabled it won't
|
|
525
525
|
// stop other concurrent tests from running.
|
|
526
526
|
const allOkays = await Promise.all(concurrentTests.map(task => this.runTest(task, contextRef.copy())));
|
|
527
|
-
return allOkays.every(
|
|
527
|
+
return allOkays.every(Boolean);
|
|
528
528
|
});
|
|
529
529
|
|
|
530
530
|
const beforeExitHandler = this.beforeExitHandler.bind(this);
|
package/lib/test.js
CHANGED
|
@@ -24,16 +24,16 @@ const testMap = new WeakMap();
|
|
|
24
24
|
class ExecutionContext extends Assertions {
|
|
25
25
|
constructor(test) {
|
|
26
26
|
super({
|
|
27
|
-
pass
|
|
27
|
+
pass() {
|
|
28
28
|
test.countPassedAssertion();
|
|
29
29
|
},
|
|
30
|
-
pending
|
|
30
|
+
pending(promise) {
|
|
31
31
|
test.addPendingAssertion(promise);
|
|
32
32
|
},
|
|
33
|
-
fail
|
|
33
|
+
fail(error) {
|
|
34
34
|
test.addFailedAssertion(error);
|
|
35
35
|
},
|
|
36
|
-
skip
|
|
36
|
+
skip() {
|
|
37
37
|
test.countPassedAssertion();
|
|
38
38
|
},
|
|
39
39
|
compareWithSnapshot: options => test.compareWithSnapshot(options),
|
|
@@ -109,7 +109,7 @@ class ExecutionContext extends Assertions {
|
|
|
109
109
|
logs: [...logs], // Don't allow modification of logs.
|
|
110
110
|
passed,
|
|
111
111
|
title: attemptTitle,
|
|
112
|
-
commit
|
|
112
|
+
commit({retainLogs = true} = {}) {
|
|
113
113
|
if (committed) {
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
@@ -132,7 +132,7 @@ class ExecutionContext extends Assertions {
|
|
|
132
132
|
startingSnapshotCount,
|
|
133
133
|
});
|
|
134
134
|
},
|
|
135
|
-
discard
|
|
135
|
+
discard({retainLogs = false} = {}) {
|
|
136
136
|
if (committed) {
|
|
137
137
|
test.saveFirstError(new Error('Can’t discard a result that was previously committed'));
|
|
138
138
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ava",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "Node.js test runner that lets you develop with confidence.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "avajs/ava",
|
|
@@ -10,18 +10,30 @@
|
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
-
"import":
|
|
14
|
-
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./index.d.ts",
|
|
15
|
+
"default": "./entrypoints/main.mjs"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./entrypoints/index.d.cts",
|
|
19
|
+
"default": "./entrypoints/main.cjs"
|
|
20
|
+
}
|
|
15
21
|
},
|
|
16
22
|
"./eslint-plugin-helper": "./entrypoints/eslint-plugin-helper.cjs",
|
|
17
23
|
"./plugin": {
|
|
18
|
-
"import":
|
|
19
|
-
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./plugin.d.ts",
|
|
26
|
+
"default": "./entrypoints/plugin.mjs"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./entrypoints/plugin.d.cts",
|
|
30
|
+
"default": "./entrypoints/plugin.cjs"
|
|
31
|
+
}
|
|
20
32
|
}
|
|
21
33
|
},
|
|
22
34
|
"type": "module",
|
|
23
35
|
"engines": {
|
|
24
|
-
"node": ">=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=
|
|
36
|
+
"node": ">=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=18"
|
|
25
37
|
},
|
|
26
38
|
"scripts": {
|
|
27
39
|
"cover": "c8 --report=none test-ava && c8 --report=none --no-clean tap && c8 report",
|
|
@@ -70,40 +82,40 @@
|
|
|
70
82
|
"typescript"
|
|
71
83
|
],
|
|
72
84
|
"dependencies": {
|
|
73
|
-
"acorn": "^8.7.
|
|
85
|
+
"acorn": "^8.7.1",
|
|
74
86
|
"acorn-walk": "^8.2.0",
|
|
75
87
|
"ansi-styles": "^6.1.0",
|
|
76
88
|
"arrgv": "^1.0.2",
|
|
77
89
|
"arrify": "^3.0.0",
|
|
78
90
|
"callsites": "^4.0.0",
|
|
79
91
|
"cbor": "^8.1.0",
|
|
80
|
-
"chalk": "^5.0.
|
|
81
|
-
"chokidar": "^3.5.
|
|
92
|
+
"chalk": "^5.0.1",
|
|
93
|
+
"chokidar": "^3.5.3",
|
|
82
94
|
"chunkd": "^2.0.1",
|
|
83
|
-
"ci-info": "^3.3.
|
|
95
|
+
"ci-info": "^3.3.1",
|
|
84
96
|
"ci-parallel-vars": "^1.0.1",
|
|
85
97
|
"clean-yaml-object": "^0.1.0",
|
|
86
98
|
"cli-truncate": "^3.1.0",
|
|
87
|
-
"code-excerpt": "^
|
|
99
|
+
"code-excerpt": "^4.0.0",
|
|
88
100
|
"common-path-prefix": "^3.0.0",
|
|
89
101
|
"concordance": "^5.0.4",
|
|
90
102
|
"currently-unhandled": "^0.4.1",
|
|
91
|
-
"debug": "^4.3.
|
|
92
|
-
"del": "^6.
|
|
93
|
-
"emittery": "^0.
|
|
94
|
-
"figures": "^4.0.
|
|
95
|
-
"globby": "^
|
|
96
|
-
"ignore-by-default": "^2.
|
|
103
|
+
"debug": "^4.3.4",
|
|
104
|
+
"del": "^6.1.1",
|
|
105
|
+
"emittery": "^0.11.0",
|
|
106
|
+
"figures": "^4.0.1",
|
|
107
|
+
"globby": "^13.1.1",
|
|
108
|
+
"ignore-by-default": "^2.1.0",
|
|
97
109
|
"indent-string": "^5.0.0",
|
|
98
110
|
"is-error": "^2.2.2",
|
|
99
111
|
"is-plain-object": "^5.0.0",
|
|
100
112
|
"is-promise": "^4.0.0",
|
|
101
113
|
"matcher": "^5.0.0",
|
|
102
|
-
"mem": "^9.0.
|
|
114
|
+
"mem": "^9.0.2",
|
|
103
115
|
"ms": "^2.1.3",
|
|
104
116
|
"p-event": "^5.0.1",
|
|
105
|
-
"p-map": "^5.
|
|
106
|
-
"picomatch": "^2.3.
|
|
117
|
+
"p-map": "^5.4.0",
|
|
118
|
+
"picomatch": "^2.3.1",
|
|
107
119
|
"pkg-conf": "^4.0.0",
|
|
108
120
|
"plur": "^5.1.0",
|
|
109
121
|
"pretty-ms": "^7.0.1",
|
|
@@ -111,30 +123,30 @@
|
|
|
111
123
|
"slash": "^3.0.0",
|
|
112
124
|
"stack-utils": "^2.0.5",
|
|
113
125
|
"strip-ansi": "^7.0.1",
|
|
114
|
-
"supertap": "^
|
|
126
|
+
"supertap": "^3.0.1",
|
|
115
127
|
"temp-dir": "^2.0.0",
|
|
116
|
-
"write-file-atomic": "^
|
|
117
|
-
"yargs": "^17.
|
|
128
|
+
"write-file-atomic": "^4.0.1",
|
|
129
|
+
"yargs": "^17.5.1"
|
|
118
130
|
},
|
|
119
131
|
"devDependencies": {
|
|
120
132
|
"@ava/test": "github:avajs/test",
|
|
121
133
|
"@ava/typescript": "^3.0.1",
|
|
122
|
-
"@sinonjs/fake-timers": "^
|
|
134
|
+
"@sinonjs/fake-timers": "^9.1.2",
|
|
123
135
|
"ansi-escapes": "^5.0.0",
|
|
124
|
-
"c8": "^7.11.
|
|
136
|
+
"c8": "^7.11.3",
|
|
125
137
|
"delay": "^5.0.0",
|
|
126
|
-
"execa": "^6.
|
|
127
|
-
"fs-extra": "^10.
|
|
138
|
+
"execa": "^6.1.0",
|
|
139
|
+
"fs-extra": "^10.1.0",
|
|
128
140
|
"get-stream": "^6.0.1",
|
|
129
141
|
"replace-string": "^4.0.0",
|
|
130
|
-
"sinon": "^
|
|
131
|
-
"tap": "^
|
|
142
|
+
"sinon": "^13.0.2",
|
|
143
|
+
"tap": "^16.2.0",
|
|
132
144
|
"temp-write": "^5.0.0",
|
|
133
145
|
"tempy": "^2.0.0",
|
|
134
146
|
"touch": "^3.1.0",
|
|
135
|
-
"tsd": "^0.
|
|
136
|
-
"typescript": "^4.
|
|
137
|
-
"xo": "^0.
|
|
147
|
+
"tsd": "^0.20.0",
|
|
148
|
+
"typescript": "^4.7.2",
|
|
149
|
+
"xo": "^0.49.0",
|
|
138
150
|
"zen-observable": "^0.8.15"
|
|
139
151
|
},
|
|
140
152
|
"peerDependencies": {
|
|
@@ -144,5 +156,9 @@
|
|
|
144
156
|
"@ava/typescript": {
|
|
145
157
|
"optional": true
|
|
146
158
|
}
|
|
159
|
+
},
|
|
160
|
+
"volta": {
|
|
161
|
+
"node": "18.3.0",
|
|
162
|
+
"npm": "8.12.0"
|
|
147
163
|
}
|
|
148
164
|
}
|
package/plugin.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export namespace SharedWorker {
|
|
|
41
41
|
readonly file: string;
|
|
42
42
|
publish: (data: Data) => PublishedMessage<Data>;
|
|
43
43
|
subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
|
|
44
|
-
teardown:
|
|
44
|
+
teardown: (fn: (() => Promise<void>) | (() => void)) => () => Promise<void>;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
export namespace Plugin {
|
package/readme.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](https://vshymanskyy.github.io/StandWithUkraine/)
|
|
2
|
+
|
|
1
3
|
# <img src="media/header.png" title="AVA" alt="AVA logo" width="530">
|
|
2
4
|
|
|
3
5
|
AVA is a test runner for Node.js with a concise API, detailed error output, embrace of new language features and process isolation that lets you develop with confidence 🚀
|
|
@@ -9,7 +11,7 @@ Read our [contributing guide](.github/CONTRIBUTING.md) if you're looking to cont
|
|
|
9
11
|

|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
Translations: [Español](https://github.com/avajs/ava-docs/blob/
|
|
14
|
+
Translations: [Español](https://github.com/avajs/ava-docs/blob/main/es_ES/readme.md), [Français](https://github.com/avajs/ava-docs/blob/main/fr_FR/readme.md), [Italiano](https://github.com/avajs/ava-docs/blob/main/it_IT/readme.md), [日本語](https://github.com/avajs/ava-docs/blob/main/ja_JP/readme.md), [한국어](https://github.com/avajs/ava-docs/blob/main/ko_KR/readme.md), [Português](https://github.com/avajs/ava-docs/blob/main/pt_BR/readme.md), [Русский](https://github.com/avajs/ava-docs/blob/main/ru_RU/readme.md), [简体中文](https://github.com/avajs/ava-docs/blob/main/zh_CN/readme.md)
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
## Why AVA?
|
|
@@ -71,7 +73,7 @@ Don't forget to configure the `test` script in your `package.json` as per above.
|
|
|
71
73
|
Create a file named `test.js` in the project root directory:
|
|
72
74
|
|
|
73
75
|
```js
|
|
74
|
-
|
|
76
|
+
import test from 'ava';
|
|
75
77
|
|
|
76
78
|
test('foo', t => {
|
|
77
79
|
t.pass();
|
|
@@ -139,15 +141,16 @@ We have a growing list of [common pitfalls](docs/08-common-pitfalls.md) you may
|
|
|
139
141
|
|
|
140
142
|
### Recipes
|
|
141
143
|
|
|
142
|
-
- [Shared workers](docs/recipes/shared-workers.md)
|
|
143
144
|
- [Test setup](docs/recipes/test-setup.md)
|
|
144
|
-
- [
|
|
145
|
+
- [TypeScript](docs/recipes/typescript.md)
|
|
146
|
+
- [Shared workers](docs/recipes/shared-workers.md)
|
|
145
147
|
- [Watch mode](docs/recipes/watch-mode.md)
|
|
146
|
-
- [Endpoint testing](docs/recipes/endpoint-testing.md)
|
|
147
148
|
- [When to use `t.plan()`](docs/recipes/when-to-use-plan.md)
|
|
148
|
-
- [Browser testing](docs/recipes/browser-testing.md)
|
|
149
|
-
- [TypeScript](docs/recipes/typescript.md)
|
|
150
149
|
- [Passing arguments to your test files](docs/recipes/passing-arguments-to-your-test-files.md)
|
|
150
|
+
- [Splitting tests in CI](docs/recipes/splitting-tests-ci.md)
|
|
151
|
+
- [Code coverage](docs/recipes/code-coverage.md)
|
|
152
|
+
- [Endpoint testing](docs/recipes/endpoint-testing.md)
|
|
153
|
+
- [Browser testing](docs/recipes/browser-testing.md)
|
|
151
154
|
- [Testing Vue.js components](docs/recipes/vue.md)
|
|
152
155
|
- [Debugging tests with Chrome DevTools](docs/recipes/debugging-with-chrome-devtools.md)
|
|
153
156
|
- [Debugging tests with VSCode](docs/recipes/debugging-with-vscode.md)
|
package/types/assertions.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type ThrowsExpectation = {
|
|
|
12
12
|
is?: Error;
|
|
13
13
|
|
|
14
14
|
/** The thrown error must have a message that equals the given string, or matches the regular expression. */
|
|
15
|
-
message?: string | RegExp;
|
|
15
|
+
message?: string | RegExp | ((message: string) => boolean);
|
|
16
16
|
|
|
17
17
|
/** The thrown error must have a name that equals the given string. */
|
|
18
18
|
name?: string;
|
|
@@ -138,6 +138,18 @@ export interface DeepEqualAssertion {
|
|
|
138
138
|
*/
|
|
139
139
|
<Actual, Expected extends Actual>(actual: Actual, expected: Expected, message?: string): actual is Expected;
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
|
|
143
|
+
* `expected`, returning a boolean indicating whether the assertion passed.
|
|
144
|
+
*/
|
|
145
|
+
<Actual extends Expected, Expected>(actual: Actual, expected: Expected, message?: string): expected is Actual;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
|
|
149
|
+
* `expected`, returning a boolean indicating whether the assertion passed.
|
|
150
|
+
*/
|
|
151
|
+
<Actual, Expected>(actual: Actual, expected: Expected, message?: string): boolean;
|
|
152
|
+
|
|
141
153
|
/** Skip this assertion. */
|
|
142
154
|
skip(actual: any, expected: any, message?: string): void;
|
|
143
155
|
}
|
|
@@ -240,7 +252,7 @@ export interface NotThrowsAsyncAssertion {
|
|
|
240
252
|
(fn: () => PromiseLike<any>, message?: string): Promise<void>;
|
|
241
253
|
|
|
242
254
|
/** Assert that the promise does not reject. You must await the result. */
|
|
243
|
-
(promise: PromiseLike<any>, message?: string): Promise<void>;
|
|
255
|
+
(promise: PromiseLike<any>, message?: string): Promise<void>;
|
|
244
256
|
|
|
245
257
|
/** Skip this assertion. */
|
|
246
258
|
skip(nonThrower: any, message?: string): void;
|
|
@@ -299,7 +311,7 @@ export interface ThrowsAsyncAssertion {
|
|
|
299
311
|
* rejection reason. Returns undefined when the assertion fails. You must await the result. The error must satisfy all
|
|
300
312
|
* expectations.
|
|
301
313
|
*/
|
|
302
|
-
<ThrownError extends Error>(promise: PromiseLike<any>, expectations?: ThrowsExpectation, message?: string): Promise<ThrownError | undefined>;
|
|
314
|
+
<ThrownError extends Error>(promise: PromiseLike<any>, expectations?: ThrowsExpectation, message?: string): Promise<ThrownError | undefined>;
|
|
303
315
|
|
|
304
316
|
/** Skip this assertion. */
|
|
305
317
|
skip(thrower: any, expectations?: any, message?: string): void;
|
|
File without changes
|
package/types/test-fn.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {Assertions} from './assertions';
|
|
2
|
-
import type {Subscribable} from './subscribable';
|
|
3
|
-
import type {TryFn} from './try-fn';
|
|
1
|
+
import type {Assertions} from './assertions.js';
|
|
2
|
+
import type {Subscribable} from './subscribable.js';
|
|
3
|
+
import type {TryFn} from './try-fn.js';
|
|
4
4
|
|
|
5
5
|
/** The `t` value passed to test & hook implementations. */
|
|
6
6
|
export interface ExecutionContext<Context = unknown> extends Assertions {
|
|
@@ -46,7 +46,7 @@ export interface PlanFn {
|
|
|
46
46
|
export type TimeoutFn = (ms: number, message?: string) => void;
|
|
47
47
|
|
|
48
48
|
/** Declare a function to be run after the test has ended. */
|
|
49
|
-
export type TeardownFn = (fn: () => void) => void;
|
|
49
|
+
export type TeardownFn = (fn: (() => Promise<void>) | (() => void)) => void;
|
|
50
50
|
|
|
51
51
|
export type ImplementationFn<Args extends unknown[], Context = unknown> =
|
|
52
52
|
((t: ExecutionContext<Context>, ...args: Args) => PromiseLike<void>) |
|
|
@@ -219,7 +219,7 @@ export type MacroDeclarationOptions<Args extends unknown[], Context = unknown> =
|
|
|
219
219
|
export interface MacroFn<Context = unknown> {
|
|
220
220
|
/** Declare a reusable test implementation. */
|
|
221
221
|
<Args extends unknown[]>(/** The function that is executed when the macro is used. */ exec: ImplementationFn<Args, Context>): Macro<Args, Context>;
|
|
222
|
-
<Args extends unknown[]>(declaration: MacroDeclarationOptions<Args, Context>): Macro<Args, Context>;
|
|
222
|
+
<Args extends unknown[]>(declaration: MacroDeclarationOptions<Args, Context>): Macro<Args, Context>;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
export interface Meta {
|
package/types/try-fn.d.ts
CHANGED