ava 3.7.1 → 3.9.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.
@@ -7,6 +7,7 @@ const stripAnsi = require('strip-ansi');
7
7
  const supertap = require('supertap');
8
8
  const indentString = require('indent-string');
9
9
 
10
+ const beautifyStack = require('./beautify-stack');
10
11
  const prefixTitle = require('./prefix-title');
11
12
 
12
13
  function dumpError(error) {
@@ -29,7 +30,7 @@ function dumpError(error) {
29
30
  }
30
31
 
31
32
  if (error.values.length > 0) {
32
- object.values = error.values.reduce((acc, value) => {
33
+ object.values = error.values.reduce((acc, value) => { // eslint-disable-line unicorn/no-reduce
33
34
  acc[value.label] = stripAnsi(value.formatted);
34
35
  return acc;
35
36
  }, {});
@@ -42,7 +43,7 @@ function dumpError(error) {
42
43
  }
43
44
 
44
45
  if (error.stack) {
45
- object.at = error.stack;
46
+ object.at = error.shouldBeautifyStack ? beautifyStack(error.stack).join('\n') : error.stack;
46
47
  }
47
48
 
48
49
  return object;
package/lib/run-status.js CHANGED
@@ -35,7 +35,7 @@ class RunStatus extends Emittery {
35
35
  };
36
36
  }
37
37
 
38
- observeWorker(worker, testFile) {
38
+ observeWorker(worker, testFile, stats) {
39
39
  this.stats.byFile.set(testFile, {
40
40
  declaredTests: 0,
41
41
  failedHooks: 0,
@@ -45,10 +45,12 @@ class RunStatus extends Emittery {
45
45
  passedKnownFailingTests: 0,
46
46
  passedTests: 0,
47
47
  selectedTests: 0,
48
+ selectingLines: false,
48
49
  skippedTests: 0,
49
50
  todoTests: 0,
50
51
  uncaughtExceptions: 0,
51
- unhandledRejections: 0
52
+ unhandledRejections: 0,
53
+ ...stats
52
54
  });
53
55
 
54
56
  this.pendingTests.set(testFile, new Set());
@@ -169,6 +171,10 @@ class RunStatus extends Emittery {
169
171
  return 1;
170
172
  }
171
173
 
174
+ if ([...this.stats.byFile.values()].some(stats => stats.selectingLines && stats.selectedTests === 0)) {
175
+ return 1;
176
+ }
177
+
172
178
  return 0;
173
179
  }
174
180
 
package/lib/runner.js CHANGED
@@ -16,6 +16,7 @@ class Runner extends Emittery {
16
16
  this.failFast = options.failFast === true;
17
17
  this.failWithoutAssertions = options.failWithoutAssertions !== false;
18
18
  this.file = options.file;
19
+ this.checkSelectedByLineNumbers = options.checkSelectedByLineNumbers;
19
20
  this.match = options.match || [];
20
21
  this.powerAssert = undefined; // Assigned later.
21
22
  this.projectDir = options.projectDir;
@@ -75,6 +76,10 @@ class Runner extends Emittery {
75
76
 
76
77
  const {args, buildTitle, implementations, rawTitle} = parseTestArgs(testArgs);
77
78
 
79
+ if (this.checkSelectedByLineNumbers) {
80
+ metadata.selected = this.checkSelectedByLineNumbers();
81
+ }
82
+
78
83
  if (metadata.todo) {
79
84
  if (implementations.length > 0) {
80
85
  throw new TypeError('`todo` tests are not allowed to have an implementation. Use `test.skip()` for tests with an implementation.');
@@ -236,7 +241,7 @@ class Runner extends Emittery {
236
241
  };
237
242
 
238
243
  let waitForSerial = Promise.resolve();
239
- await runnables.reduce((previous, runnable) => {
244
+ await runnables.reduce((previous, runnable) => { // eslint-disable-line unicorn/no-reduce
240
245
  if (runnable.metadata.serial || this.serial) {
241
246
  waitForSerial = previous.then(() => {
242
247
  // Serial runnables run as long as there was no previous failure, unless
@@ -283,6 +288,7 @@ class Runner extends Emittery {
283
288
  metadata: task.metadata,
284
289
  powerAssert: this.powerAssert,
285
290
  title: `${task.title}${titleSuffix || ''}`,
291
+ isHook: true,
286
292
  testPassed
287
293
  }));
288
294
  const outcome = await this.runMultiple(hooks, this.serial);
@@ -347,7 +353,7 @@ class Runner extends Emittery {
347
353
  this.emit('stateChange', {
348
354
  type: 'test-failed',
349
355
  title: result.title,
350
- err: serializeError('Test failure', true, result.error),
356
+ err: serializeError('Test failure', true, result.error, this.file),
351
357
  duration: result.duration,
352
358
  knownFailing: result.metadata.failing,
353
359
  logs: result.logs
@@ -368,6 +374,10 @@ class Runner extends Emittery {
368
374
  continue;
369
375
  }
370
376
 
377
+ if (this.checkSelectedByLineNumbers && !task.metadata.selected) {
378
+ continue;
379
+ }
380
+
371
381
  this.emit('stateChange', {
372
382
  type: 'selected-test',
373
383
  title: task.title,
@@ -386,6 +396,10 @@ class Runner extends Emittery {
386
396
  continue;
387
397
  }
388
398
 
399
+ if (this.checkSelectedByLineNumbers && !task.metadata.selected) {
400
+ continue;
401
+ }
402
+
389
403
  this.emit('stateChange', {
390
404
  type: 'selected-test',
391
405
  title: task.title,
@@ -408,6 +422,10 @@ class Runner extends Emittery {
408
422
  continue;
409
423
  }
410
424
 
425
+ if (this.checkSelectedByLineNumbers && !task.metadata.selected) {
426
+ continue;
427
+ }
428
+
411
429
  this.emit('stateChange', {
412
430
  type: 'selected-test',
413
431
  title: task.title,
@@ -433,7 +451,7 @@ class Runner extends Emittery {
433
451
  return false;
434
452
  }
435
453
 
436
- return serialTests.reduce(async (previous, task) => {
454
+ return serialTests.reduce(async (previous, task) => { // eslint-disable-line unicorn/no-reduce
437
455
  const previousOk = await previous;
438
456
  // Don't start tests after an interrupt.
439
457
  if (this.interrupted) {
@@ -3,9 +3,9 @@ const path = require('path');
3
3
  const cleanYamlObject = require('clean-yaml-object');
4
4
  const concordance = require('concordance');
5
5
  const isError = require('is-error');
6
+ const slash = require('slash');
6
7
  const StackUtils = require('stack-utils');
7
8
  const assert = require('./assert');
8
- const beautifyStack = require('./beautify-stack');
9
9
  const concordanceOptions = require('./concordance-options').default;
10
10
 
11
11
  function isAvaAssertionError(source) {
@@ -17,13 +17,29 @@ function filter(propertyName, isRoot) {
17
17
  }
18
18
 
19
19
  const stackUtils = new StackUtils();
20
- function extractSource(stack) {
21
- if (!stack) {
20
+ function extractSource(stack, testFile) {
21
+ if (!stack || !testFile) {
22
22
  return null;
23
23
  }
24
24
 
25
- const firstStackLine = stack.split('\n')[0];
26
- return stackUtils.parseLine(firstStackLine);
25
+ // Normalize the test file so it matches `callSite.file`.
26
+ const relFile = path.relative(process.cwd(), testFile);
27
+ const normalizedFile = process.platform === 'win32' ? slash(relFile) : relFile;
28
+ for (const line of stack.split('\n')) {
29
+ try {
30
+ const callSite = stackUtils.parseLine(line);
31
+ if (callSite.file === normalizedFile) {
32
+ return {
33
+ isDependency: false,
34
+ isWithinProject: true,
35
+ file: path.resolve(process.cwd(), callSite.file),
36
+ line: callSite.line
37
+ };
38
+ }
39
+ } catch {}
40
+ }
41
+
42
+ return null;
27
43
  }
28
44
 
29
45
  function buildSource(source) {
@@ -51,22 +67,19 @@ function buildSource(source) {
51
67
  };
52
68
  }
53
69
 
54
- function trySerializeError(err, shouldBeautifyStack) {
55
- let stack = err.savedError ? err.savedError.stack : err.stack;
56
-
57
- if (shouldBeautifyStack) {
58
- stack = beautifyStack(stack);
59
- }
70
+ function trySerializeError(err, shouldBeautifyStack, testFile) {
71
+ const stack = err.savedError ? err.savedError.stack : err.stack;
60
72
 
61
73
  const retval = {
62
74
  avaAssertionError: isAvaAssertionError(err),
63
75
  nonErrorObject: false,
64
- source: buildSource(extractSource(stack)),
65
- stack
76
+ source: extractSource(stack, testFile),
77
+ stack,
78
+ shouldBeautifyStack
66
79
  };
67
80
 
68
81
  if (err.actualStack) {
69
- retval.stack = shouldBeautifyStack ? beautifyStack(err.actualStack) : err.actualStack;
82
+ retval.stack = err.actualStack;
70
83
  }
71
84
 
72
85
  if (retval.avaAssertionError) {
@@ -133,7 +146,7 @@ function trySerializeError(err, shouldBeautifyStack) {
133
146
  return retval;
134
147
  }
135
148
 
136
- function serializeError(origin, shouldBeautifyStack, err) {
149
+ function serializeError(origin, shouldBeautifyStack, err, testFile) {
137
150
  if (!isError(err)) {
138
151
  return {
139
152
  avaAssertionError: false,
@@ -143,8 +156,8 @@ function serializeError(origin, shouldBeautifyStack, err) {
143
156
  }
144
157
 
145
158
  try {
146
- return trySerializeError(err, shouldBeautifyStack);
147
- } catch (_) {
159
+ return trySerializeError(err, shouldBeautifyStack, testFile);
160
+ } catch {
148
161
  const replacement = new Error(`${origin}: Could not serialize error`);
149
162
  return {
150
163
  avaAssertionError: false,
package/lib/test.js CHANGED
@@ -39,7 +39,8 @@ class ExecutionContext extends assert.Assertions {
39
39
  compareWithSnapshot: options => {
40
40
  return test.compareWithSnapshot(options);
41
41
  },
42
- powerAssert: test.powerAssert
42
+ powerAssert: test.powerAssert,
43
+ experiments: test.experiments
43
44
  });
44
45
  testMap.set(this, test);
45
46
 
@@ -68,6 +69,10 @@ class ExecutionContext extends assert.Assertions {
68
69
  test.timeout(ms);
69
70
  };
70
71
 
72
+ this.teardown = callback => {
73
+ test.addTeardown(callback);
74
+ };
75
+
71
76
  this.try = async (...attemptArgs) => {
72
77
  const {args, buildTitle, implementations, receivedImplementationArray} = parseTestArgs(attemptArgs);
73
78
 
@@ -193,12 +198,14 @@ class Test {
193
198
  this.experiments = options.experiments || {};
194
199
  this.failWithoutAssertions = options.failWithoutAssertions;
195
200
  this.fn = options.fn;
201
+ this.isHook = options.isHook === true;
196
202
  this.metadata = options.metadata;
197
203
  this.powerAssert = options.powerAssert;
198
204
  this.title = options.title;
199
205
  this.testPassed = options.testPassed;
200
206
  this.registerUniqueTitle = options.registerUniqueTitle;
201
207
  this.logs = [];
208
+ this.teardowns = [];
202
209
 
203
210
  const {snapshotBelongsTo = this.title, nextSnapshotIndex = 0} = options;
204
211
  this.snapshotBelongsTo = snapshotBelongsTo;
@@ -457,6 +464,40 @@ class Test {
457
464
  this.timeoutTimer = null;
458
465
  }
459
466
 
467
+ addTeardown(callback) {
468
+ if (this.isHook) {
469
+ this.saveFirstError(new Error('`t.teardown()` is not allowed in hooks'));
470
+ return;
471
+ }
472
+
473
+ if (this.finishing) {
474
+ this.saveFirstError(new Error('`t.teardown()` cannot be used during teardown'));
475
+ return;
476
+ }
477
+
478
+ if (typeof callback !== 'function') {
479
+ throw new TypeError('Expected a function');
480
+ }
481
+
482
+ this.teardowns.push(callback);
483
+ }
484
+
485
+ async runTeardowns() {
486
+ const teardowns = [...this.teardowns];
487
+
488
+ if (this.experiments.reverseTeardowns) {
489
+ teardowns.reverse();
490
+ }
491
+
492
+ for (const teardown of teardowns) {
493
+ try {
494
+ await teardown(); // eslint-disable-line no-await-in-loop
495
+ } catch (error) {
496
+ this.saveFirstError(error);
497
+ }
498
+ }
499
+ }
500
+
460
501
  verifyPlan() {
461
502
  if (!this.assertError && this.planCount !== null && this.planCount !== this.assertCount) {
462
503
  this.saveFirstError(new assert.AssertionError({
@@ -670,6 +711,7 @@ class Test {
670
711
  this.clearTimeout();
671
712
  this.verifyPlan();
672
713
  this.verifyAssertions();
714
+ await this.runTeardowns();
673
715
 
674
716
  this.duration = nowAndTimers.now() - this.startedAt;
675
717
 
package/lib/watcher.js CHANGED
@@ -85,6 +85,9 @@ class Watcher {
85
85
  this.runVector = 0;
86
86
  this.previousFiles = [];
87
87
  this.globs = {cwd: projectDir, ...globs};
88
+
89
+ const patternFilters = filter.map(({pattern}) => pattern);
90
+
88
91
  this.providers = providers.filter(({level}) => level >= providerLevels.pathRewrites);
89
92
  this.run = (specificFiles = [], updateSnapshots = false) => {
90
93
  const clearLogOnNextRun = this.clearLogOnNextRun && this.runVector > 0;
@@ -106,7 +109,7 @@ class Watcher {
106
109
  }
107
110
 
108
111
  if (filter.length > 0) {
109
- specificFiles = applyTestFileFilter({cwd: projectDir, filter, testFiles: specificFiles});
112
+ specificFiles = applyTestFileFilter({cwd: projectDir, filter: patternFilters, testFiles: specificFiles});
110
113
  }
111
114
 
112
115
  this.pruneFailures(specificFiles);
@@ -0,0 +1,90 @@
1
+ function parse(file) {
2
+ const fs = require('fs');
3
+ const acorn = require('acorn');
4
+ const walk = require('acorn-walk');
5
+
6
+ const ast = acorn.parse(fs.readFileSync(file, 'utf8'), {
7
+ ecmaVersion: 11,
8
+ locations: true
9
+ });
10
+
11
+ const locations = [];
12
+ walk.simple(ast, {
13
+ CallExpression(node) {
14
+ locations.push(node.loc);
15
+ }
16
+ });
17
+
18
+ // Walking is depth-first, but we want to sort these breadth-first.
19
+ locations.sort((a, b) => {
20
+ if (a.start.line === b.start.line) {
21
+ return a.start.column - b.start.column;
22
+ }
23
+
24
+ return a.start.line - b.start.line;
25
+ });
26
+
27
+ return locations;
28
+ }
29
+
30
+ function findTest(locations, declaration) {
31
+ // Find all calls that span the test declaration.
32
+ const spans = locations.filter(loc => {
33
+ if (loc.start.line > declaration.line || loc.end.line < declaration.line) {
34
+ return false;
35
+ }
36
+
37
+ if (loc.start.line === declaration.line && loc.start.column > declaration.column) {
38
+ return false;
39
+ }
40
+
41
+ if (loc.end.line === declaration.line && loc.end.column < declaration.column) {
42
+ return false;
43
+ }
44
+
45
+ return true;
46
+ });
47
+
48
+ // Locations should be sorted by source order, so the last span must be the test.
49
+ return spans.pop();
50
+ }
51
+
52
+ const range = (start, end) => new Array(end - start + 1).fill(start).map((element, index) => element + index);
53
+
54
+ module.exports = ({file, lineNumbers = []}) => {
55
+ if (lineNumbers.length === 0) {
56
+ return undefined;
57
+ }
58
+
59
+ // Avoid loading these until we actually need to select tests by line number.
60
+ const callsites = require('callsites');
61
+ const sourceMapSupport = require('source-map-support');
62
+
63
+ const locations = parse(file);
64
+ const selected = new Set(lineNumbers);
65
+
66
+ return () => {
67
+ // Assume this is called from a test declaration, which is located in the file.
68
+ // If not… don't select the test!
69
+ const callSite = callsites().find(callSite => callSite.getFileName() === file);
70
+ if (!callSite) {
71
+ return false;
72
+ }
73
+
74
+ // FIXME: This assumes the callSite hasn't already been adjusted. It's likely
75
+ // that if `source-map-support/register` has been loaded, this would result
76
+ // in the wrong location.
77
+ const sourceCallSite = sourceMapSupport.wrapCallSite(callSite);
78
+ const start = {
79
+ line: sourceCallSite.getLineNumber(),
80
+ column: sourceCallSite.getColumnNumber() - 1 // Use 0-indexed columns.
81
+ };
82
+
83
+ const test = findTest(locations, start);
84
+ if (!test) {
85
+ return false;
86
+ }
87
+
88
+ return range(test.start.line, test.end.line).some(line => selected.has(line));
89
+ };
90
+ };
@@ -30,6 +30,7 @@ ipc.options.then(async options => {
30
30
  const Runner = require('../runner');
31
31
  const serializeError = require('../serialize-error');
32
32
  const dependencyTracking = require('./dependency-tracker');
33
+ const lineNumberSelection = require('./line-numbers');
33
34
 
34
35
  async function exit(code) {
35
36
  if (!process.exitCode) {
@@ -41,7 +42,21 @@ ipc.options.then(async options => {
41
42
  process.exit(); // eslint-disable-line unicorn/no-process-exit
42
43
  }
43
44
 
45
+ // TODO: Initialize providers here, then pass to lineNumberSelection() so they
46
+ // can be used to parse the test file.
47
+ let checkSelectedByLineNumbers;
48
+ try {
49
+ checkSelectedByLineNumbers = lineNumberSelection({
50
+ file: options.file,
51
+ lineNumbers: options.lineNumbers
52
+ });
53
+ } catch (error) {
54
+ ipc.send({type: 'line-number-selection-error', err: serializeError('Line number selection error', false, error, options.file)});
55
+ checkSelectedByLineNumbers = () => false;
56
+ }
57
+
44
58
  const runner = new Runner({
59
+ checkSelectedByLineNumbers,
45
60
  experiments: options.experiments,
46
61
  failFast: options.failFast,
47
62
  failWithoutAssertions: options.failWithoutAssertions,
@@ -70,7 +85,7 @@ ipc.options.then(async options => {
70
85
  runner.on('stateChange', state => ipc.send(state));
71
86
 
72
87
  runner.on('error', error => {
73
- ipc.send({type: 'internal-error', err: serializeError('Internal runner error', false, error)});
88
+ ipc.send({type: 'internal-error', err: serializeError('Internal runner error', false, error, runner.file)});
74
89
  exit(1);
75
90
  });
76
91
 
@@ -81,7 +96,7 @@ ipc.options.then(async options => {
81
96
  ipc.send({type: 'touched-files', files: touchedFiles});
82
97
  }
83
98
  } catch (error) {
84
- ipc.send({type: 'internal-error', err: serializeError('Internal runner error', false, error)});
99
+ ipc.send({type: 'internal-error', err: serializeError('Internal runner error', false, error, runner.file)});
85
100
  exit(1);
86
101
  return;
87
102
  }
@@ -90,7 +105,7 @@ ipc.options.then(async options => {
90
105
  currentlyUnhandled()
91
106
  .filter(rejection => !attributedRejections.has(rejection.promise))
92
107
  .forEach(rejection => {
93
- ipc.send({type: 'unhandled-rejection', err: serializeError('Unhandled rejection', true, rejection.reason)});
108
+ ipc.send({type: 'unhandled-rejection', err: serializeError('Unhandled rejection', true, rejection.reason, runner.file)});
94
109
  });
95
110
 
96
111
  exit(0);
@@ -102,7 +117,7 @@ ipc.options.then(async options => {
102
117
  return;
103
118
  }
104
119
 
105
- ipc.send({type: 'uncaught-exception', err: serializeError('Uncaught exception', true, error)});
120
+ ipc.send({type: 'uncaught-exception', err: serializeError('Uncaught exception', true, error, runner.file)});
106
121
  exit(1);
107
122
  });
108
123
 
@@ -181,7 +196,7 @@ ipc.options.then(async options => {
181
196
  if (Reflect.has(mod, Symbol.for('esm:package'))) {
182
197
  requireFn = mod(module);
183
198
  }
184
- } catch (_) {}
199
+ } catch {}
185
200
  }
186
201
 
187
202
  // Install dependency tracker after the require configuration has been evaluated
@@ -207,7 +222,7 @@ ipc.options.then(async options => {
207
222
  exit(1);
208
223
  }
209
224
  } catch (error) {
210
- ipc.send({type: 'uncaught-exception', err: serializeError('Uncaught exception', true, error)});
225
+ ipc.send({type: 'uncaught-exception', err: serializeError('Uncaught exception', true, error, runner.file)});
211
226
  exit(1);
212
227
  }
213
228
  }).catch(error => {
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "ava",
3
- "version": "3.7.1",
4
- "description": "Testing can be a drag. AVA helps you get it done.",
3
+ "version": "3.9.0",
4
+ "description": "Node.js test runner that lets you develop with confidence.",
5
5
  "license": "MIT",
6
6
  "repository": "avajs/ava",
7
7
  "homepage": "https://avajs.dev",
8
8
  "bin": "cli.js",
9
9
  "engines": {
10
- "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=13.5.0"
10
+ "node": ">=10.18.0 <11 || >=12.14.0 <12.17.0 || >=12.17.0 <13 || >=14.0.0"
11
11
  },
12
12
  "scripts": {
13
- "test": "xo && tsd && nyc tap"
13
+ "test": "xo && tsd && c8 --report=none tap && c8 --report=none --no-clean test-ava && c8 report"
14
14
  },
15
15
  "files": [
16
16
  "lib",
@@ -56,51 +56,53 @@
56
56
  ],
57
57
  "dependencies": {
58
58
  "@concordance/react": "^2.0.0",
59
+ "acorn": "^7.3.1",
60
+ "acorn-walk": "^7.1.1",
59
61
  "ansi-styles": "^4.2.1",
60
62
  "arrgv": "^1.0.2",
61
63
  "arrify": "^2.0.1",
62
- "chalk": "^4.0.0",
63
- "chokidar": "^3.3.1",
64
+ "callsites": "^3.1.0",
65
+ "chalk": "^4.1.0",
66
+ "chokidar": "^3.4.0",
64
67
  "chunkd": "^2.0.1",
65
68
  "ci-info": "^2.0.0",
66
69
  "ci-parallel-vars": "^1.0.0",
67
- "clean-stack": "^2.2.0",
68
70
  "clean-yaml-object": "^0.1.0",
69
71
  "cli-cursor": "^3.1.0",
70
72
  "cli-truncate": "^2.1.0",
71
73
  "code-excerpt": "^2.1.1",
72
74
  "common-path-prefix": "^3.0.0",
73
- "concordance": "^4.0.0",
75
+ "concordance": "^5.0.0",
74
76
  "convert-source-map": "^1.7.0",
75
77
  "currently-unhandled": "^0.4.1",
76
78
  "debug": "^4.1.1",
77
79
  "del": "^5.1.0",
78
- "emittery": "^0.6.0",
80
+ "emittery": "^0.7.0",
79
81
  "equal-length": "^1.0.0",
80
82
  "figures": "^3.2.0",
81
- "globby": "^11.0.0",
82
- "ignore-by-default": "^1.0.0",
83
+ "globby": "^11.0.1",
84
+ "ignore-by-default": "^2.0.0",
83
85
  "import-local": "^3.0.2",
84
86
  "indent-string": "^4.0.0",
85
87
  "is-error": "^2.2.2",
86
88
  "is-plain-object": "^3.0.0",
87
- "is-promise": "^2.1.0",
89
+ "is-promise": "^4.0.0",
88
90
  "lodash": "^4.17.15",
89
- "matcher": "^2.1.0",
91
+ "matcher": "^3.0.0",
90
92
  "md5-hex": "^3.0.1",
91
93
  "mem": "^6.1.0",
92
94
  "ms": "^2.1.2",
93
- "ora": "^4.0.3",
95
+ "ora": "^4.0.4",
94
96
  "p-map": "^4.0.0",
95
97
  "picomatch": "^2.2.2",
96
98
  "pkg-conf": "^3.1.0",
97
99
  "plur": "^4.0.0",
98
- "pretty-ms": "^6.0.1",
100
+ "pretty-ms": "^7.0.0",
99
101
  "read-pkg": "^5.2.0",
100
102
  "resolve-cwd": "^3.0.0",
101
103
  "slash": "^3.0.0",
102
- "source-map-support": "^0.5.16",
103
- "stack-utils": "^2.0.1",
104
+ "source-map-support": "^0.5.19",
105
+ "stack-utils": "^2.0.2",
104
106
  "strip-ansi": "^6.0.0",
105
107
  "supertap": "^1.0.0",
106
108
  "temp-dir": "^2.0.0",
@@ -111,18 +113,20 @@
111
113
  },
112
114
  "devDependencies": {
113
115
  "@ava/babel": "^1.0.1",
116
+ "@ava/test": "github:avajs/test",
117
+ "@babel/plugin-proposal-do-expressions": "^7.10.1",
114
118
  "@sinonjs/fake-timers": "^6.0.1",
115
119
  "ansi-escapes": "^4.3.1",
120
+ "c8": "^7.2.0",
116
121
  "delay": "^4.3.0",
117
122
  "esm": "^3.2.25",
118
- "execa": "^4.0.0",
123
+ "execa": "^4.0.2",
119
124
  "get-stream": "^5.1.0",
120
- "nyc": "^15.0.1",
121
- "p-event": "^4.1.0",
125
+ "p-event": "^4.2.0",
122
126
  "proxyquire": "^2.1.3",
123
127
  "react": "^16.13.1",
124
128
  "react-test-renderer": "^16.13.1",
125
- "replace-string": "^3.0.0",
129
+ "replace-string": "^3.1.0",
126
130
  "sinon": "^9.0.2",
127
131
  "source-map-fixtures": "^2.1.0",
128
132
  "tap": "^14.10.7",
@@ -130,57 +134,8 @@
130
134
  "tempy": "^0.5.0",
131
135
  "touch": "^3.1.0",
132
136
  "tsd": "^0.11.0",
133
- "typescript": "^3.8.3",
134
- "xo": "^0.29.1",
137
+ "typescript": "^3.9.5",
138
+ "xo": "^0.32.0",
135
139
  "zen-observable": "^0.8.15"
136
- },
137
- "xo": {
138
- "ignores": [
139
- "media/**",
140
- "test-tap/fixture/ava-paths/target/test.js",
141
- "test-tap/fixture/{source-map-initial,syntax-error}.js",
142
- "test-tap/fixture/snapshots/test-sourcemaps/build/**",
143
- "test-tap/fixture/power-assert.js"
144
- ],
145
- "rules": {
146
- "no-use-extend-native/no-use-extend-native": "off",
147
- "@typescript-eslint/no-var-requires": "off"
148
- },
149
- "overrides": [
150
- {
151
- "files": "*.d.ts",
152
- "rules": {
153
- "@typescript-eslint/member-ordering": "off",
154
- "@typescript-eslint/prefer-readonly-parameter-types": "off",
155
- "@typescript-eslint/prefer-function-type": "off",
156
- "@typescript-eslint/unified-signatures": "off"
157
- }
158
- },
159
- {
160
- "files": "test-{d,tap}/**/*.ts",
161
- "rules": {
162
- "@typescript-eslint/explicit-function-return-type": "off",
163
- "@typescript-eslint/no-empty-function": "off",
164
- "@typescript-eslint/no-unsafe-call": "off",
165
- "@typescript-eslint/no-unsafe-member-access": "off",
166
- "@typescript-eslint/no-unsafe-return": "off",
167
- "@typescript-eslint/no-unused-vars": "off",
168
- "@typescript-eslint/prefer-readonly-parameter-types": "off",
169
- "no-unused-vars": "off"
170
- }
171
- },
172
- {
173
- "files": "test-tap/**/*.js",
174
- "rules": {
175
- "promise/prefer-await-to-then": "off"
176
- }
177
- },
178
- {
179
- "files": "test-tap/fixture/**/*.js",
180
- "rules": {
181
- "import/no-extraneous-dependencies": "off"
182
- }
183
- }
184
- ]
185
140
  }
186
141
  }