ava 2.0.0 → 2.4.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/eslint-plugin-helper.js +26 -7
- package/index.d.ts +96 -23
- package/lib/api.js +17 -3
- package/lib/assert.js +21 -25
- package/lib/babel-pipeline.js +27 -15
- package/lib/cli.js +32 -5
- package/lib/fork.js +1 -0
- package/lib/globs.js +4 -4
- package/lib/load-config.js +41 -13
- package/lib/parse-test-args.js +15 -0
- package/lib/reporters/mini.js +5 -0
- package/lib/reporters/tap.js +23 -4
- package/lib/reporters/verbose.js +3 -0
- package/lib/runner.js +29 -27
- package/lib/serialize-error.js +7 -2
- package/lib/snapshot-manager.js +39 -20
- package/lib/test.js +236 -31
- package/lib/watcher.js +5 -4
- package/lib/worker/fake-tty-has-colors.js +19 -0
- package/lib/worker/fake-tty.js +59 -13
- package/lib/worker/subprocess.js +1 -0
- package/package.json +52 -45
- package/profile.js +8 -5
- package/readme.md +4 -2
package/eslint-plugin-helper.js
CHANGED
|
@@ -4,15 +4,34 @@ const normalizeExtensions = require('./lib/extensions');
|
|
|
4
4
|
const {hasExtension, normalizeGlobs, classify} = require('./lib/globs');
|
|
5
5
|
const loadConfig = require('./lib/load-config');
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const configCache = new Map();
|
|
8
|
+
const helperCache = new Map();
|
|
8
9
|
|
|
9
|
-
function load(projectDir) {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
function load(projectDir, overrides) {
|
|
11
|
+
const cacheKey = `${JSON.stringify(overrides)}\n${projectDir}`;
|
|
12
|
+
if (helperCache.has(cacheKey)) {
|
|
13
|
+
return helperCache.get(cacheKey);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let conf;
|
|
17
|
+
let babelConfig;
|
|
18
|
+
if (configCache.has(projectDir)) {
|
|
19
|
+
({conf, babelConfig} = configCache.get(projectDir));
|
|
20
|
+
} else {
|
|
21
|
+
conf = loadConfig({resolveFrom: projectDir});
|
|
22
|
+
babelConfig = babelPipeline.validate(conf.babel);
|
|
23
|
+
configCache.set(projectDir, {conf, babelConfig});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (overrides) {
|
|
27
|
+
conf = {...conf, ...overrides};
|
|
28
|
+
if (overrides.extensions) {
|
|
29
|
+
// Ignore extensions from the Babel config. Assume all extensions are
|
|
30
|
+
// provided in the override.
|
|
31
|
+
babelConfig = null;
|
|
32
|
+
}
|
|
12
33
|
}
|
|
13
34
|
|
|
14
|
-
const conf = loadConfig(projectDir);
|
|
15
|
-
const babelConfig = babelPipeline.validate(conf.babel);
|
|
16
35
|
const extensions = normalizeExtensions(conf.extensions || [], babelConfig);
|
|
17
36
|
const globs = {cwd: projectDir, ...normalizeGlobs(conf.files, conf.helpers, conf.sources, extensions.all)};
|
|
18
37
|
|
|
@@ -30,7 +49,7 @@ function load(projectDir) {
|
|
|
30
49
|
return classify(`${importPath}.${globs.extensions[0]}`, globs);
|
|
31
50
|
}
|
|
32
51
|
});
|
|
33
|
-
|
|
52
|
+
helperCache.set(cacheKey, helper);
|
|
34
53
|
return helper;
|
|
35
54
|
}
|
|
36
55
|
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="node"/>
|
|
2
|
+
|
|
1
3
|
export interface ObservableLike {
|
|
2
4
|
subscribe(observer: (value: unknown) => void): void;
|
|
3
5
|
[Symbol.observable](): ObservableLike;
|
|
@@ -23,6 +25,13 @@ export type ThrowsExpectation = {
|
|
|
23
25
|
name?: string;
|
|
24
26
|
};
|
|
25
27
|
|
|
28
|
+
export type CommitDiscardOptions = {
|
|
29
|
+
/**
|
|
30
|
+
* Whether the logs should be included in those of the parent test.
|
|
31
|
+
*/
|
|
32
|
+
retainLogs?: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
26
35
|
/** Options that can be passed to the `t.snapshot()` assertion. */
|
|
27
36
|
export type SnapshotOptions = {
|
|
28
37
|
/** If provided and not an empty string, used to select the snapshot to compare the `expected` value against. */
|
|
@@ -351,7 +360,7 @@ export interface TruthyAssertion {
|
|
|
351
360
|
}
|
|
352
361
|
|
|
353
362
|
/** The `t` value passed to test & hook implementations. */
|
|
354
|
-
export interface ExecutionContext<Context =
|
|
363
|
+
export interface ExecutionContext<Context = unknown> extends Assertions {
|
|
355
364
|
/** Test context, shared with hooks. */
|
|
356
365
|
context: Context;
|
|
357
366
|
|
|
@@ -361,6 +370,7 @@ export interface ExecutionContext<Context = {}> extends Assertions {
|
|
|
361
370
|
log: LogFn;
|
|
362
371
|
plan: PlanFn;
|
|
363
372
|
timeout: TimeoutFn;
|
|
373
|
+
try: TryFn<Context>;
|
|
364
374
|
}
|
|
365
375
|
|
|
366
376
|
export interface LogFn {
|
|
@@ -390,8 +400,71 @@ export interface TimeoutFn {
|
|
|
390
400
|
(ms: number): void;
|
|
391
401
|
}
|
|
392
402
|
|
|
403
|
+
export interface TryFn<Context = unknown> {
|
|
404
|
+
/**
|
|
405
|
+
* Requires opt-in. Attempt to run some assertions. The result must be explicitly committed or discarded or else
|
|
406
|
+
* the test will fail. A macro may be provided. The title may help distinguish attempts from
|
|
407
|
+
* one another.
|
|
408
|
+
*/
|
|
409
|
+
<Args extends any[]>(title: string, fn: EitherMacro<Args, Context>, ...args: Args): Promise<TryResult>;
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Requires opt-in. Attempt to run some assertions. The result must be explicitly committed or discarded or else
|
|
413
|
+
* the test will fail. A macro may be provided. The title may help distinguish attempts from
|
|
414
|
+
* one another.
|
|
415
|
+
*/
|
|
416
|
+
<Args extends any[]>(title: string, fn: [EitherMacro<Args, Context>, ...EitherMacro<Args, Context>[]], ...args: Args): Promise<TryResult[]>;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Requires opt-in. Attempt to run some assertions. The result must be explicitly committed or discarded or else
|
|
420
|
+
* the test will fail. A macro may be provided.
|
|
421
|
+
*/
|
|
422
|
+
<Args extends any[]>(fn: EitherMacro<Args, Context>, ...args: Args): Promise<TryResult>;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Requires opt-in. Attempt to run some assertions. The result must be explicitly committed or discarded or else
|
|
426
|
+
* the test will fail. A macro may be provided.
|
|
427
|
+
*/
|
|
428
|
+
<Args extends any[]>(fn: [EitherMacro<Args, Context>, ...EitherMacro<Args, Context>[]], ...args: Args): Promise<TryResult[]>;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export interface AssertionError extends Error {}
|
|
432
|
+
|
|
433
|
+
export interface TryResult {
|
|
434
|
+
/**
|
|
435
|
+
* Title of the attempt, helping you tell attempts aparts.
|
|
436
|
+
*/
|
|
437
|
+
title: string;
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Indicates whether all assertions passed, or at least one failed.
|
|
441
|
+
*/
|
|
442
|
+
passed: boolean;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Errors raised for each failed assertion.
|
|
446
|
+
*/
|
|
447
|
+
errors: AssertionError[];
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Logs created during the attempt using `t.log()`. Contains formatted values.
|
|
451
|
+
*/
|
|
452
|
+
logs: string[];
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Commit the attempt. Counts as one assertion for the plan count. If the
|
|
456
|
+
* attempt failed, calling this will also cause your test to fail.
|
|
457
|
+
*/
|
|
458
|
+
commit(options?: CommitDiscardOptions): void;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Discard the attempt.
|
|
462
|
+
*/
|
|
463
|
+
discard(options?: CommitDiscardOptions): void;
|
|
464
|
+
}
|
|
465
|
+
|
|
393
466
|
/** The `t` value passed to implementations for tests & hooks declared with the `.cb` modifier. */
|
|
394
|
-
export interface CbExecutionContext<Context =
|
|
467
|
+
export interface CbExecutionContext<Context = unknown> extends ExecutionContext<Context> {
|
|
395
468
|
/**
|
|
396
469
|
* End the test. If `error` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) the test or hook
|
|
397
470
|
* will fail.
|
|
@@ -400,14 +473,14 @@ export interface CbExecutionContext<Context = {}> extends ExecutionContext<Conte
|
|
|
400
473
|
}
|
|
401
474
|
|
|
402
475
|
export type ImplementationResult = PromiseLike<void> | ObservableLike | void;
|
|
403
|
-
export type Implementation<Context =
|
|
404
|
-
export type CbImplementation<Context =
|
|
476
|
+
export type Implementation<Context = unknown> = (t: ExecutionContext<Context>) => ImplementationResult;
|
|
477
|
+
export type CbImplementation<Context = unknown> = (t: CbExecutionContext<Context>) => ImplementationResult;
|
|
405
478
|
|
|
406
479
|
/** A reusable test or hook implementation. */
|
|
407
|
-
export type UntitledMacro<Args extends any[], Context =
|
|
480
|
+
export type UntitledMacro<Args extends any[], Context = unknown> = (t: ExecutionContext<Context>, ...args: Args) => ImplementationResult;
|
|
408
481
|
|
|
409
482
|
/** A reusable test or hook implementation. */
|
|
410
|
-
export type Macro<Args extends any[], Context =
|
|
483
|
+
export type Macro<Args extends any[], Context = unknown> = UntitledMacro<Args, Context> & {
|
|
411
484
|
/**
|
|
412
485
|
* Implement this function to generate a test (or hook) title whenever this macro is used. `providedTitle` contains
|
|
413
486
|
* the title provided when the test or hook was declared. Also receives the remaining test arguments.
|
|
@@ -421,10 +494,10 @@ export type EitherMacro<Args extends any[], Context> = Macro<Args, Context> | Un
|
|
|
421
494
|
export type OneOrMoreMacros<Args extends any[], Context> = EitherMacro<Args, Context> | [EitherMacro<Args, Context>, ...EitherMacro<Args, Context>[]];
|
|
422
495
|
|
|
423
496
|
/** A reusable test or hook implementation, for tests & hooks declared with the `.cb` modifier. */
|
|
424
|
-
export type UntitledCbMacro<Args extends any[], Context =
|
|
497
|
+
export type UntitledCbMacro<Args extends any[], Context = unknown> = (t: CbExecutionContext<Context>, ...args: Args) => ImplementationResult
|
|
425
498
|
|
|
426
499
|
/** A reusable test or hook implementation, for tests & hooks declared with the `.cb` modifier. */
|
|
427
|
-
export type CbMacro<Args extends any[], Context =
|
|
500
|
+
export type CbMacro<Args extends any[], Context = unknown> = UntitledCbMacro<Args, Context> & {
|
|
428
501
|
title?: (providedTitle: string | undefined, ...args: Args) => string;
|
|
429
502
|
}
|
|
430
503
|
|
|
@@ -433,7 +506,7 @@ export type EitherCbMacro<Args extends any[], Context> = CbMacro<Args, Context>
|
|
|
433
506
|
/** Alias for a single macro, or an array of macros, used for tests & hooks declared with the `.cb` modifier. */
|
|
434
507
|
export type OneOrMoreCbMacros<Args extends any[], Context> = EitherCbMacro<Args, Context> | [EitherCbMacro<Args, Context>, ...EitherCbMacro<Args, Context>[]];
|
|
435
508
|
|
|
436
|
-
export interface TestInterface<Context =
|
|
509
|
+
export interface TestInterface<Context = unknown> {
|
|
437
510
|
/** Declare a concurrent test. */
|
|
438
511
|
(title: string, implementation: Implementation<Context>): void;
|
|
439
512
|
|
|
@@ -470,7 +543,7 @@ export interface TestInterface<Context = {}> {
|
|
|
470
543
|
meta: MetaInterface;
|
|
471
544
|
}
|
|
472
545
|
|
|
473
|
-
export interface AfterInterface<Context =
|
|
546
|
+
export interface AfterInterface<Context = unknown> {
|
|
474
547
|
/** Declare a hook that is run once, after all tests have passed. */
|
|
475
548
|
(implementation: Implementation<Context>): void;
|
|
476
549
|
|
|
@@ -492,7 +565,7 @@ export interface AfterInterface<Context = {}> {
|
|
|
492
565
|
skip: HookSkipInterface<Context>;
|
|
493
566
|
}
|
|
494
567
|
|
|
495
|
-
export interface AlwaysInterface<Context =
|
|
568
|
+
export interface AlwaysInterface<Context = unknown> {
|
|
496
569
|
/** Declare a hook that is run once, after all tests are done. */
|
|
497
570
|
(implementation: Implementation<Context>): void;
|
|
498
571
|
|
|
@@ -511,7 +584,7 @@ export interface AlwaysInterface<Context = {}> {
|
|
|
511
584
|
skip: HookSkipInterface<Context>;
|
|
512
585
|
}
|
|
513
586
|
|
|
514
|
-
export interface BeforeInterface<Context =
|
|
587
|
+
export interface BeforeInterface<Context = unknown> {
|
|
515
588
|
/** Declare a hook that is run once, before all tests. */
|
|
516
589
|
(implementation: Implementation<Context>): void;
|
|
517
590
|
|
|
@@ -530,7 +603,7 @@ export interface BeforeInterface<Context = {}> {
|
|
|
530
603
|
skip: HookSkipInterface<Context>;
|
|
531
604
|
}
|
|
532
605
|
|
|
533
|
-
export interface CbInterface<Context =
|
|
606
|
+
export interface CbInterface<Context = unknown> {
|
|
534
607
|
/** Declare a test that must call `t.end()` when it's done. */
|
|
535
608
|
(title: string, implementation: CbImplementation<Context>): void;
|
|
536
609
|
|
|
@@ -553,7 +626,7 @@ export interface CbInterface<Context = {}> {
|
|
|
553
626
|
skip: CbSkipInterface<Context>;
|
|
554
627
|
}
|
|
555
628
|
|
|
556
|
-
export interface CbFailingInterface<Context =
|
|
629
|
+
export interface CbFailingInterface<Context = unknown> {
|
|
557
630
|
/** Declare a test that must call `t.end()` when it's done. The test is expected to fail. */
|
|
558
631
|
(title: string, implementation: CbImplementation<Context>): void;
|
|
559
632
|
|
|
@@ -573,7 +646,7 @@ export interface CbFailingInterface<Context = {}> {
|
|
|
573
646
|
skip: CbSkipInterface<Context>;
|
|
574
647
|
}
|
|
575
648
|
|
|
576
|
-
export interface CbOnlyInterface<Context =
|
|
649
|
+
export interface CbOnlyInterface<Context = unknown> {
|
|
577
650
|
/**
|
|
578
651
|
* Declare a test that must call `t.end()` when it's done. Only this test and others declared with `.only()` are run.
|
|
579
652
|
*/
|
|
@@ -592,7 +665,7 @@ export interface CbOnlyInterface<Context = {}> {
|
|
|
592
665
|
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
|
|
593
666
|
}
|
|
594
667
|
|
|
595
|
-
export interface CbSkipInterface<Context =
|
|
668
|
+
export interface CbSkipInterface<Context = unknown> {
|
|
596
669
|
/** Skip this test. */
|
|
597
670
|
(title: string, implementation: CbImplementation<Context>): void;
|
|
598
671
|
|
|
@@ -603,7 +676,7 @@ export interface CbSkipInterface<Context = {}> {
|
|
|
603
676
|
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
|
|
604
677
|
}
|
|
605
678
|
|
|
606
|
-
export interface FailingInterface<Context =
|
|
679
|
+
export interface FailingInterface<Context = unknown> {
|
|
607
680
|
/** Declare a concurrent test. The test is expected to fail. */
|
|
608
681
|
(title: string, implementation: Implementation<Context>): void;
|
|
609
682
|
|
|
@@ -623,7 +696,7 @@ export interface FailingInterface<Context = {}> {
|
|
|
623
696
|
skip: SkipInterface<Context>;
|
|
624
697
|
}
|
|
625
698
|
|
|
626
|
-
export interface HookCbInterface<Context =
|
|
699
|
+
export interface HookCbInterface<Context = unknown> {
|
|
627
700
|
/** Declare a hook that must call `t.end()` when it's done. */
|
|
628
701
|
(implementation: CbImplementation<Context>): void;
|
|
629
702
|
|
|
@@ -644,7 +717,7 @@ export interface HookCbInterface<Context = {}> {
|
|
|
644
717
|
skip: HookCbSkipInterface<Context>;
|
|
645
718
|
}
|
|
646
719
|
|
|
647
|
-
export interface HookCbSkipInterface<Context =
|
|
720
|
+
export interface HookCbSkipInterface<Context = unknown> {
|
|
648
721
|
/** Skip this hook. */
|
|
649
722
|
(implementation: CbImplementation<Context>): void;
|
|
650
723
|
|
|
@@ -658,7 +731,7 @@ export interface HookCbSkipInterface<Context = {}> {
|
|
|
658
731
|
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
|
|
659
732
|
}
|
|
660
733
|
|
|
661
|
-
export interface HookSkipInterface<Context =
|
|
734
|
+
export interface HookSkipInterface<Context = unknown> {
|
|
662
735
|
/** Skip this hook. */
|
|
663
736
|
(implementation: Implementation<Context>): void;
|
|
664
737
|
|
|
@@ -672,7 +745,7 @@ export interface HookSkipInterface<Context = {}> {
|
|
|
672
745
|
<T extends any[]>(macros: OneOrMoreMacros<T, Context>, ...rest: T): void;
|
|
673
746
|
}
|
|
674
747
|
|
|
675
|
-
export interface OnlyInterface<Context =
|
|
748
|
+
export interface OnlyInterface<Context = unknown> {
|
|
676
749
|
/** Declare a test. Only this test and others declared with `.only()` are run. */
|
|
677
750
|
(title: string, implementation: Implementation<Context>): void;
|
|
678
751
|
|
|
@@ -689,7 +762,7 @@ export interface OnlyInterface<Context = {}> {
|
|
|
689
762
|
<T extends any[]>(macros: OneOrMoreMacros<T, Context>, ...rest: T): void;
|
|
690
763
|
}
|
|
691
764
|
|
|
692
|
-
export interface SerialInterface<Context =
|
|
765
|
+
export interface SerialInterface<Context = unknown> {
|
|
693
766
|
/** Declare a serial test. */
|
|
694
767
|
(title: string, implementation: Implementation<Context>): void;
|
|
695
768
|
|
|
@@ -724,7 +797,7 @@ export interface SerialInterface<Context = {}> {
|
|
|
724
797
|
todo: TodoDeclaration;
|
|
725
798
|
}
|
|
726
799
|
|
|
727
|
-
export interface SkipInterface<Context =
|
|
800
|
+
export interface SkipInterface<Context = unknown> {
|
|
728
801
|
/** Skip this test. */
|
|
729
802
|
(title: string, implementation: Implementation<Context>): void;
|
|
730
803
|
|
package/lib/api.js
CHANGED
|
@@ -51,6 +51,7 @@ class Api extends Emittery {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
async run(files = [], runtimeOptions = {}) {
|
|
54
|
+
let setupOrGlobError;
|
|
54
55
|
files = files.map(file => path.resolve(this.options.resolveTestsFrom, file));
|
|
55
56
|
|
|
56
57
|
const apiOptions = this.options;
|
|
@@ -106,9 +107,12 @@ class Api extends Emittery {
|
|
|
106
107
|
}
|
|
107
108
|
};
|
|
108
109
|
|
|
110
|
+
let precompiler;
|
|
111
|
+
let helpers;
|
|
112
|
+
|
|
109
113
|
try {
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
precompiler = await this._setupPrecompiler(); // eslint-disable-line require-atomic-updates
|
|
115
|
+
helpers = [];
|
|
112
116
|
if (files.length === 0 || precompiler.enabled) {
|
|
113
117
|
let found;
|
|
114
118
|
if (precompiler.enabled) {
|
|
@@ -122,7 +126,12 @@ class Api extends Emittery {
|
|
|
122
126
|
({tests: files} = found);
|
|
123
127
|
}
|
|
124
128
|
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
files = [];
|
|
131
|
+
setupOrGlobError = error;
|
|
132
|
+
}
|
|
125
133
|
|
|
134
|
+
try {
|
|
126
135
|
if (this.options.parallelRuns) {
|
|
127
136
|
const {currentIndex, totalRuns} = this.options.parallelRuns;
|
|
128
137
|
const fileCount = files.length;
|
|
@@ -140,6 +149,7 @@ class Api extends Emittery {
|
|
|
140
149
|
|
|
141
150
|
await this.emit('run', {
|
|
142
151
|
clearLogOnNextRun: runtimeOptions.clearLogOnNextRun === true,
|
|
152
|
+
experiments: Object.keys(apiOptions.experiments),
|
|
143
153
|
failFastEnabled: failFast,
|
|
144
154
|
filePathPrefix: commonPathPrefix(files),
|
|
145
155
|
files,
|
|
@@ -150,6 +160,10 @@ class Api extends Emittery {
|
|
|
150
160
|
status: runStatus
|
|
151
161
|
});
|
|
152
162
|
|
|
163
|
+
if (setupOrGlobError) {
|
|
164
|
+
throw setupOrGlobError;
|
|
165
|
+
}
|
|
166
|
+
|
|
153
167
|
// Bail out early if no files were found.
|
|
154
168
|
if (files.length === 0) {
|
|
155
169
|
return runStatus;
|
|
@@ -310,7 +324,7 @@ class Api extends Emittery {
|
|
|
310
324
|
const forkExecArgv = execArgv.slice();
|
|
311
325
|
let flagName = '--inspect';
|
|
312
326
|
const oldValue = forkExecArgv[inspectArgIndex];
|
|
313
|
-
if (oldValue.
|
|
327
|
+
if (oldValue.includes('brk')) {
|
|
314
328
|
flagName += '-brk';
|
|
315
329
|
}
|
|
316
330
|
|
package/lib/assert.js
CHANGED
|
@@ -53,25 +53,21 @@ class AssertionError extends Error {
|
|
|
53
53
|
// Reserved for power-assert statements
|
|
54
54
|
this.statements = [];
|
|
55
55
|
|
|
56
|
-
if (opts.
|
|
57
|
-
this.
|
|
56
|
+
if (opts.savedError) {
|
|
57
|
+
this.savedError = opts.savedError;
|
|
58
58
|
} else {
|
|
59
|
-
|
|
60
|
-
Error.stackTraceLimit = Infinity;
|
|
61
|
-
Error.captureStackTrace(this);
|
|
62
|
-
Error.stackTraceLimit = limitBefore;
|
|
59
|
+
this.savedError = getErrorWithLongStackTrace();
|
|
63
60
|
}
|
|
64
61
|
}
|
|
65
62
|
}
|
|
66
63
|
exports.AssertionError = AssertionError;
|
|
67
64
|
|
|
68
|
-
function
|
|
65
|
+
function getErrorWithLongStackTrace() {
|
|
69
66
|
const limitBefore = Error.stackTraceLimit;
|
|
70
67
|
Error.stackTraceLimit = Infinity;
|
|
71
|
-
const
|
|
72
|
-
Error.captureStackTrace(obj, getStack);
|
|
68
|
+
const err = new Error();
|
|
73
69
|
Error.stackTraceLimit = limitBefore;
|
|
74
|
-
return
|
|
70
|
+
return err;
|
|
75
71
|
}
|
|
76
72
|
|
|
77
73
|
function validateExpectations(assertion, expectations, numArgs) { // eslint-disable-line complexity
|
|
@@ -143,12 +139,12 @@ function validateExpectations(assertion, expectations, numArgs) { // eslint-disa
|
|
|
143
139
|
|
|
144
140
|
// Note: this function *must* throw exceptions, since it can be used
|
|
145
141
|
// as part of a pending assertion for promises.
|
|
146
|
-
function assertExpectations({assertion, actual, expectations, message, prefix,
|
|
142
|
+
function assertExpectations({assertion, actual, expectations, message, prefix, savedError}) {
|
|
147
143
|
if (!isError(actual)) {
|
|
148
144
|
throw new AssertionError({
|
|
149
145
|
assertion,
|
|
150
146
|
message,
|
|
151
|
-
|
|
147
|
+
savedError,
|
|
152
148
|
values: [formatWithLabel(`${prefix} exception that is not an error:`, actual)]
|
|
153
149
|
});
|
|
154
150
|
}
|
|
@@ -159,7 +155,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
|
|
|
159
155
|
throw new AssertionError({
|
|
160
156
|
assertion,
|
|
161
157
|
message,
|
|
162
|
-
|
|
158
|
+
savedError,
|
|
163
159
|
actualStack,
|
|
164
160
|
values: [
|
|
165
161
|
formatWithLabel(`${prefix} unexpected exception:`, actual),
|
|
@@ -172,7 +168,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
|
|
|
172
168
|
throw new AssertionError({
|
|
173
169
|
assertion,
|
|
174
170
|
message,
|
|
175
|
-
|
|
171
|
+
savedError,
|
|
176
172
|
actualStack,
|
|
177
173
|
values: [
|
|
178
174
|
formatWithLabel(`${prefix} unexpected exception:`, actual),
|
|
@@ -185,7 +181,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
|
|
|
185
181
|
throw new AssertionError({
|
|
186
182
|
assertion,
|
|
187
183
|
message,
|
|
188
|
-
|
|
184
|
+
savedError,
|
|
189
185
|
actualStack,
|
|
190
186
|
values: [
|
|
191
187
|
formatWithLabel(`${prefix} unexpected exception:`, actual),
|
|
@@ -198,7 +194,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
|
|
|
198
194
|
throw new AssertionError({
|
|
199
195
|
assertion,
|
|
200
196
|
message,
|
|
201
|
-
|
|
197
|
+
savedError,
|
|
202
198
|
actualStack,
|
|
203
199
|
values: [
|
|
204
200
|
formatWithLabel(`${prefix} unexpected exception:`, actual),
|
|
@@ -211,7 +207,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
|
|
|
211
207
|
throw new AssertionError({
|
|
212
208
|
assertion,
|
|
213
209
|
message,
|
|
214
|
-
|
|
210
|
+
savedError,
|
|
215
211
|
actualStack,
|
|
216
212
|
values: [
|
|
217
213
|
formatWithLabel(`${prefix} unexpected exception:`, actual),
|
|
@@ -224,7 +220,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
|
|
|
224
220
|
throw new AssertionError({
|
|
225
221
|
assertion,
|
|
226
222
|
message,
|
|
227
|
-
|
|
223
|
+
savedError,
|
|
228
224
|
actualStack,
|
|
229
225
|
values: [
|
|
230
226
|
formatWithLabel(`${prefix} unexpected exception:`, actual),
|
|
@@ -480,14 +476,14 @@ class Assertions {
|
|
|
480
476
|
}
|
|
481
477
|
|
|
482
478
|
const handlePromise = (promise, wasReturned) => {
|
|
483
|
-
//
|
|
484
|
-
const
|
|
479
|
+
// Create an error object to record the stack before it gets lost in the promise chain.
|
|
480
|
+
const savedError = getErrorWithLongStackTrace();
|
|
485
481
|
// Handle "promise like" objects by casting to a real Promise.
|
|
486
482
|
const intermediate = Promise.resolve(promise).then(value => { // eslint-disable-line promise/prefer-await-to-then
|
|
487
483
|
throw new AssertionError({
|
|
488
484
|
assertion: 'throwsAsync',
|
|
489
485
|
message,
|
|
490
|
-
|
|
486
|
+
savedError,
|
|
491
487
|
values: [formatWithLabel(`${wasReturned ? 'Returned promise' : 'Promise'} resolved with:`, value)]
|
|
492
488
|
});
|
|
493
489
|
}, reason => {
|
|
@@ -497,7 +493,7 @@ class Assertions {
|
|
|
497
493
|
expectations,
|
|
498
494
|
message,
|
|
499
495
|
prefix: `${wasReturned ? 'Returned promise' : 'Promise'} rejected with`,
|
|
500
|
-
|
|
496
|
+
savedError
|
|
501
497
|
});
|
|
502
498
|
return reason;
|
|
503
499
|
});
|
|
@@ -587,14 +583,14 @@ class Assertions {
|
|
|
587
583
|
}
|
|
588
584
|
|
|
589
585
|
const handlePromise = (promise, wasReturned) => {
|
|
590
|
-
//
|
|
591
|
-
const
|
|
586
|
+
// Create an error object to record the stack before it gets lost in the promise chain.
|
|
587
|
+
const savedError = getErrorWithLongStackTrace();
|
|
592
588
|
// Handle "promise like" objects by casting to a real Promise.
|
|
593
589
|
const intermediate = Promise.resolve(promise).then(noop, error => { // eslint-disable-line promise/prefer-await-to-then
|
|
594
590
|
throw new AssertionError({
|
|
595
591
|
assertion: 'notThrowsAsync',
|
|
596
592
|
message,
|
|
597
|
-
|
|
593
|
+
savedError,
|
|
598
594
|
values: [formatWithLabel(`${wasReturned ? 'Returned promise' : 'Promise'} rejected with:`, error)]
|
|
599
595
|
});
|
|
600
596
|
});
|
package/lib/babel-pipeline.js
CHANGED
|
@@ -58,6 +58,26 @@ function validate(conf) {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
function enableParserPlugins(api) {
|
|
62
|
+
api.assertVersion(7);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
name: 'ava-babel-pipeline-enable-parser-plugins',
|
|
66
|
+
manipulateOptions(_, parserOpts) {
|
|
67
|
+
parserOpts.plugins.push(
|
|
68
|
+
'asyncGenerators',
|
|
69
|
+
'bigInt',
|
|
70
|
+
'classPrivateProperties',
|
|
71
|
+
'classProperties',
|
|
72
|
+
'dynamicImport',
|
|
73
|
+
'numericSeparator',
|
|
74
|
+
'objectRestSpread',
|
|
75
|
+
'optionalCatchBinding'
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
61
81
|
// Compare actual values rather than file paths, which should be
|
|
62
82
|
// more reliable.
|
|
63
83
|
function makeValueChecker(ref) {
|
|
@@ -118,7 +138,12 @@ function hashPartialTestConfig({babelrc, config, options: {plugins, presets}}, p
|
|
|
118
138
|
inputs.push(config, stripBomBuf(fs.readFileSync(config)));
|
|
119
139
|
}
|
|
120
140
|
|
|
121
|
-
for (const
|
|
141
|
+
for (const item of [...plugins, ...presets]) {
|
|
142
|
+
if (!item.file) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const {file: {resolved: filename}} = item;
|
|
122
147
|
if (pluginAndPresetHashes.has(filename)) {
|
|
123
148
|
inputs.push(pluginAndPresetHashes.get(filename));
|
|
124
149
|
continue;
|
|
@@ -168,9 +193,6 @@ function build(projectDir, cacheDir, userOptions, compileEnhancements) {
|
|
|
168
193
|
const pluginAndPresetHashes = new Map();
|
|
169
194
|
|
|
170
195
|
const ensureStage4 = wantsStage4(userOptions, projectDir);
|
|
171
|
-
const containsAsyncGenerators = makeValueChecker('@babel/plugin-syntax-async-generators');
|
|
172
|
-
const containsObjectRestSpread = makeValueChecker('@babel/plugin-syntax-object-rest-spread');
|
|
173
|
-
const containsOptionalCatchBinding = makeValueChecker('@babel/plugin-syntax-optional-catch-binding');
|
|
174
196
|
const containsStage4 = makeValueChecker('../stage-4');
|
|
175
197
|
const containsTransformTestFiles = makeValueChecker('@ava/babel-preset-transform-test-files');
|
|
176
198
|
|
|
@@ -193,17 +215,7 @@ function build(projectDir, cacheDir, userOptions, compileEnhancements) {
|
|
|
193
215
|
}
|
|
194
216
|
|
|
195
217
|
const {options: testOptions} = partialTestConfig;
|
|
196
|
-
|
|
197
|
-
testOptions.plugins.unshift(createConfigItem('@babel/plugin-syntax-async-generators', 'plugin'));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (!testOptions.plugins.some(containsObjectRestSpread)) { // TODO: Remove once Babel can parse this syntax unaided.
|
|
201
|
-
testOptions.plugins.unshift(createConfigItem('@babel/plugin-syntax-object-rest-spread', 'plugin'));
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (!testOptions.plugins.some(containsOptionalCatchBinding)) { // TODO: Remove once Babel can parse this syntax unaided.
|
|
205
|
-
testOptions.plugins.unshift(createConfigItem('@babel/plugin-syntax-optional-catch-binding', 'plugin'));
|
|
206
|
-
}
|
|
218
|
+
testOptions.plugins.push(enableParserPlugins);
|
|
207
219
|
|
|
208
220
|
if (ensureStage4 && !testOptions.presets.some(containsStage4)) {
|
|
209
221
|
// Apply last.
|
package/lib/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
3
4
|
const del = require('del');
|
|
4
5
|
const updateNotifier = require('update-notifier');
|
|
5
6
|
const figures = require('figures');
|
|
@@ -7,7 +8,7 @@ const arrify = require('arrify');
|
|
|
7
8
|
const meow = require('meow');
|
|
8
9
|
const Promise = require('bluebird');
|
|
9
10
|
const isCi = require('is-ci');
|
|
10
|
-
const
|
|
11
|
+
const loadConfig = require('./load-config');
|
|
11
12
|
|
|
12
13
|
// Bluebird specific
|
|
13
14
|
Promise.longStackTraces();
|
|
@@ -18,10 +19,17 @@ function exit(message) {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
exports.run = async () => { // eslint-disable-line complexity
|
|
22
|
+
const {flags: {config: configFile}} = meow({ // Process the --config flag first
|
|
23
|
+
autoHelp: false, // --help should get picked up by the next meow invocation.
|
|
24
|
+
flags: {
|
|
25
|
+
config: {type: 'string'}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
21
29
|
let conf = {};
|
|
22
30
|
let confError = null;
|
|
23
31
|
try {
|
|
24
|
-
conf =
|
|
32
|
+
conf = loadConfig({configFile});
|
|
25
33
|
} catch (error) {
|
|
26
34
|
confError = error;
|
|
27
35
|
}
|
|
@@ -35,7 +43,7 @@ exports.run = async () => { // eslint-disable-line complexity
|
|
|
35
43
|
--match, -m Only run tests with matching title (Can be repeated)
|
|
36
44
|
--update-snapshots, -u Update snapshots
|
|
37
45
|
--fail-fast Stop after first test failure
|
|
38
|
-
--timeout, -T Set global timeout
|
|
46
|
+
--timeout, -T Set global timeout (milliseconds or human-readable, e.g. 10s, 2m)
|
|
39
47
|
--serial, -s Run tests serially
|
|
40
48
|
--concurrency, -c Max number of test files running at the same time (Default: CPU cores)
|
|
41
49
|
--verbose, -v Enable verbose output
|
|
@@ -43,6 +51,8 @@ exports.run = async () => { // eslint-disable-line complexity
|
|
|
43
51
|
--color Force color output
|
|
44
52
|
--no-color Disable color output
|
|
45
53
|
--reset-cache Reset AVA's compilation cache and exit
|
|
54
|
+
--config JavaScript file for AVA to read its config from, instead of using package.json
|
|
55
|
+
or ava.config.js files
|
|
46
56
|
|
|
47
57
|
Examples
|
|
48
58
|
ava
|
|
@@ -204,12 +214,31 @@ exports.run = async () => { // eslint-disable-line complexity
|
|
|
204
214
|
|
|
205
215
|
const match = arrify(conf.match);
|
|
206
216
|
const resolveTestsFrom = cli.input.length === 0 ? projectDir : process.cwd();
|
|
217
|
+
|
|
218
|
+
const files = cli.input.map(file => path.relative(resolveTestsFrom, path.resolve(process.cwd(), file)));
|
|
219
|
+
|
|
220
|
+
for (const file of cli.input) {
|
|
221
|
+
try {
|
|
222
|
+
const stats = fs.statSync(file);
|
|
223
|
+
if (!stats.isFile()) {
|
|
224
|
+
exit(`${file} is not a test file.`);
|
|
225
|
+
}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
if (error.code === 'ENOENT') {
|
|
228
|
+
exit(`${file} does not exist.`);
|
|
229
|
+
} else {
|
|
230
|
+
exit(`Error accessing ${file}\n\n${chalk.gray((error && error.stack) || error)}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
207
235
|
const api = new Api({
|
|
208
236
|
babelConfig,
|
|
209
237
|
cacheEnabled: conf.cache !== false,
|
|
210
238
|
color: conf.color,
|
|
211
239
|
compileEnhancements: conf.compileEnhancements !== false,
|
|
212
240
|
concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0,
|
|
241
|
+
experiments: conf.nonSemVerExperiments,
|
|
213
242
|
extensions,
|
|
214
243
|
failFast: conf.failFast,
|
|
215
244
|
failWithoutAssertions: conf.failWithoutAssertions !== false,
|
|
@@ -259,8 +288,6 @@ exports.run = async () => { // eslint-disable-line complexity
|
|
|
259
288
|
});
|
|
260
289
|
});
|
|
261
290
|
|
|
262
|
-
const files = cli.input.map(file => path.relative(resolveTestsFrom, path.resolve(process.cwd(), file)));
|
|
263
|
-
|
|
264
291
|
if (conf.watch) {
|
|
265
292
|
const watcher = new Watcher({
|
|
266
293
|
api,
|