Skip to content

Commit 21e0fca

Browse files
committed
Remove test.cb()
Fixes #2387.
1 parent 14ec281 commit 21e0fca

30 files changed

+95
-739
lines changed

docs/01-writing-tests.md

+4-10
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ test('handles observables', t => {
9393

9494
## Callback support
9595

96-
AVA supports using `t.end` as the final callback when using Node.js-style error-first callback APIs. AVA will consider any truthy value passed as the first argument to `t.end` to be an error. Note that `t.end` requires "callback mode", which can be enabled by using the `test.cb` chain.
96+
*👉 AVA 4 removes support for `test.cb()` and `t.end()`.*
97+
98+
AVA 3 supports using `t.end` as the final callback when using Node.js-style error-first callback APIs. AVA will consider any truthy value passed as the first argument to `t.end` to be an error. Note that `t.end` requires "callback mode", which can be enabled by using the `test.cb` chain.
9799

98100
```js
99101
test.cb('data.txt can be read', t => {
@@ -223,7 +225,7 @@ test('title', t => {
223225
});
224226
```
225227

226-
Hooks can be synchronous or asynchronous, just like tests. To make a hook asynchronous return a promise or observable, use an async function, or enable callback mode via `test.before.cb()`, `test.beforeEach.cb()` etc.
228+
Hooks can be synchronous or asynchronous, just like tests. To make a hook asynchronous return a promise or observable, or use an async function.
227229

228230
```js
229231
test.before(async t => {
@@ -233,14 +235,6 @@ test.before(async t => {
233235
test.after(t => {
234236
return new Promise(/* ... */);
235237
});
236-
237-
test.beforeEach.cb(t => {
238-
setTimeout(t.end);
239-
});
240-
241-
test.afterEach.cb(t => {
242-
setTimeout(t.end);
243-
});
244238
```
245239

246240
Keep in mind that the `.beforeEach()` and `.afterEach()` hooks run just before and after a test is run, and that by default tests run concurrently. This means each multiple `.beforeEach()` hooks may run concurrently. Using `test.serial.beforeEach()` does not change this. If you need to set up global state for each test (like spying on `console.log` [for example](https://github.com/avajs/ava/issues/560)), you'll need to make sure the tests themselves are [run serially](#running-tests-serially).

docs/02-execution-context.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ When used in `test.afterEach()` or `test.afterEach.always()` hooks this tells yo
2828

2929
## `t.end()`
3030

31-
End the test. Only works with `test.cb()`.
31+
End the test. Only works with `test.cb()`. Removed in AVA 4.
3232

3333
## `t.log(...values)`
3434

docs/03-assertions.md

-9
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,6 @@ test('resolves with 3', t => {
4141
t.is(n, 3);
4242
});
4343
});
44-
45-
test.cb('invokes callback', t => {
46-
t.plan(1);
47-
48-
someAsyncFunction(() => {
49-
t.pass();
50-
t.end();
51-
});
52-
});
5344
```
5445

5546
These won't:

docs/08-common-pitfalls.md

+3-12
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,13 @@ test('fetches foo', async t => {
3939
});
4040
```
4141

42-
If you're using callbacks, use [`test.cb`](./01-writing-tests.md#callback-support):
42+
If you're using callbacks, promisify the callback function using something like [`util.promisify()`](https://nodejs.org/dist/latest/docs/api/util.html#util_util_promisify_original):
4343

4444
```js
45-
test.cb('fetches foo', t => {
46-
fetch((err, data) => {
47-
t.is(data, 'foo');
48-
t.end();
49-
});
50-
});
51-
```
52-
53-
Alternatively, promisify the callback function using something like [`pify`](https://github.com/sindresorhus/pify):
45+
const {promisify} = require('util');
5446

55-
```js
5647
test('fetches foo', async t => {
57-
const data = await pify(fetch)();
48+
const data = await promisify(fetch)();
5849
t.is(data, 'foo');
5950
});
6051
```

docs/recipes/typescript.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ test(macro, '2 * 3', 6);
136136
test('providedTitle', macro, '3 * 3', 9);
137137
```
138138

139-
You'll need a different type if you're expecting your macro to be used with a callback test:
139+
You'll need a different type if you're expecting your macro to be used with an AVA 3 callback test:
140140

141141
```ts
142142
import test, {CbMacro} from 'ava';
@@ -166,7 +166,7 @@ test.beforeEach(t => {
166166
t.context.foo = 123; // error: Type '123' is not assignable to type 'string'
167167
});
168168

169-
test.serial.cb.failing('very long chains are properly typed', t => {
169+
test.serial.failing('very long chains are properly typed', t => {
170170
t.context.fooo = 'a value'; // error: Property 'fooo' does not exist on type ''
171171
});
172172

docs/recipes/when-to-use-plan.md

-19
Original file line numberDiff line numberDiff line change
@@ -93,25 +93,6 @@ As stated in the previous example, using the `t.throws()` assertion with `async`
9393

9494
`t.plan()` provides value in the following cases.
9595

96-
### Ensuring multiple callbacks are actually called
97-
98-
```js
99-
test.cb('invokes callbacks', t => {
100-
t.plan(2);
101-
102-
const callbackA = () => {
103-
t.pass();
104-
t.end();
105-
};
106-
107-
const callbackB = () => t.pass();
108-
109-
bThenA(callbackA, callbackB);
110-
});
111-
```
112-
113-
The above ensures `callbackB` is called first (and only once), followed by `callbackA`. Any other combination would not satisfy the plan.
114-
11596
### Tests with branching statements
11697

11798
In most cases, it's a bad idea to use any complex branching inside your tests. A notable exception is for tests that are auto-generated (perhaps from a JSON document). Below `t.plan()` is used to ensure the correctness of the JSON input:

index.d.ts

-149
Original file line numberDiff line numberDiff line change
@@ -464,20 +464,10 @@ export interface TryResult {
464464
discard(options?: CommitDiscardOptions): void;
465465
}
466466

467-
/** The `t` value passed to implementations for tests & hooks declared with the `.cb` modifier. */
468-
export interface CbExecutionContext<Context = unknown> extends ExecutionContext<Context> {
469-
/**
470-
* End the test. If `error` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) the test or hook
471-
* will fail.
472-
*/
473-
end(error?: any): void;
474-
}
475-
476467
// FIXME(novemberborn) Refactor implementations to be different types returning a promise,, subscribable, or void, not a
477468
// single type returning a union. A union with void as a return type doesn't make sense.
478469
export type ImplementationResult = PromiseLike<void> | Subscribable | boolean | void;
479470
export type Implementation<Context = unknown> = (t: ExecutionContext<Context>) => ImplementationResult;
480-
export type CbImplementation<Context = unknown> = (t: CbExecutionContext<Context>) => ImplementationResult;
481471

482472
/** A reusable test or hook implementation. */
483473
export type UntitledMacro<Args extends any[], Context = unknown> = (t: ExecutionContext<Context>, ...args: Args) => ImplementationResult;
@@ -496,19 +486,6 @@ export type EitherMacro<Args extends any[], Context> = Macro<Args, Context> | Un
496486
/** Alias for a single macro, or an array of macros. */
497487
export type OneOrMoreMacros<Args extends any[], Context> = EitherMacro<Args, Context> | [EitherMacro<Args, Context>, ...Array<EitherMacro<Args, Context>>];
498488

499-
/** A reusable test or hook implementation, for tests & hooks declared with the `.cb` modifier. */
500-
export type UntitledCbMacro<Args extends any[], Context = unknown> = (t: CbExecutionContext<Context>, ...args: Args) => ImplementationResult;
501-
502-
/** A reusable test or hook implementation, for tests & hooks declared with the `.cb` modifier. */
503-
export type CbMacro<Args extends any[], Context = unknown> = UntitledCbMacro<Args, Context> & {
504-
title?: (providedTitle: string | undefined, ...args: Args) => string;
505-
};
506-
507-
export type EitherCbMacro<Args extends any[], Context> = CbMacro<Args, Context> | UntitledCbMacro<Args, Context>;
508-
509-
/** Alias for a single macro, or an array of macros, used for tests & hooks declared with the `.cb` modifier. */
510-
export type OneOrMoreCbMacros<Args extends any[], Context> = EitherCbMacro<Args, Context> | [EitherCbMacro<Args, Context>, ...Array<EitherCbMacro<Args, Context>>];
511-
512489
export interface TestInterface<Context = unknown> {
513490
/** Declare a concurrent test. */
514491
(title: string, implementation: Implementation<Context>): void;
@@ -531,9 +508,6 @@ export interface TestInterface<Context = unknown> {
531508
/** Declare a hook that is run before each test. */
532509
beforeEach: BeforeInterface<Context>;
533510

534-
/** Declare a test that must call `t.end()` when it's done. */
535-
cb: CbInterface<Context>;
536-
537511
/** Declare a test that is expected to fail. */
538512
failing: FailingInterface<Context>;
539513

@@ -562,9 +536,6 @@ export interface AfterInterface<Context = unknown> {
562536
/** Declare a hook that is run once, after all tests are done. */
563537
always: AlwaysInterface<Context>;
564538

565-
/** Declare a hook that must call `t.end()` when it's done. */
566-
cb: HookCbInterface<Context>;
567-
568539
skip: HookSkipInterface<Context>;
569540
}
570541

@@ -581,9 +552,6 @@ export interface AlwaysInterface<Context = unknown> {
581552
/** Declare a hook that is run once, after all tests are done. */
582553
<T extends any[]>(macros: OneOrMoreMacros<T, Context>, ...rest: T): void;
583554

584-
/** Declare a hook that must call `t.end()` when it's done. */
585-
cb: HookCbInterface<Context>;
586-
587555
skip: HookSkipInterface<Context>;
588556
}
589557

@@ -600,85 +568,9 @@ export interface BeforeInterface<Context = unknown> {
600568
/** Declare a hook that is run once, before all tests. */
601569
<T extends any[]>(macros: OneOrMoreMacros<T, Context>, ...rest: T): void;
602570

603-
/** Declare a hook that must call `t.end()` when it's done. */
604-
cb: HookCbInterface<Context>;
605-
606571
skip: HookSkipInterface<Context>;
607572
}
608573

609-
export interface CbInterface<Context = unknown> {
610-
/** Declare a test that must call `t.end()` when it's done. */
611-
(title: string, implementation: CbImplementation<Context>): void;
612-
613-
/**
614-
* Declare a concurrent test that uses one or more macros. The macros must call `t.end()` when they're done.
615-
* Additional arguments are passed to the macro.
616-
*/
617-
<T extends any[]>(title: string, macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
618-
619-
/**
620-
* Declare a concurrent test that uses one or more macros. The macros must call `t.end()` when they're done.
621-
* The macro is responsible for generating a unique test title.
622-
*/
623-
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
624-
625-
/** Declare a test that is expected to fail. */
626-
failing: CbFailingInterface<Context>;
627-
628-
only: CbOnlyInterface<Context>;
629-
skip: CbSkipInterface<Context>;
630-
}
631-
632-
export interface CbFailingInterface<Context = unknown> {
633-
/** Declare a test that must call `t.end()` when it's done. The test is expected to fail. */
634-
(title: string, implementation: CbImplementation<Context>): void;
635-
636-
/**
637-
* Declare a test that uses one or more macros. The macros must call `t.end()` when they're done.
638-
* Additional arguments are passed to the macro. The test is expected to fail.
639-
*/
640-
<T extends any[]>(title: string, macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
641-
642-
/**
643-
* Declare a test that uses one or more macros. The macros must call `t.end()` when they're done.
644-
* The test is expected to fail.
645-
*/
646-
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
647-
648-
only: CbOnlyInterface<Context>;
649-
skip: CbSkipInterface<Context>;
650-
}
651-
652-
export interface CbOnlyInterface<Context = unknown> {
653-
/**
654-
* Declare a test that must call `t.end()` when it's done. Only this test and others declared with `.only()` are run.
655-
*/
656-
(title: string, implementation: CbImplementation<Context>): void;
657-
658-
/**
659-
* Declare a test that uses one or more macros. The macros must call `t.end()` when they're done.
660-
* Additional arguments are passed to the macro. Only this test and others declared with `.only()` are run.
661-
*/
662-
<T extends any[]>(title: string, macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
663-
664-
/**
665-
* Declare a test that uses one or more macros. The macros must call `t.end()` when they're done.
666-
* Additional arguments are passed to the macro. Only this test and others declared with `.only()` are run.
667-
*/
668-
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
669-
}
670-
671-
export interface CbSkipInterface<Context = unknown> {
672-
/** Skip this test. */
673-
(title: string, implementation: CbImplementation<Context>): void;
674-
675-
/** Skip this test. */
676-
<T extends any[]>(title: string, macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
677-
678-
/** Skip this test. */
679-
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
680-
}
681-
682574
export interface FailingInterface<Context = unknown> {
683575
/** Declare a concurrent test. The test is expected to fail. */
684576
(title: string, implementation: Implementation<Context>): void;
@@ -699,41 +591,6 @@ export interface FailingInterface<Context = unknown> {
699591
skip: SkipInterface<Context>;
700592
}
701593

702-
export interface HookCbInterface<Context = unknown> {
703-
/** Declare a hook that must call `t.end()` when it's done. */
704-
(implementation: CbImplementation<Context>): void;
705-
706-
/** Declare a hook that must call `t.end()` when it's done. */
707-
(title: string, implementation: CbImplementation<Context>): void;
708-
709-
/**
710-
* Declare a hook that uses one or more macros. The macros must call `t.end()` when they're done.
711-
* Additional arguments are passed to the macro.
712-
*/
713-
<T extends any[]>(title: string, macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
714-
715-
/**
716-
* Declare a hook that uses one or more macros. The macros must call `t.end()` when they're done.
717-
*/
718-
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
719-
720-
skip: HookCbSkipInterface<Context>;
721-
}
722-
723-
export interface HookCbSkipInterface<Context = unknown> {
724-
/** Skip this hook. */
725-
(implementation: CbImplementation<Context>): void;
726-
727-
/** Skip this hook. */
728-
(title: string, implementation: CbImplementation<Context>): void;
729-
730-
/** Skip this hook. */
731-
<T extends any[]>(title: string, macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
732-
733-
/** Skip this hook. */
734-
<T extends any[]>(macros: OneOrMoreCbMacros<T, Context>, ...rest: T): void;
735-
}
736-
737594
export interface HookSkipInterface<Context = unknown> {
738595
/** Skip this hook. */
739596
(implementation: Implementation<Context>): void;
@@ -789,9 +646,6 @@ export interface SerialInterface<Context = unknown> {
789646
/** Declare a serial hook that is run before each test. */
790647
beforeEach: BeforeInterface<Context>;
791648

792-
/** Declare a serial test that must call `t.end()` when it's done. */
793-
cb: CbInterface<Context>;
794-
795649
/** Declare a serial test that is expected to fail. */
796650
failing: FailingInterface<Context>;
797651

@@ -842,9 +696,6 @@ export const before: BeforeInterface;
842696
/** Call to declare a hook that is run before each test, or chain to declare modifiers. */
843697
export const beforeEach: BeforeInterface;
844698

845-
/** Call to declare a test that must invoke `t.end()` when it's done, or chain to declare modifiers. */
846-
export const cb: CbInterface;
847-
848699
/** Call to declare a test that is expected to fail, or chain to declare modifiers. */
849700
export const failing: FailingInterface;
850701

lib/create-chain.js

-16
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,10 @@ function createHookChain(hook, isAfterHook) {
4848
// * `skip` must come at the end
4949
// * no `only`
5050
// * no repeating
51-
extendChain(hook, 'cb', 'callback');
5251
extendChain(hook, 'skip', 'skipped');
53-
extendChain(hook.cb, 'skip', 'skipped');
5452
if (isAfterHook) {
5553
extendChain(hook, 'always');
56-
extendChain(hook.always, 'cb', 'callback');
5754
extendChain(hook.always, 'skip', 'skipped');
58-
extendChain(hook.always.cb, 'skip', 'skipped');
5955
}
6056

6157
return hook;
@@ -69,27 +65,15 @@ function createChain(fn, defaults, meta) {
6965
// * `only` and `skip` cannot be chained together
7066
// * no repeating
7167
const root = startChain('test', fn, {...defaults, type: 'test'});
72-
extendChain(root, 'cb', 'callback');
7368
extendChain(root, 'failing');
7469
extendChain(root, 'only', 'exclusive');
7570
extendChain(root, 'serial');
7671
extendChain(root, 'skip', 'skipped');
77-
extendChain(root.cb, 'failing');
78-
extendChain(root.cb, 'only', 'exclusive');
79-
extendChain(root.cb, 'skip', 'skipped');
80-
extendChain(root.cb.failing, 'only', 'exclusive');
81-
extendChain(root.cb.failing, 'skip', 'skipped');
8272
extendChain(root.failing, 'only', 'exclusive');
8373
extendChain(root.failing, 'skip', 'skipped');
84-
extendChain(root.serial, 'cb', 'callback');
8574
extendChain(root.serial, 'failing');
8675
extendChain(root.serial, 'only', 'exclusive');
8776
extendChain(root.serial, 'skip', 'skipped');
88-
extendChain(root.serial.cb, 'failing');
89-
extendChain(root.serial.cb, 'only', 'exclusive');
90-
extendChain(root.serial.cb, 'skip', 'skipped');
91-
extendChain(root.serial.cb.failing, 'only', 'exclusive');
92-
extendChain(root.serial.cb.failing, 'skip', 'skipped');
9377
extendChain(root.serial.failing, 'only', 'exclusive');
9478
extendChain(root.serial.failing, 'skip', 'skipped');
9579

0 commit comments

Comments
 (0)