ava 5.0.0 → 5.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,2 +1,12 @@
1
- export {default} from './main.js';
2
- export * from './main.js';
1
+ import type {TestFn} from '../types/test-fn.cjs';
2
+
3
+ export * from '../types/assertions.cjs';
4
+ export * from '../types/try-fn.cjs';
5
+ export * from '../types/test-fn.cjs';
6
+ export * from '../types/subscribable.cjs';
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,9 +1,9 @@
1
- import type {TestFn} from '../types/test-fn.js';
1
+ import type {TestFn} from '../types/test-fn.cjs';
2
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';
3
+ export * from '../types/assertions.cjs';
4
+ export * from '../types/try-fn.cjs';
5
+ export * from '../types/test-fn.cjs';
6
+ export * from '../types/subscribable.cjs';
7
7
 
8
8
  /** Call to declare a test, or chain to declare hooks or test modifiers */
9
9
  declare const test: TestFn;
@@ -1 +1,6 @@
1
- export * from './plugin.js'
1
+ import type {SharedWorker} from '../types/shared-worker.cjs';
2
+
3
+ export function registerSharedWorker<Data = unknown>(options: SharedWorker.Plugin.RegistrationOptions<'ava-4', Data>): SharedWorker.Plugin.Protocol<Data>;
4
+ // Add overloads for additional protocols.
5
+
6
+ export type {SharedWorker} from '../types/shared-worker.cjs';
@@ -1,77 +1,6 @@
1
- import type {URL} from 'node:url';
2
-
3
- export namespace SharedWorker {
4
- export type ProtocolIdentifier = 'ava-4';
5
-
6
- export type FactoryOptions = {
7
- negotiateProtocol <Data = unknown>(supported: readonly ['ava-4']): Protocol<Data>;
8
- // Add overloads for additional protocols.
9
- };
10
-
11
- export type Factory = (options: FactoryOptions) => void;
12
-
13
- export type Protocol<Data = unknown> = {
14
- readonly initialData: Data;
15
- readonly protocol: 'ava-4';
16
- broadcast: (data: Data) => BroadcastMessage<Data>;
17
- ready: () => Protocol<Data>;
18
- subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
19
- testWorkers: () => AsyncIterableIterator<TestWorker<Data>>;
20
- };
21
-
22
- export type BroadcastMessage<Data = unknown> = {
23
- readonly id: string;
24
- replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
25
- };
26
-
27
- export type PublishedMessage<Data = unknown> = {
28
- readonly id: string;
29
- replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
30
- };
31
-
32
- export type ReceivedMessage<Data = unknown> = {
33
- readonly data: Data;
34
- readonly id: string;
35
- readonly testWorker: TestWorker;
36
- reply: (data: Data) => PublishedMessage<Data>;
37
- };
38
-
39
- export type TestWorker<Data = unknown> = {
40
- readonly id: string;
41
- readonly file: string;
42
- publish: (data: Data) => PublishedMessage<Data>;
43
- subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
44
- teardown: (fn: (() => Promise<void>) | (() => void)) => () => Promise<void>;
45
- };
46
-
47
- export namespace Plugin {
48
- export type RegistrationOptions<Identifier extends ProtocolIdentifier, Data = unknown> = {
49
- readonly filename: string | URL;
50
- readonly initialData?: Data;
51
- readonly supportedProtocols: readonly Identifier[];
52
- readonly teardown?: () => void;
53
- };
54
-
55
- export type Protocol<Data = unknown> = {
56
- readonly available: Promise<void>;
57
- readonly currentlyAvailable: boolean;
58
- readonly protocol: 'ava-4';
59
- publish: (data: Data) => PublishedMessage<Data>;
60
- subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
61
- };
62
-
63
- export type PublishedMessage<Data = unknown> = {
64
- readonly id: string;
65
- replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
66
- };
67
-
68
- export type ReceivedMessage<Data = unknown> = {
69
- readonly data: Data;
70
- readonly id: string;
71
- reply: (data: Data) => PublishedMessage<Data>;
72
- };
73
- }
74
- }
1
+ import type {SharedWorker} from '../types/shared-worker.cjs';
75
2
 
76
3
  export function registerSharedWorker<Data = unknown>(options: SharedWorker.Plugin.RegistrationOptions<'ava-4', Data>): SharedWorker.Plugin.Protocol<Data>;
77
4
  // Add overloads for additional protocols.
5
+
6
+ export type {SharedWorker} from '../types/shared-worker.cjs';
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ // For compatibility with resolution algorithms other than Node16.
2
+
3
+ export * from './entrypoints/main.cjs';
4
+ export {default} from './entrypoints/main.cjs';
package/lib/api.js CHANGED
@@ -16,6 +16,7 @@ import fork from './fork.js';
16
16
  import * as globs from './globs.js';
17
17
  import isCi from './is-ci.js';
18
18
  import {getApplicableLineNumbers} from './line-numbers.js';
19
+ import {setCappedTimeout} from './now-and-timers.cjs';
19
20
  import {observeWorkerProcess} from './plugin-support/shared-workers.js';
20
21
  import RunStatus from './run-status.js';
21
22
  import scheduler from './scheduler.js';
@@ -52,7 +53,7 @@ class TimeoutTrigger {
52
53
 
53
54
  debounce() {
54
55
  if (this.timer === undefined) {
55
- this.timer = setTimeout(() => this.trigger(), this.waitMs);
56
+ this.timer = setCappedTimeout(() => this.trigger(), this.waitMs);
56
57
  } else {
57
58
  this.timer.refresh();
58
59
  }
package/lib/cli.js CHANGED
@@ -250,8 +250,8 @@ export default async function loadCli() { // eslint-disable-line complexity
250
250
  setChalk(chalkOptions);
251
251
 
252
252
  if (confError) {
253
- if (confError.parent) {
254
- exit(`${confError.message}\n\n${chalk.gray((confError.parent && confError.parent.stack) || confError.parent)}`);
253
+ if (confError.cause) {
254
+ exit(`${confError.message}\n\n${chalk.gray(confError.cause?.stack ?? confError.cause)}`);
255
255
  } else {
256
256
  exit(confError.message);
257
257
  }
@@ -29,17 +29,13 @@ const loadConfigFile = async ({projectDir, configFile}) => {
29
29
  return null;
30
30
  }
31
31
 
32
- throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {parent: error});
32
+ throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {cause: error});
33
33
  }
34
34
  };
35
35
 
36
36
  function resolveConfigFile(configFile) {
37
37
  if (configFile) {
38
38
  configFile = path.resolve(configFile); // Relative to CWD
39
-
40
- if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) {
41
- throw new Error('Config files must have .js, .cjs or .mjs extensions');
42
- }
43
39
  }
44
40
 
45
41
  return configFile;
@@ -78,7 +74,7 @@ async function checkJsonFile(searchDir) {
78
74
  }
79
75
  }
80
76
 
81
- export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) {
77
+ export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { // eslint-disable-line complexity
82
78
  let packageConf = await packageConfig('ava', {cwd: resolveFrom});
83
79
  const filepath = packageJsonPath(packageConf);
84
80
  const projectDir = filepath === undefined ? resolveFrom : path.dirname(filepath);
@@ -94,7 +90,17 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
94
90
  let fileForErrorMessage;
95
91
  let conflicting = [];
96
92
  if (configFile) {
97
- const loaded = await loadConfigFile({projectDir, configFile});
93
+ let loaded;
94
+ try {
95
+ loaded = await loadConfigFile({projectDir, configFile});
96
+ } catch (error) {
97
+ if (!configFile.endsWith('.js') && !configFile.endsWith('.cjs') && !configFile.endsWith('.mjs')) {
98
+ throw Object.assign(new Error('Could not load config file; it should have .js, .cjs or .mjs extension'), {cause: error});
99
+ }
100
+
101
+ throw error;
102
+ }
103
+
98
104
  if (loaded !== null) {
99
105
  ({config: fileConf, fileForErrorMessage} = loaded);
100
106
  }
@@ -3,3 +3,14 @@ const timers = require('timers');
3
3
 
4
4
  Object.assign(exports, timers);
5
5
  exports.now = Date.now;
6
+
7
+ // Any delay larger than this value is ignored by Node.js, with a delay of `1`
8
+ // used instead. See <https://nodejs.org/api/timers.html#settimeoutcallback-delay-args>.
9
+ const MAX_DELAY = (2 ** 31) - 1;
10
+
11
+ function setCappedTimeout(callback, delay) {
12
+ const safeDelay = Math.min(delay, MAX_DELAY);
13
+ return timers.setTimeout(callback, safeDelay);
14
+ }
15
+
16
+ exports.setCappedTimeout = setCappedTimeout;
@@ -370,8 +370,11 @@ export default class Reporter {
370
370
  }
371
371
 
372
372
  this.lineWriter.writeLine(`${testsInFile.size} tests were pending in ${this.relativeFile(file)}\n`);
373
+ const testTitleToLogs = evt.pendingTestsLogs.get(file);
373
374
  for (const title of testsInFile) {
375
+ const logs = testTitleToLogs?.get(title);
374
376
  this.lineWriter.writeLine(`${figures.circleDotted} ${this.prefixTitle(file, title)}`);
377
+ this.writeLogs({logs});
375
378
  }
376
379
 
377
380
  this.lineWriter.writeLine('');
package/lib/run-status.js CHANGED
@@ -9,6 +9,7 @@ export default class RunStatus extends Emittery {
9
9
  super();
10
10
 
11
11
  this.pendingTests = new Map();
12
+ this.pendingTestsLogs = new Map();
12
13
 
13
14
  this.emptyParallelRun = parallelRuns
14
15
  && parallelRuns.currentFileCount === 0
@@ -60,6 +61,7 @@ export default class RunStatus extends Emittery {
60
61
  });
61
62
 
62
63
  this.pendingTests.set(testFile, new Set());
64
+ this.pendingTestsLogs.set(testFile, new Map());
63
65
  worker.onStateChange(data => this.emitStateChange(data));
64
66
  }
65
67
 
@@ -124,10 +126,15 @@ export default class RunStatus extends Emittery {
124
126
  fileStats.remainingTests--;
125
127
  this.removePendingTest(event);
126
128
  break;
129
+ case 'test-register-log-reference':
130
+ this.addPendingTestLogs(event);
131
+ break;
127
132
  case 'timeout':
128
133
  stats.timeouts++;
129
134
  event.pendingTests = this.pendingTests;
135
+ event.pendingTestsLogs = this.pendingTestsLogs;
130
136
  this.pendingTests = new Map();
137
+ this.pendingTestsLogs = new Map();
131
138
  for (const testsInFile of event.pendingTests.values()) {
132
139
  stats.timedOutTests += testsInFile.size;
133
140
  }
@@ -135,11 +142,15 @@ export default class RunStatus extends Emittery {
135
142
  break;
136
143
  case 'interrupt':
137
144
  event.pendingTests = this.pendingTests;
145
+ event.pendingTestsLogs = this.pendingTestsLogs;
138
146
  this.pendingTests = new Map();
147
+ this.pendingTestsLogs = new Map();
139
148
  break;
140
149
  case 'process-exit':
141
150
  event.pendingTests = this.pendingTests;
151
+ event.pendingTestsLogs = this.pendingTestsLogs;
142
152
  this.pendingTests = new Map();
153
+ this.pendingTestsLogs = new Map();
143
154
  break;
144
155
  case 'uncaught-exception':
145
156
  stats.uncaughtExceptions++;
@@ -198,6 +209,10 @@ export default class RunStatus extends Emittery {
198
209
  return 0;
199
210
  }
200
211
 
212
+ addPendingTestLogs(event) {
213
+ this.pendingTestsLogs.get(event.testFile)?.set(event.title, event.logs);
214
+ }
215
+
201
216
  addPendingTest(event) {
202
217
  if (this.pendingTests.has(event.testFile)) {
203
218
  this.pendingTests.get(event.testFile).add(event.title);
package/lib/runner.js CHANGED
@@ -358,6 +358,12 @@ export default class Runner extends Emittery {
358
358
  notifyTimeoutUpdate: this.notifyTimeoutUpdate,
359
359
  });
360
360
 
361
+ this.emit('stateChange', {
362
+ type: 'test-register-log-reference',
363
+ title: task.title,
364
+ logs: test.logs,
365
+ });
366
+
361
367
  const result = await this.runSingle(test);
362
368
  testOk = result.passed;
363
369
 
package/lib/test.js CHANGED
@@ -405,7 +405,7 @@ export default class Test {
405
405
 
406
406
  this.clearTimeout();
407
407
  this.timeoutMs = ms;
408
- this.timeoutTimer = nowAndTimers.setTimeout(() => {
408
+ this.timeoutTimer = nowAndTimers.setCappedTimeout(() => {
409
409
  this.saveFirstError(new Error(message || 'Test timeout exceeded'));
410
410
 
411
411
  if (this.finishDueToTimeout) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ava",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Node.js test runner that lets you develop with confidence.",
5
5
  "license": "MIT",
6
6
  "repository": "avajs/ava",
@@ -42,7 +42,8 @@
42
42
  "files": [
43
43
  "entrypoints",
44
44
  "lib",
45
- "types"
45
+ "types",
46
+ "*.d.ts"
46
47
  ],
47
48
  "keywords": [
48
49
  "🦄",
@@ -80,17 +81,17 @@
80
81
  "typescript"
81
82
  ],
82
83
  "dependencies": {
83
- "acorn": "^8.8.0",
84
+ "acorn": "^8.8.1",
84
85
  "acorn-walk": "^8.2.0",
85
- "ansi-styles": "^6.1.0",
86
+ "ansi-styles": "^6.2.1",
86
87
  "arrgv": "^1.0.2",
87
88
  "arrify": "^3.0.0",
88
89
  "callsites": "^4.0.0",
89
90
  "cbor": "^8.1.0",
90
- "chalk": "^5.0.1",
91
+ "chalk": "^5.1.2",
91
92
  "chokidar": "^3.5.3",
92
93
  "chunkd": "^2.0.1",
93
- "ci-info": "^3.3.2",
94
+ "ci-info": "^3.6.1",
94
95
  "ci-parallel-vars": "^1.0.1",
95
96
  "clean-yaml-object": "^0.1.0",
96
97
  "cli-truncate": "^3.1.0",
@@ -100,7 +101,7 @@
100
101
  "currently-unhandled": "^0.4.1",
101
102
  "debug": "^4.3.4",
102
103
  "del": "^7.0.0",
103
- "emittery": "^0.13.1",
104
+ "emittery": "^1.0.1",
104
105
  "figures": "^5.0.0",
105
106
  "globby": "^13.1.2",
106
107
  "ignore-by-default": "^2.1.0",
@@ -119,34 +120,34 @@
119
120
  "pretty-ms": "^8.0.0",
120
121
  "resolve-cwd": "^3.0.0",
121
122
  "slash": "^3.0.0",
122
- "stack-utils": "^2.0.5",
123
+ "stack-utils": "^2.0.6",
123
124
  "strip-ansi": "^7.0.1",
124
125
  "supertap": "^3.0.1",
125
- "temp-dir": "^2.0.0",
126
- "write-file-atomic": "^4.0.2",
127
- "yargs": "^17.5.1"
126
+ "temp-dir": "^3.0.0",
127
+ "write-file-atomic": "^5.0.0",
128
+ "yargs": "^17.6.2"
128
129
  },
129
130
  "devDependencies": {
130
131
  "@ava/test": "github:avajs/test",
131
132
  "@ava/typescript": "^3.0.1",
132
133
  "@sindresorhus/tsconfig": "^3.0.1",
133
- "@sinonjs/fake-timers": "^9.1.2",
134
- "ansi-escapes": "^5.0.0",
134
+ "@sinonjs/fake-timers": "^10.0.0",
135
+ "ansi-escapes": "^6.0.0",
135
136
  "c8": "^7.12.0",
136
137
  "delay": "^5.0.0",
137
138
  "execa": "^6.1.0",
138
139
  "fs-extra": "^10.1.0",
139
140
  "get-stream": "^6.0.1",
140
141
  "replace-string": "^4.0.0",
141
- "sinon": "^14.0.0",
142
+ "sinon": "^14.0.2",
142
143
  "tap": "^16.3.0",
143
144
  "temp-write": "^5.0.0",
144
145
  "tempy": "^3.0.0",
145
146
  "touch": "^3.1.0",
146
- "tsd": "^0.22.0",
147
- "typescript": "^4.7.3",
148
- "xo": "^0.52.2",
149
- "zen-observable": "^0.8.15"
147
+ "tsd": "^0.24.1",
148
+ "typescript": "^4.8.4",
149
+ "xo": "^0.52.4",
150
+ "zen-observable": "^0.9.0"
150
151
  },
151
152
  "peerDependencies": {
152
153
  "@ava/typescript": "*"
package/plugin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ // For compatibility with resolution algorithms other than Node16.
2
+
3
+ export * from './entrypoints/plugin.cjs';
File without changes
@@ -0,0 +1,74 @@
1
+ import type {URL} from 'node:url';
2
+
3
+ export namespace SharedWorker {
4
+ export type ProtocolIdentifier = 'ava-4';
5
+
6
+ export type FactoryOptions = {
7
+ negotiateProtocol <Data = unknown>(supported: readonly ['ava-4']): Protocol<Data>;
8
+ // Add overloads for additional protocols.
9
+ };
10
+
11
+ export type Factory = (options: FactoryOptions) => void;
12
+
13
+ export type Protocol<Data = unknown> = {
14
+ readonly initialData: Data;
15
+ readonly protocol: 'ava-4';
16
+ broadcast: (data: Data) => BroadcastMessage<Data>;
17
+ ready: () => Protocol<Data>;
18
+ subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
19
+ testWorkers: () => AsyncIterableIterator<TestWorker<Data>>;
20
+ };
21
+
22
+ export type BroadcastMessage<Data = unknown> = {
23
+ readonly id: string;
24
+ replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
25
+ };
26
+
27
+ export type PublishedMessage<Data = unknown> = {
28
+ readonly id: string;
29
+ replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
30
+ };
31
+
32
+ export type ReceivedMessage<Data = unknown> = {
33
+ readonly data: Data;
34
+ readonly id: string;
35
+ readonly testWorker: TestWorker;
36
+ reply: (data: Data) => PublishedMessage<Data>;
37
+ };
38
+
39
+ export type TestWorker<Data = unknown> = {
40
+ readonly id: string;
41
+ readonly file: string;
42
+ publish: (data: Data) => PublishedMessage<Data>;
43
+ subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
44
+ teardown: (fn: (() => Promise<void>) | (() => void)) => () => Promise<void>;
45
+ };
46
+
47
+ export namespace Plugin {
48
+ export type RegistrationOptions<Identifier extends ProtocolIdentifier, Data = unknown> = {
49
+ readonly filename: string | URL;
50
+ readonly initialData?: Data;
51
+ readonly supportedProtocols: readonly Identifier[];
52
+ readonly teardown?: () => void;
53
+ };
54
+
55
+ export type Protocol<Data = unknown> = {
56
+ readonly available: Promise<void>;
57
+ readonly currentlyAvailable: boolean;
58
+ readonly protocol: 'ava-4';
59
+ publish: (data: Data) => PublishedMessage<Data>;
60
+ subscribe: () => AsyncIterableIterator<ReceivedMessage<Data>>;
61
+ };
62
+
63
+ export type PublishedMessage<Data = unknown> = {
64
+ readonly id: string;
65
+ replies: () => AsyncIterableIterator<ReceivedMessage<Data>>;
66
+ };
67
+
68
+ export type ReceivedMessage<Data = unknown> = {
69
+ readonly data: Data;
70
+ readonly id: string;
71
+ reply: (data: Data) => PublishedMessage<Data>;
72
+ };
73
+ }
74
+ }
File without changes
@@ -1,6 +1,6 @@
1
- import type {Assertions} from './assertions.js';
2
- import type {Subscribable} from './subscribable.js';
3
- import type {TryFn} from './try-fn.js';
1
+ import type {Assertions} from './assertions.cjs';
2
+ import type {Subscribable} from './subscribable.cjs';
3
+ import type {TryFn} from './try-fn.cjs';
4
4
 
5
5
  /** The `t` value passed to test & hook implementations. */
6
6
  export type ExecutionContext<Context = unknown> = {
@@ -1,4 +1,4 @@
1
- import type {Implementation} from './test-fn.js';
1
+ import type {Implementation} from './test-fn.cjs';
2
2
 
3
3
  export type CommitDiscardOptions = {
4
4
  /**