ava 4.3.3 → 5.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.
@@ -0,0 +1,2 @@
1
+ export {default} from './main.js';
2
+ export * from './main.js';
@@ -0,0 +1,12 @@
1
+ import type {TestFn} from '../types/test-fn.js';
2
+
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
+
8
+ /** Call to declare a test, or chain to declare hooks or test modifiers */
9
+ declare const test: TestFn;
10
+
11
+ /** Call to declare a test, or chain to declare hooks or test modifiers */
12
+ export default test;
@@ -1 +1 @@
1
- export * from '../plugin.js'
1
+ export * from './plugin.js'
@@ -1,4 +1,4 @@
1
- import {URL} from 'node:url';
1
+ import type {URL} from 'node:url';
2
2
 
3
3
  export namespace SharedWorker {
4
4
  export type ProtocolIdentifier = 'ava-4';
package/lib/api.js CHANGED
@@ -246,14 +246,16 @@ export default class Api extends Emittery {
246
246
  }
247
247
  }));
248
248
 
249
- // Resolve the correct concurrency value.
250
- let concurrency = Math.min(os.cpus().length, isCi ? 2 : Number.POSITIVE_INFINITY);
251
- if (apiOptions.concurrency > 0) {
252
- concurrency = apiOptions.concurrency;
253
- }
254
-
249
+ // Resolve the correct concurrency value. Note that `os.cpus()` can return empty arrays on
250
+ // platforms not officially supported by Node.js. Use 1 as a minimum.
251
+ // See <https://github.com/nodejs/node/issues/38190>.
252
+ let concurrency = Math.max(1, os.cpus().length);
255
253
  if (apiOptions.serial) {
256
254
  concurrency = 1;
255
+ } else if (apiOptions.concurrency > 0) {
256
+ concurrency = apiOptions.concurrency;
257
+ } else if (isCi) {
258
+ concurrency = 2;
257
259
  }
258
260
 
259
261
  const deregisteredSharedWorkers = [];
package/lib/assert.js CHANGED
@@ -8,8 +8,10 @@ import {SnapshotError, VersionMismatchError} from './snapshot-manager.js';
8
8
 
9
9
  function formatDescriptorDiff(actualDescriptor, expectedDescriptor, options) {
10
10
  options = {...options, ...concordanceOptions};
11
+ const {diffGutters} = options.theme;
12
+ const {insertLine, deleteLine} = options.theme.string.diff;
11
13
  return {
12
- label: 'Difference:',
14
+ label: `Difference (${diffGutters.actual}${deleteLine.open}actual${deleteLine.close}, ${diffGutters.expected}${insertLine.open}expected${insertLine.close}):`,
13
15
  formatted: concordance.diffDescriptors(actualDescriptor, expectedDescriptor, options),
14
16
  };
15
17
  }
package/lib/cli.js CHANGED
@@ -5,10 +5,10 @@ import process from 'node:process';
5
5
 
6
6
  import arrify from 'arrify';
7
7
  import ciParallelVars from 'ci-parallel-vars';
8
- import del from 'del';
8
+ import {deleteAsync} from 'del';
9
9
  import figures from 'figures';
10
10
  import yargs from 'yargs';
11
- import {hideBin} from 'yargs/helpers'; // eslint-disable-line node/file-extension-in-import
11
+ import {hideBin} from 'yargs/helpers'; // eslint-disable-line n/file-extension-in-import
12
12
 
13
13
  import Api from './api.js';
14
14
  import {chalk} from './chalk.js';
@@ -124,7 +124,7 @@ export default async function loadCli() { // eslint-disable-line complexity
124
124
  // run AVA with the debug command, though it's allowed.
125
125
  let activeInspector = false;
126
126
  try {
127
- const {default: inspector} = await import('node:inspector'); // eslint-disable-line node/no-unsupported-features/es-syntax
127
+ const {default: inspector} = await import('node:inspector');
128
128
 
129
129
  activeInspector = inspector.url() !== undefined;
130
130
  } catch {}
@@ -242,11 +242,11 @@ export default async function loadCli() { // eslint-disable-line complexity
242
242
 
243
243
  const chalkOptions = {level: 0};
244
244
  if (combined.color !== false) {
245
- const {supportsColor: {level}} = await import('chalk'); // eslint-disable-line node/no-unsupported-features/es-syntax, unicorn/import-style
245
+ const {supportsColor: {level}} = await import('chalk'); // eslint-disable-line unicorn/import-style
246
246
  chalkOptions.level = level;
247
247
  }
248
248
 
249
- const {set: setChalk} = await import('./chalk.js'); // eslint-disable-line node/no-unsupported-features/es-syntax
249
+ const {set: setChalk} = await import('./chalk.js');
250
250
  setChalk(chalkOptions);
251
251
 
252
252
  if (confError) {
@@ -262,7 +262,7 @@ export default async function loadCli() { // eslint-disable-line complexity
262
262
  const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'ava');
263
263
 
264
264
  try {
265
- const deletedFilePaths = await del('*', {cwd: cacheDir});
265
+ const deletedFilePaths = await deleteAsync('*', {cwd: cacheDir});
266
266
 
267
267
  if (deletedFilePaths.length === 0) {
268
268
  console.log(`\n${chalk.green(figures.tick)} No cache files to remove`);
@@ -43,7 +43,7 @@ export default function exceptCode(source, options = {}) {
43
43
  const coloredLineNumber = isErrorSource ? lineNumber : chalk.grey(lineNumber);
44
44
  const result = ` ${coloredLineNumber} ${item.value.padEnd(extendedWidth)}`;
45
45
 
46
- return isErrorSource ? chalk.bgRed(result) : result;
46
+ return isErrorSource ? chalk.bgRed.bold(result) : result;
47
47
  })
48
48
  .join('\n');
49
49
  }
@@ -85,7 +85,7 @@ const colorTheme = {
85
85
  undefined: ansiStyles.yellow,
86
86
  };
87
87
 
88
- const plainTheme = JSON.parse(JSON.stringify(colorTheme), value => typeof value === 'string' ? stripAnsi(value) : value);
88
+ const plainTheme = JSON.parse(JSON.stringify(colorTheme), (_name, value) => typeof value === 'string' ? stripAnsi(value) : value);
89
89
 
90
90
  const theme = chalk.level > 0 ? colorTheme : plainTheme;
91
91
 
@@ -11,7 +11,7 @@ const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
11
11
  const EXPERIMENTS = new Set();
12
12
 
13
13
  const importConfig = async ({configFile, fileForErrorMessage}) => {
14
- const {default: config = MISSING_DEFAULT_EXPORT} = await import(url.pathToFileURL(configFile)); // eslint-disable-line node/no-unsupported-features/es-syntax
14
+ const {default: config = MISSING_DEFAULT_EXPORT} = await import(url.pathToFileURL(configFile));
15
15
  if (config === MISSING_DEFAULT_EXPORT) {
16
16
  throw new Error(`${fileForErrorMessage} must have a default export`);
17
17
  }
@@ -156,7 +156,7 @@ function broadcastMessage(data) {
156
156
  }
157
157
 
158
158
  async function loadFactory() {
159
- const {default: factory} = await import(workerData.filename); // eslint-disable-line node/no-unsupported-features/es-syntax
159
+ const {default: factory} = await import(workerData.filename);
160
160
  return factory;
161
161
  }
162
162
 
@@ -15,7 +15,7 @@ const levelsByProtocol = {
15
15
 
16
16
  async function load(providerModule, projectDir) {
17
17
  const ava = {version: pkg.version};
18
- const {default: makeProvider} = await import(providerModule); // eslint-disable-line node/no-unsupported-features/es-syntax
18
+ const {default: makeProvider} = await import(providerModule);
19
19
 
20
20
  let fatal;
21
21
  let level;
@@ -233,6 +233,16 @@ export default class Reporter {
233
233
  break;
234
234
  }
235
235
 
236
+ case 'process-exit': {
237
+ this.write(colors.error(`${figures.cross} Exiting due to process.exit() when running ${this.relativeFile(event.testFile)}`));
238
+
239
+ this.lineWriter.writeLine();
240
+ this.lineWriter.writeLine(colors.errorStack(event.stack));
241
+ this.lineWriter.writeLine();
242
+
243
+ break;
244
+ }
245
+
236
246
  case 'hook-finished': {
237
247
  if (event.logs.length > 0) {
238
248
  this.lineWriter.writeLine(` ${this.prefixTitle(event.testFile, event.title)}`);
@@ -244,9 +254,9 @@ export default class Reporter {
244
254
 
245
255
  case 'selected-test': {
246
256
  if (event.skip) {
247
- this.lineWriter.writeLine(colors.skip(`- ${this.prefixTitle(event.testFile, event.title)}`));
257
+ this.lineWriter.writeLine(colors.skip(`- [skip] ${this.prefixTitle(event.testFile, event.title)}`));
248
258
  } else if (event.todo) {
249
- this.lineWriter.writeLine(colors.todo(`- ${this.prefixTitle(event.testFile, event.title)}`));
259
+ this.lineWriter.writeLine(colors.todo(`- [todo] ${this.prefixTitle(event.testFile, event.title)}`));
250
260
  }
251
261
 
252
262
  break;
@@ -504,15 +514,30 @@ export default class Reporter {
504
514
  }
505
515
 
506
516
  writeTestSummary(event) {
517
+ // Prefix icon indicates matched expectations vs. not.
518
+ // Prefix color indicates passed-as-expected vs. not (fail or unexpected pass).
519
+ // This yields four possibilities, which in the standard configuration render as:
520
+ // * normal test, pass: <green>✔</green>
521
+ // * normal test, fail: <red>✘ [fail]</red>
522
+ // * fail-expected test, fail: <red>✔ [expected fail]</red>
523
+ // * fail-expected test, pass: <red>✘ [unexpected pass]</red>
524
+ let prefix;
525
+ let suffix;
507
526
  if (event.type === 'hook-failed' || event.type === 'test-failed') {
508
- this.write(`${colors.error(figures.cross)} ${this.prefixTitle(event.testFile, event.title)} ${colors.error(event.err.message)}`);
527
+ const type = event.knownFailing ? '[unexpected pass]' : '[fail]';
528
+ prefix = colors.error(`${figures.cross} ${type}:`);
529
+ suffix = chalk.italic(colors.error(event.err.message));
509
530
  } else if (event.knownFailing) {
510
- this.write(`${colors.error(figures.tick)} ${colors.error(this.prefixTitle(event.testFile, event.title))}`);
531
+ prefix = colors.error(figures.tick + ' [expected fail]');
511
532
  } else {
512
- const duration = event.duration > this.durationThreshold ? colors.duration(' (' + prettyMs(event.duration) + ')') : '';
513
- this.write(`${colors.pass(figures.tick)} ${this.prefixTitle(event.testFile, event.title)}${duration}`);
533
+ prefix = colors.pass(figures.tick);
534
+ if (event.duration > this.durationThreshold) {
535
+ suffix = colors.duration(`(${prettyMs(event.duration)})`);
536
+ }
514
537
  }
515
538
 
539
+ const label = this.prefixTitle(event.testFile, event.title);
540
+ this.write(`${prefix} ${label}${suffix ? ' ' + suffix : ''}`);
516
541
  this.writeLogs(event);
517
542
  }
518
543
 
@@ -658,8 +683,8 @@ export default class Reporter {
658
683
  this.lineWriter.writeLine(colors.error(`${this.stats.uncaughtExceptions} uncaught ${plur('exception', this.stats.uncaughtExceptions)}`));
659
684
  }
660
685
 
661
- if (this.stats.timeouts > 0) {
662
- this.lineWriter.writeLine(colors.error(`${this.stats.timeouts} ${plur('test', this.stats.timeouts)} remained pending after a timeout`));
686
+ if (this.stats.timedOutTests > 0) {
687
+ this.lineWriter.writeLine(colors.error(`${this.stats.timedOutTests} ${plur('test', this.stats.timedOutTests)} remained pending after a timeout`));
663
688
  }
664
689
 
665
690
  if (this.previousFailures > 0) {
@@ -29,7 +29,7 @@ function dumpError(error) {
29
29
  }
30
30
 
31
31
  if (error.values.length > 0) {
32
- object.values = Object.fromEntries(error.values.map(({label, formatted}) => [label, stripAnsi(formatted)]));
32
+ object.values = Object.fromEntries(error.values.map(({label, formatted}) => [stripAnsi(label), stripAnsi(formatted)]));
33
33
  }
34
34
  }
35
35
 
@@ -128,6 +128,17 @@ export default class TapReporter {
128
128
  }
129
129
  }
130
130
 
131
+ writeProcessExit(evt) {
132
+ const error = new Error(`Exiting due to process.exit() when running ${this.relativeFile(evt.testFile)}`);
133
+ error.stack = evt.stack;
134
+
135
+ for (const [testFile, tests] of evt.pendingTests) {
136
+ for (const title of tests) {
137
+ this.writeTest({testFile, title, err: error}, {passed: false, todo: false, skip: false});
138
+ }
139
+ }
140
+ }
141
+
131
142
  writeTimeout(evt) {
132
143
  const error = new Error(`Exited because no new tests completed within the last ${evt.period}ms of inactivity`);
133
144
 
@@ -158,6 +169,9 @@ export default class TapReporter {
158
169
  this.filesWithMissingAvaImports.add(evt.testFile);
159
170
  this.writeCrash(evt, `No tests found in ${this.relativeFile(evt.testFile)}, make sure to import "ava" at the top of your test file`);
160
171
  break;
172
+ case 'process-exit':
173
+ this.writeProcessExit(evt);
174
+ break;
161
175
  case 'selected-test':
162
176
  if (evt.skip) {
163
177
  this.writeTest(evt, {passed: true, todo: false, skip: true});
package/lib/run-status.js CHANGED
@@ -33,6 +33,7 @@ export default class RunStatus extends Emittery {
33
33
  selectedTests: 0,
34
34
  sharedWorkerErrors: 0,
35
35
  skippedTests: 0,
36
+ timedOutTests: 0,
36
37
  timeouts: 0,
37
38
  todoTests: 0,
38
39
  uncaughtExceptions: 0,
@@ -62,6 +63,7 @@ export default class RunStatus extends Emittery {
62
63
  worker.onStateChange(data => this.emitStateChange(data));
63
64
  }
64
65
 
66
+ // eslint-disable-next-line complexity
65
67
  emitStateChange(event) {
66
68
  const {stats} = this;
67
69
  const fileStats = stats.byFile.get(event.testFile);
@@ -123,10 +125,11 @@ export default class RunStatus extends Emittery {
123
125
  this.removePendingTest(event);
124
126
  break;
125
127
  case 'timeout':
128
+ stats.timeouts++;
126
129
  event.pendingTests = this.pendingTests;
127
130
  this.pendingTests = new Map();
128
131
  for (const testsInFile of event.pendingTests.values()) {
129
- stats.timeouts += testsInFile.size;
132
+ stats.timedOutTests += testsInFile.size;
130
133
  }
131
134
 
132
135
  break;
@@ -134,6 +137,10 @@ export default class RunStatus extends Emittery {
134
137
  event.pendingTests = this.pendingTests;
135
138
  this.pendingTests = new Map();
136
139
  break;
140
+ case 'process-exit':
141
+ event.pendingTests = this.pendingTests;
142
+ this.pendingTests = new Map();
143
+ break;
137
144
  case 'uncaught-exception':
138
145
  stats.uncaughtExceptions++;
139
146
  fileStats.uncaughtExceptions++;
@@ -175,6 +182,7 @@ export default class RunStatus extends Emittery {
175
182
  || this.stats.failedHooks > 0
176
183
  || this.stats.failedTests > 0
177
184
  || this.stats.failedWorkers > 0
185
+ || this.stats.remainingTests > 0
178
186
  || this.stats.sharedWorkerErrors > 0
179
187
  || this.stats.timeouts > 0
180
188
  || this.stats.uncaughtExceptions > 0
package/lib/watcher.js CHANGED
@@ -294,6 +294,7 @@ export default class Watcher {
294
294
  switch (evt.type) {
295
295
  case 'hook-failed':
296
296
  case 'internal-error':
297
+ case 'process-exit':
297
298
  case 'test-failed':
298
299
  case 'uncaught-exception':
299
300
  case 'unhandled-rejection':
@@ -19,6 +19,41 @@ import {flags, refs, sharedWorkerTeardowns} from './state.cjs';
19
19
  import {isRunningInThread, isRunningInChildProcess} from './utils.cjs';
20
20
 
21
21
  const currentlyUnhandled = setUpCurrentlyUnhandled();
22
+ let runner;
23
+
24
+ // Override process.exit with an undetectable replacement
25
+ // to report when it is called from a test (which it should never be).
26
+ const {apply} = Reflect;
27
+ const realExit = process.exit;
28
+
29
+ async function exit(code, forceSync = false) {
30
+ dependencyTracking.flush();
31
+ const flushing = channel.flush();
32
+ if (!forceSync) {
33
+ await flushing;
34
+ }
35
+
36
+ apply(realExit, process, [code]);
37
+ }
38
+
39
+ const handleProcessExit = (fn, receiver, args) => {
40
+ const error = new Error('Unexpected process.exit()');
41
+ Error.captureStackTrace(error, handleProcessExit);
42
+ const {stack} = serializeError('', true, error);
43
+ channel.send({type: 'process-exit', stack});
44
+
45
+ // Make sure to extract the code only from `args` rather than e.g. `Array.prototype`.
46
+ // This level of paranoia is usually unwarranted, but we're dealing with test code
47
+ // that has already colored outside the lines.
48
+ const code = args.length > 0 ? args[0] : undefined;
49
+
50
+ // Force a synchronous exit as guaranteed by the real process.exit().
51
+ exit(code, true);
52
+ };
53
+
54
+ process.exit = new Proxy(realExit, {
55
+ apply: handleProcessExit,
56
+ });
22
57
 
23
58
  const run = async options => {
24
59
  setOptions(options);
@@ -29,16 +64,6 @@ const run = async options => {
29
64
  global.console = Object.assign(global.console, new console.Console({stdout, stderr, colorMode: true}));
30
65
  }
31
66
 
32
- async function exit(code) {
33
- if (!process.exitCode) {
34
- process.exitCode = code;
35
- }
36
-
37
- dependencyTracking.flush();
38
- await channel.flush();
39
- process.exit(); // eslint-disable-line unicorn/no-process-exit
40
- }
41
-
42
67
  let checkSelectedByLineNumbers;
43
68
  try {
44
69
  checkSelectedByLineNumbers = lineNumberSelection({
@@ -50,7 +75,7 @@ const run = async options => {
50
75
  checkSelectedByLineNumbers = () => false;
51
76
  }
52
77
 
53
- const runner = new Runner({
78
+ runner = new Runner({
54
79
  checkSelectedByLineNumbers,
55
80
  experiments: options.experiments,
56
81
  failFast: options.failFast,
@@ -141,7 +166,7 @@ const run = async options => {
141
166
 
142
167
  for (const extension of extensionsToLoadAsModules) {
143
168
  if (ref.endsWith(`.${extension}`)) {
144
- return import(pathToFileURL(ref)); // eslint-disable-line node/no-unsupported-features/es-syntax
169
+ return import(pathToFileURL(ref));
145
170
  }
146
171
  }
147
172
 
@@ -161,7 +186,7 @@ const run = async options => {
161
186
  if (options.debug && options.debug.port !== undefined && options.debug.host !== undefined) {
162
187
  // If an inspector was active when the main process started, and is
163
188
  // already active for the worker process, do not open a new one.
164
- const {default: inspector} = await import('node:inspector'); // eslint-disable-line node/no-unsupported-features/es-syntax
189
+ const {default: inspector} = await import('node:inspector');
165
190
  if (!options.debug.active || inspector.url() === undefined) {
166
191
  inspector.open(options.debug.port, options.debug.host, true);
167
192
  }
@@ -15,7 +15,7 @@ let pEvent = async (emitter, event, options) => {
15
15
  emitter.on(event, addToBuffer);
16
16
 
17
17
  try {
18
- ({pEvent} = await import('p-event')); // eslint-disable-line node/no-unsupported-features/es-syntax
18
+ ({pEvent} = await import('p-event'));
19
19
  } finally {
20
20
  emitter.off(event, addToBuffer);
21
21
  }
@@ -12,7 +12,7 @@ function parse(file) {
12
12
  const walk = require('acorn-walk');
13
13
 
14
14
  const ast = acorn.parse(fs.readFileSync(file, 'utf8'), {
15
- ecmaVersion: 11,
15
+ ecmaVersion: 'latest',
16
16
  locations: true,
17
17
  sourceType: 'module',
18
18
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ava",
3
- "version": "4.3.3",
3
+ "version": "5.0.0",
4
4
  "description": "Node.js test runner that lets you develop with confidence.",
5
5
  "license": "MIT",
6
6
  "repository": "avajs/ava",
@@ -11,18 +11,18 @@
11
11
  "exports": {
12
12
  ".": {
13
13
  "import": {
14
- "types": "./index.d.ts",
14
+ "types": "./entrypoints/main.d.ts",
15
15
  "default": "./entrypoints/main.mjs"
16
16
  },
17
17
  "require": {
18
- "types": "./entrypoints/index.d.cts",
18
+ "types": "./entrypoints/main.d.cts",
19
19
  "default": "./entrypoints/main.cjs"
20
20
  }
21
21
  },
22
22
  "./eslint-plugin-helper": "./entrypoints/eslint-plugin-helper.cjs",
23
23
  "./plugin": {
24
24
  "import": {
25
- "types": "./plugin.d.ts",
25
+ "types": "./entrypoints/plugin.d.ts",
26
26
  "default": "./entrypoints/plugin.mjs"
27
27
  },
28
28
  "require": {
@@ -33,18 +33,16 @@
33
33
  },
34
34
  "type": "module",
35
35
  "engines": {
36
- "node": ">=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=18"
36
+ "node": ">=14.19 <15 || >=16.15 <17 || >=18"
37
37
  },
38
38
  "scripts": {
39
39
  "cover": "c8 --report=none test-ava && c8 --report=none --no-clean tap && c8 report",
40
- "test": "xo && tsd && npm run -s cover"
40
+ "test": "xo && tsc --noEmit && npm run -s cover"
41
41
  },
42
42
  "files": [
43
43
  "entrypoints",
44
44
  "lib",
45
- "types",
46
- "index.d.ts",
47
- "plugin.d.ts"
45
+ "types"
48
46
  ],
49
47
  "keywords": [
50
48
  "🦄",
@@ -82,7 +80,7 @@
82
80
  "typescript"
83
81
  ],
84
82
  "dependencies": {
85
- "acorn": "^8.7.1",
83
+ "acorn": "^8.8.0",
86
84
  "acorn-walk": "^8.2.0",
87
85
  "ansi-styles": "^6.1.0",
88
86
  "arrgv": "^1.0.2",
@@ -92,7 +90,7 @@
92
90
  "chalk": "^5.0.1",
93
91
  "chokidar": "^3.5.3",
94
92
  "chunkd": "^2.0.1",
95
- "ci-info": "^3.3.1",
93
+ "ci-info": "^3.3.2",
96
94
  "ci-parallel-vars": "^1.0.1",
97
95
  "clean-yaml-object": "^0.1.0",
98
96
  "cli-truncate": "^3.1.0",
@@ -101,10 +99,10 @@
101
99
  "concordance": "^5.0.4",
102
100
  "currently-unhandled": "^0.4.1",
103
101
  "debug": "^4.3.4",
104
- "del": "^6.1.1",
105
- "emittery": "^0.11.0",
106
- "figures": "^4.0.1",
107
- "globby": "^13.1.1",
102
+ "del": "^7.0.0",
103
+ "emittery": "^0.13.1",
104
+ "figures": "^5.0.0",
105
+ "globby": "^13.1.2",
108
106
  "ignore-by-default": "^2.1.0",
109
107
  "indent-string": "^5.0.0",
110
108
  "is-error": "^2.2.2",
@@ -114,39 +112,40 @@
114
112
  "mem": "^9.0.2",
115
113
  "ms": "^2.1.3",
116
114
  "p-event": "^5.0.1",
117
- "p-map": "^5.4.0",
115
+ "p-map": "^5.5.0",
118
116
  "picomatch": "^2.3.1",
119
117
  "pkg-conf": "^4.0.0",
120
118
  "plur": "^5.1.0",
121
- "pretty-ms": "^7.0.1",
119
+ "pretty-ms": "^8.0.0",
122
120
  "resolve-cwd": "^3.0.0",
123
121
  "slash": "^3.0.0",
124
122
  "stack-utils": "^2.0.5",
125
123
  "strip-ansi": "^7.0.1",
126
124
  "supertap": "^3.0.1",
127
125
  "temp-dir": "^2.0.0",
128
- "write-file-atomic": "^4.0.1",
126
+ "write-file-atomic": "^4.0.2",
129
127
  "yargs": "^17.5.1"
130
128
  },
131
129
  "devDependencies": {
132
130
  "@ava/test": "github:avajs/test",
133
131
  "@ava/typescript": "^3.0.1",
132
+ "@sindresorhus/tsconfig": "^3.0.1",
134
133
  "@sinonjs/fake-timers": "^9.1.2",
135
134
  "ansi-escapes": "^5.0.0",
136
- "c8": "^7.11.3",
135
+ "c8": "^7.12.0",
137
136
  "delay": "^5.0.0",
138
137
  "execa": "^6.1.0",
139
138
  "fs-extra": "^10.1.0",
140
139
  "get-stream": "^6.0.1",
141
140
  "replace-string": "^4.0.0",
142
- "sinon": "^13.0.2",
143
- "tap": "^16.2.0",
141
+ "sinon": "^14.0.0",
142
+ "tap": "^16.3.0",
144
143
  "temp-write": "^5.0.0",
145
- "tempy": "^2.0.0",
144
+ "tempy": "^3.0.0",
146
145
  "touch": "^3.1.0",
147
- "tsd": "^0.20.0",
148
- "typescript": "^4.7.2",
149
- "xo": "^0.49.0",
146
+ "tsd": "^0.22.0",
147
+ "typescript": "^4.7.3",
148
+ "xo": "^0.52.2",
150
149
  "zen-observable": "^0.8.15"
151
150
  },
152
151
  "peerDependencies": {
@@ -158,7 +157,7 @@
158
157
  }
159
158
  },
160
159
  "volta": {
161
- "node": "18.3.0",
162
- "npm": "8.12.0"
160
+ "node": "18.8.0",
161
+ "npm": "8.18.0"
163
162
  }
164
163
  }
@@ -18,7 +18,7 @@ export type ThrowsExpectation = {
18
18
  name?: string;
19
19
  };
20
20
 
21
- export interface Assertions {
21
+ export type Assertions = {
22
22
  /**
23
23
  * Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), returning a boolean
24
24
  * indicating whether the assertion passed.
@@ -118,9 +118,9 @@ export interface Assertions {
118
118
  * indicating whether the assertion passed.
119
119
  */
120
120
  truthy: TruthyAssertion;
121
- }
121
+ };
122
122
 
123
- export interface AssertAssertion {
123
+ export type AssertAssertion = {
124
124
  /**
125
125
  * Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), returning a boolean
126
126
  * indicating whether the assertion passed.
@@ -129,9 +129,9 @@ export interface AssertAssertion {
129
129
 
130
130
  /** Skip this assertion. */
131
131
  skip(actual: any, message?: string): void;
132
- }
132
+ };
133
133
 
134
- export interface DeepEqualAssertion {
134
+ export type DeepEqualAssertion = {
135
135
  /**
136
136
  * Assert that `actual` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
137
137
  * `expected`, returning a boolean indicating whether the assertion passed.
@@ -152,9 +152,9 @@ export interface DeepEqualAssertion {
152
152
 
153
153
  /** Skip this assertion. */
154
154
  skip(actual: any, expected: any, message?: string): void;
155
- }
155
+ };
156
156
 
157
- export interface LikeAssertion {
157
+ export type LikeAssertion = {
158
158
  /**
159
159
  * Assert that `value` is like `selector`, returning a boolean indicating whether the assertion passed.
160
160
  */
@@ -162,17 +162,17 @@ export interface LikeAssertion {
162
162
 
163
163
  /** Skip this assertion. */
164
164
  skip(value: any, selector: any, message?: string): void;
165
- }
165
+ };
166
166
 
167
- export interface FailAssertion {
167
+ export type FailAssertion = {
168
168
  /** Fail the test, always returning `false`. */
169
169
  (message?: string): boolean;
170
170
 
171
171
  /** Skip this assertion. */
172
172
  skip(message?: string): void;
173
- }
173
+ };
174
174
 
175
- export interface FalseAssertion {
175
+ export type FalseAssertion = {
176
176
  /**
177
177
  * Assert that `actual` is strictly false, returning a boolean indicating whether the assertion passed.
178
178
  */
@@ -180,9 +180,9 @@ export interface FalseAssertion {
180
180
 
181
181
  /** Skip this assertion. */
182
182
  skip(actual: any, message?: string): void;
183
- }
183
+ };
184
184
 
185
- export interface FalsyAssertion {
185
+ export type FalsyAssertion = {
186
186
  /**
187
187
  * Assert that `actual` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy), returning a boolean
188
188
  * indicating whether the assertion passed.
@@ -191,9 +191,9 @@ export interface FalsyAssertion {
191
191
 
192
192
  /** Skip this assertion. */
193
193
  skip(actual: any, message?: string): void;
194
- }
194
+ };
195
195
 
196
- export interface IsAssertion {
196
+ export type IsAssertion = {
197
197
  /**
198
198
  * Assert that `actual` is [the same
199
199
  * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
@@ -203,9 +203,9 @@ export interface IsAssertion {
203
203
 
204
204
  /** Skip this assertion. */
205
205
  skip(actual: any, expected: any, message?: string): void;
206
- }
206
+ };
207
207
 
208
- export interface NotAssertion {
208
+ export type NotAssertion = {
209
209
  /**
210
210
  * Assert that `actual` is not [the same
211
211
  * value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) as `expected`,
@@ -215,9 +215,9 @@ export interface NotAssertion {
215
215
 
216
216
  /** Skip this assertion. */
217
217
  skip(actual: any, expected: any, message?: string): void;
218
- }
218
+ };
219
219
 
220
- export interface NotDeepEqualAssertion {
220
+ export type NotDeepEqualAssertion = {
221
221
  /**
222
222
  * Assert that `actual` is not [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to
223
223
  * `expected`, returning a boolean indicating whether the assertion passed.
@@ -226,9 +226,9 @@ export interface NotDeepEqualAssertion {
226
226
 
227
227
  /** Skip this assertion. */
228
228
  skip(actual: any, expected: any, message?: string): void;
229
- }
229
+ };
230
230
 
231
- export interface NotRegexAssertion {
231
+ export type NotRegexAssertion = {
232
232
  /**
233
233
  * Assert that `string` does not match the regular expression, returning a boolean indicating whether the assertion
234
234
  * passed.
@@ -237,17 +237,17 @@ export interface NotRegexAssertion {
237
237
 
238
238
  /** Skip this assertion. */
239
239
  skip(string: string, regex: RegExp, message?: string): void;
240
- }
240
+ };
241
241
 
242
- export interface NotThrowsAssertion {
242
+ export type NotThrowsAssertion = {
243
243
  /** Assert that the function does not throw. */
244
244
  (fn: () => any, message?: string): void;
245
245
 
246
246
  /** Skip this assertion. */
247
247
  skip(fn: () => any, message?: string): void;
248
- }
248
+ };
249
249
 
250
- export interface NotThrowsAsyncAssertion {
250
+ export type NotThrowsAsyncAssertion = {
251
251
  /** Assert that the async function does not throw. You must await the result. */
252
252
  (fn: () => PromiseLike<any>, message?: string): Promise<void>;
253
253
 
@@ -256,17 +256,17 @@ export interface NotThrowsAsyncAssertion {
256
256
 
257
257
  /** Skip this assertion. */
258
258
  skip(nonThrower: any, message?: string): void;
259
- }
259
+ };
260
260
 
261
- export interface PassAssertion {
261
+ export type PassAssertion = {
262
262
  /** Count a passing assertion, always returning `true`. */
263
263
  (message?: string): boolean;
264
264
 
265
265
  /** Skip this assertion. */
266
266
  skip(message?: string): void;
267
- }
267
+ };
268
268
 
269
- export interface RegexAssertion {
269
+ export type RegexAssertion = {
270
270
  /**
271
271
  * Assert that `string` matches the regular expression, returning a boolean indicating whether the assertion passed.
272
272
  */
@@ -274,9 +274,9 @@ export interface RegexAssertion {
274
274
 
275
275
  /** Skip this assertion. */
276
276
  skip(string: string, regex: RegExp, message?: string): void;
277
- }
277
+ };
278
278
 
279
- export interface SnapshotAssertion {
279
+ export type SnapshotAssertion = {
280
280
  /**
281
281
  * Assert that `expected` is [deeply equal](https://github.com/concordancejs/concordance#comparison-details) to a
282
282
  * previously recorded [snapshot](https://github.com/concordancejs/concordance#serialization-details), or if
@@ -286,9 +286,9 @@ export interface SnapshotAssertion {
286
286
 
287
287
  /** Skip this assertion. */
288
288
  skip(expected: any, message?: string): void;
289
- }
289
+ };
290
290
 
291
- export interface ThrowsAssertion {
291
+ export type ThrowsAssertion = {
292
292
  /**
293
293
  * Assert that the function throws [an error](https://www.npmjs.com/package/is-error). If so, returns the error value.
294
294
  * The error must satisfy all expectations. Returns undefined when the assertion fails.
@@ -297,9 +297,9 @@ export interface ThrowsAssertion {
297
297
 
298
298
  /** Skip this assertion. */
299
299
  skip(fn: () => any, expectations?: any, message?: string): void;
300
- }
300
+ };
301
301
 
302
- export interface ThrowsAsyncAssertion {
302
+ export type ThrowsAsyncAssertion = {
303
303
  /**
304
304
  * Assert that the async function throws [an error](https://www.npmjs.com/package/is-error). If so, returns the error
305
305
  * value. Returns undefined when the assertion fails. You must await the result. The error must satisfy all expectations.
@@ -315,9 +315,9 @@ export interface ThrowsAsyncAssertion {
315
315
 
316
316
  /** Skip this assertion. */
317
317
  skip(thrower: any, expectations?: any, message?: string): void;
318
- }
318
+ };
319
319
 
320
- export interface TrueAssertion {
320
+ export type TrueAssertion = {
321
321
  /**
322
322
  * Assert that `actual` is strictly true, returning a boolean indicating whether the assertion passed.
323
323
  */
@@ -325,9 +325,9 @@ export interface TrueAssertion {
325
325
 
326
326
  /** Skip this assertion. */
327
327
  skip(actual: any, message?: string): void;
328
- }
328
+ };
329
329
 
330
- export interface TruthyAssertion {
330
+ export type TruthyAssertion = {
331
331
  /**
332
332
  * Assert that `actual` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), returning a boolean
333
333
  * indicating whether the assertion passed.
@@ -336,4 +336,4 @@ export interface TruthyAssertion {
336
336
 
337
337
  /** Skip this assertion. */
338
338
  skip(actual: any, message?: string): void;
339
- }
339
+ };
@@ -1,6 +1,6 @@
1
- export interface Subscribable {
1
+ export type Subscribable = {
2
2
  subscribe(observer: {
3
3
  error(error: any): void;
4
4
  complete(): void;
5
5
  }): void;
6
- }
6
+ };
@@ -3,7 +3,7 @@ import type {Subscribable} from './subscribable.js';
3
3
  import type {TryFn} from './try-fn.js';
4
4
 
5
5
  /** The `t` value passed to test & hook implementations. */
6
- export interface ExecutionContext<Context = unknown> extends Assertions {
6
+ export type ExecutionContext<Context = unknown> = {
7
7
  /** Test context, shared with hooks. */
8
8
  context: Context;
9
9
 
@@ -18,17 +18,17 @@ export interface ExecutionContext<Context = unknown> extends Assertions {
18
18
  readonly teardown: TeardownFn;
19
19
  readonly timeout: TimeoutFn;
20
20
  readonly try: TryFn<Context>;
21
- }
21
+ } & Assertions;
22
22
 
23
- export interface LogFn {
23
+ export type LogFn = {
24
24
  /** Log one or more values. */
25
25
  (...values: any[]): void;
26
26
 
27
27
  /** Skip logging. */
28
28
  skip(...values: any[]): void;
29
- }
29
+ };
30
30
 
31
- export interface PlanFn {
31
+ export type PlanFn = {
32
32
  /**
33
33
  * Plan how many assertion there are in the test. The test will fail if the actual assertion count doesn't match the
34
34
  * number of planned assertions. See [assertion planning](https://github.com/avajs/ava#assertion-planning).
@@ -37,7 +37,7 @@ export interface PlanFn {
37
37
 
38
38
  /** Don't plan assertions. */
39
39
  skip(count: number): void;
40
- }
40
+ };
41
41
 
42
42
  /**
43
43
  * Set a timeout for the test, in milliseconds. The test will fail if the timeout is exceeded.
@@ -67,7 +67,7 @@ export type Macro<Args extends unknown[], Context = unknown> = {
67
67
  /** A test or hook implementation. */
68
68
  export type Implementation<Args extends unknown[], Context = unknown> = ImplementationFn<Args, Context> | Macro<Args, Context>;
69
69
 
70
- export interface TestFn<Context = unknown> {
70
+ export type TestFn<Context = unknown> = {
71
71
  /** Declare a concurrent test. Additional arguments are passed to the implementation or macro. */
72
72
  <Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
73
73
 
@@ -88,9 +88,9 @@ export interface TestFn<Context = unknown> {
88
88
  serial: SerialFn<Context>;
89
89
  skip: SkipFn<Context>;
90
90
  todo: TodoFn;
91
- }
91
+ };
92
92
 
93
- export interface AfterFn<Context = unknown> {
93
+ export type AfterFn<Context = unknown> = {
94
94
  /**
95
95
  * Declare a hook that is run once, after all tests have passed.
96
96
  * Additional arguments are passed to the implementation or macro.
@@ -105,9 +105,9 @@ export interface AfterFn<Context = unknown> {
105
105
 
106
106
  always: AlwaysInterface<Context>;
107
107
  skip: HookSkipFn<Context>;
108
- }
108
+ };
109
109
 
110
- export interface AlwaysInterface<Context = unknown> {
110
+ export type AlwaysInterface<Context = unknown> = {
111
111
  /**
112
112
  * Declare a hook that is run once, after all tests are done.
113
113
  * Additional arguments are passed to the implementation or macro.
@@ -121,9 +121,9 @@ export interface AlwaysInterface<Context = unknown> {
121
121
  <Args extends unknown[]>(implementation: Implementation<Args, Context>, ...args: Args): void;
122
122
 
123
123
  skip: HookSkipFn<Context>;
124
- }
124
+ };
125
125
 
126
- export interface BeforeFn<Context = unknown> {
126
+ export type BeforeFn<Context = unknown> = {
127
127
  /**
128
128
  * Declare a hook that is run once, before all tests.
129
129
  * Additional arguments are passed to the implementation or macro.
@@ -137,9 +137,9 @@ export interface BeforeFn<Context = unknown> {
137
137
  <Args extends unknown[]>(implementation: Implementation<Args, Context>, ...args: Args): void;
138
138
 
139
139
  skip: HookSkipFn<Context>;
140
- }
140
+ };
141
141
 
142
- export interface FailingFn<Context = unknown> {
142
+ export type FailingFn<Context = unknown> = {
143
143
  /**
144
144
  * Declare a concurrent test that is expected to fail.
145
145
  * Additional arguments are passed to the implementation or macro.
@@ -154,17 +154,17 @@ export interface FailingFn<Context = unknown> {
154
154
 
155
155
  only: OnlyFn<Context>;
156
156
  skip: SkipFn<Context>;
157
- }
157
+ };
158
158
 
159
- export interface HookSkipFn<Context = unknown> {
159
+ export type HookSkipFn<Context = unknown> = {
160
160
  /** Skip this hook. */
161
161
  <Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
162
162
 
163
163
  /** Skip this hook. */
164
164
  <Args extends unknown[]>(implementation: Implementation<Args, Context>, ...args: Args): void;
165
- }
165
+ };
166
166
 
167
- export interface OnlyFn<Context = unknown> {
167
+ export type OnlyFn<Context = unknown> = {
168
168
  /**
169
169
  * Declare a test. Only this test and others declared with `.only()` are run.
170
170
  * Additional arguments are passed to the implementation or macro.
@@ -176,9 +176,9 @@ export interface OnlyFn<Context = unknown> {
176
176
  * Additional arguments are passed to the macro. The macro is responsible for generating a unique test title.
177
177
  */
178
178
  <Args extends unknown[]>(macro: Macro<Args, Context>, ...args: Args): void;
179
- }
179
+ };
180
180
 
181
- export interface SerialFn<Context = unknown> {
181
+ export type SerialFn<Context = unknown> = {
182
182
  /** Declare a serial test. Additional arguments are passed to the implementation or macro. */
183
183
  <Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
184
184
 
@@ -195,15 +195,15 @@ export interface SerialFn<Context = unknown> {
195
195
  only: OnlyFn<Context>;
196
196
  skip: SkipFn<Context>;
197
197
  todo: TodoFn;
198
- }
198
+ };
199
199
 
200
- export interface SkipFn<Context = unknown> {
200
+ export type SkipFn<Context = unknown> = {
201
201
  /** Skip this test. */
202
202
  <Args extends unknown[]>(title: string, implementation: Implementation<Args, Context>, ...args: Args): void;
203
203
 
204
204
  /** Skip this test. */
205
205
  <Args extends unknown[]>(macro: Macro<Args, Context>, ...args: Args): void;
206
- }
206
+ };
207
207
 
208
208
  /** Declare a test that should be implemented later. */
209
209
  export type TodoFn = (title: string) => void;
@@ -216,16 +216,16 @@ export type MacroDeclarationOptions<Args extends unknown[], Context = unknown> =
216
216
  title: TitleFn<Args>;
217
217
  };
218
218
 
219
- export interface MacroFn<Context = unknown> {
219
+ export type 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
222
  <Args extends unknown[]>(declaration: MacroDeclarationOptions<Args, Context>): Macro<Args, Context>;
223
- }
223
+ };
224
224
 
225
- export interface Meta {
225
+ export type Meta = {
226
226
  /** Path to the test file being executed. */
227
227
  file: string;
228
228
 
229
229
  /** Directory where snapshots are stored. */
230
230
  snapshotDirectory: string;
231
- }
231
+ };
package/types/try-fn.d.ts CHANGED
@@ -7,9 +7,9 @@ export type CommitDiscardOptions = {
7
7
  retainLogs?: boolean;
8
8
  };
9
9
 
10
- export interface AssertionError extends Error {}
10
+ export type AssertionError = Record<string, unknown> & Error;
11
11
 
12
- export interface TryResult {
12
+ export type TryResult = {
13
13
  /**
14
14
  * Title of the attempt, helping you tell attempts aparts.
15
15
  */
@@ -40,9 +40,9 @@ export interface TryResult {
40
40
  * Discard the attempt.
41
41
  */
42
42
  discard(options?: CommitDiscardOptions): void;
43
- }
43
+ };
44
44
 
45
- export interface TryFn<Context = unknown> {
45
+ export type TryFn<Context = unknown> = {
46
46
  /**
47
47
  * Attempt to run some assertions. The result must be explicitly committed or discarded or else
48
48
  * the test will fail. The title may help distinguish attempts from one another.
@@ -54,5 +54,5 @@ export interface TryFn<Context = unknown> {
54
54
  * the test will fail.
55
55
  */
56
56
  <Args extends unknown[]>(fn: Implementation<Args, Context>, ...args: Args): Promise<TryResult>;
57
- }
57
+ };
58
58
 
@@ -1,2 +0,0 @@
1
- export {default} from '../index.js';
2
- export * from '../index.js';
package/index.d.ts DELETED
@@ -1,12 +0,0 @@
1
- import type {TestFn} from './types/test-fn.js';
2
-
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
-
8
- /** Call to declare a test, or chain to declare hooks or test modifiers */
9
- declare const test: TestFn;
10
-
11
- /** Call to declare a test, or chain to declare hooks or test modifiers */
12
- export default test;