Skip to content

Commit aa35f15

Browse files
authored
Pass an undefined title argument to macro-title functions
Previously, AVA would pass the empty string. By passing an undefined value, the title function can use argument defaults which is more natural. This is a breaking change for users who were concatenating `title`, under the assumption it was an empty string.
1 parent 37390e6 commit aa35f15

File tree

6 files changed

+13
-13
lines changed

6 files changed

+13
-13
lines changed

docs/recipes/typescript.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import test, {Macro} from 'ava';
6666
const macro: Macro = (t, input: string, expected: number) => {
6767
t.is(eval(input), expected);
6868
};
69-
macro.title = (providedTitle: string, input: string, expected: number) => `${providedTitle} ${input} = ${expected}`.trim();
69+
macro.title = (providedTitle = '', input: string, expected: number) => `${providedTitle} ${input} = ${expected}`.trim();
7070

7171
test(macro, '2 + 2', 4);
7272
test(macro, '2 * 3', 6);

index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,13 +390,13 @@ export interface Macro<Context = {}> {
390390
* Implement this function to generate a test (or hook) title whenever this macro is used. `providedTitle` contains
391391
* the title provided when the test or hook was declared. Also receives the remaining test arguments.
392392
*/
393-
title?: (providedTitle: string, ...args: Array<any>) => string;
393+
title?: (providedTitle: string | undefined, ...args: Array<any>) => string;
394394
}
395395

396396
/** A reusable test or hook implementation, for tests & hooks declared with the `.cb` modifier. */
397397
export interface CbMacro<Context = {}> {
398398
(t: CbExecutionContext<Context>, ...args: Array<any>): ImplementationResult;
399-
title?: (providedTitle: string, ...args: Array<any>) => string;
399+
title?: (providedTitle: string | undefined, ...args: Array<any>) => string;
400400
}
401401

402402
export interface TestInterface<Context = {}> {

index.js.flow

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,13 +403,13 @@ export interface Macro<Context = {}> {
403403
* Implement this function to generate a test (or hook) title whenever this macro is used. `providedTitle` contains
404404
* the title provided when the test or hook was declared. Also receives the remaining test arguments.
405405
*/
406-
title?: (providedTitle: string, ...args: Array<any>) => string;
406+
title?: (providedTitle: string | void, ...args: Array<any>) => string;
407407
}
408408

409409
/** A reusable test or hook implementation, for tests & hooks declared with the `.cb` modifier. */
410410
export interface CbMacro<Context = {}> {
411411
(t: CbExecutionContext<Context>, ...args: Array<any>): ImplementationResult;
412-
title?: (providedTitle: string, ...args: Array<any>) => string;
412+
title?: (providedTitle: string | void, ...args: Array<any>) => string;
413413
}
414414

415415
export interface TestInterface<Context = {}> {

lib/runner.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Runner extends Emittery {
5555

5656
const specifiedTitle = typeof args[0] === 'string' ?
5757
args.shift() :
58-
'';
58+
undefined;
5959
const implementations = Array.isArray(args[0]) ?
6060
args.shift() :
6161
args.splice(0, 1);
@@ -65,7 +65,7 @@ class Runner extends Emittery {
6565
throw new TypeError('`todo` tests are not allowed to have an implementation. Use `test.skip()` for tests with an implementation.');
6666
}
6767

68-
if (specifiedTitle === '') {
68+
if (specifiedTitle === undefined || specifiedTitle === '') {
6969
throw new TypeError('`todo` tests require a title');
7070
}
7171

@@ -97,14 +97,14 @@ class Runner extends Emittery {
9797

9898
for (const implementation of implementations) {
9999
let title = implementation.title ?
100-
implementation.title.apply(implementation, [specifiedTitle].concat(args)) :
100+
implementation.title(specifiedTitle, ...args) :
101101
specifiedTitle;
102102

103-
if (typeof title !== 'string') {
103+
if (title !== undefined && typeof title !== 'string') {
104104
throw new TypeError('Test & hook titles must be strings');
105105
}
106106

107-
if (title === '') {
107+
if (title === undefined || title === '') {
108108
if (metadata.type === 'test') {
109109
throw new TypeError('Tests must have a title');
110110
} else if (metadata.always) {

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -691,14 +691,14 @@ function macro(t, input, expected) {
691691
t.is(eval(input), expected);
692692
}
693693

694-
macro.title = (providedTitle, input, expected) => `${providedTitle} ${input} = ${expected}`.trim();
694+
macro.title = (providedTitle = '', input, expected) => `${providedTitle} ${input} = ${expected}`.trim();
695695

696696
test(macro, '2 + 2', 4);
697697
test(macro, '2 * 3', 6);
698698
test('providedTitle', macro, '3 * 3', 9);
699699
```
700700

701-
The `providedTitle` argument defaults to an empty string if the user does not supply a string title. This allows for easy concatenation without having to worry about `null` / `undefined`. It is worth remembering that the empty string is considered a falsy value, so you can still use `if(providedTitle) {...}`.
701+
The `providedTitle` argument defaults to `undefined` if the user does not supply a string title. This means you can use a parameter assignment to set the default value. The example above uses the empty string as the default.
702702

703703
You can also pass arrays of macro functions:
704704

test/runner.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ test('macros: Customize test names attaching a `title` function', t => {
611611
avaT.pass();
612612
}
613613

614-
macroFn.title = (title, firstArg) => (title || 'default') + firstArg;
614+
macroFn.title = (title = 'default', firstArg) => title + firstArg;
615615

616616
return promiseEnd(new Runner(), runner => {
617617
runner.on('stateChange', evt => {

0 commit comments

Comments
 (0)