Skip to content

Commit 21e35cc

Browse files
mattphillipsSimenB
authored andcommitted
[jest-each]: Add flag to prevent done callback being supplied to describe (jestjs#6843)
* Add flag to prevent done callback being supplied to describe * Add changelog entry * Refactor with thymikee linter ;)
1 parent c5389cb commit 21e35cc

File tree

7 files changed

+171
-116
lines changed

7 files changed

+171
-116
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
- `[docs]` Add custom toMatchSnapshot matcher docs ([#6837](https://github.com/facebook/jest/pull/6837))
1010

11+
### Fixes
12+
13+
- `[jest-each`] Prevent done callback being supplied to describe ([#6843](https://github.com/facebook/jest/pull/6843))
14+
1115
## 23.5.0
1216

1317
### Features

packages/jest-circus/src/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ test.each = bindEach(test);
121121
test.only.each = bindEach(test.only);
122122
test.skip.each = bindEach(test.skip);
123123

124-
describe.each = bindEach(describe);
125-
describe.only.each = bindEach(describe.only);
126-
describe.skip.each = bindEach(describe.skip);
124+
describe.each = bindEach(describe, false);
125+
describe.only.each = bindEach(describe.only, false);
126+
describe.skip.each = bindEach(describe.skip, false);
127127

128128
module.exports = {
129129
afterAll,

packages/jest-each/src/__tests__/array.test.js

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,26 @@ const expectFunction = expect.any(Function);
1515
const get = (object, lensPath) =>
1616
lensPath.reduce((acc, key) => acc[key], object);
1717

18+
const getGlobalTestMocks = () => {
19+
const globals = {
20+
describe: jest.fn(),
21+
fdescribe: jest.fn(),
22+
fit: jest.fn(),
23+
it: jest.fn(),
24+
test: jest.fn(),
25+
xdescribe: jest.fn(),
26+
xit: jest.fn(),
27+
xtest: jest.fn(),
28+
};
29+
globals.test.only = jest.fn();
30+
globals.test.skip = jest.fn();
31+
globals.it.only = jest.fn();
32+
globals.it.skip = jest.fn();
33+
globals.describe.only = jest.fn();
34+
globals.describe.skip = jest.fn();
35+
return globals;
36+
};
37+
1838
describe('jest-each', () => {
1939
[
2040
['test'],
@@ -27,20 +47,6 @@ describe('jest-each', () => {
2747
['describe', 'only'],
2848
].forEach(keyPath => {
2949
describe(`.${keyPath.join('.')}`, () => {
30-
const getGlobalTestMocks = () => {
31-
const globals = {
32-
describe: jest.fn(),
33-
fdescribe: jest.fn(),
34-
fit: jest.fn(),
35-
it: jest.fn(),
36-
test: jest.fn(),
37-
};
38-
globals.test.only = jest.fn();
39-
globals.it.only = jest.fn();
40-
globals.describe.only = jest.fn();
41-
return globals;
42-
};
43-
4450
test('calls global with given title', () => {
4551
const globalTestMocks = getGlobalTestMocks();
4652
const eachObject = each.withGlobal(globalTestMocks)([[]]);
@@ -237,18 +243,6 @@ describe('jest-each', () => {
237243
expect(testCallBack).toHaveBeenCalledWith('joe', 'bloggs');
238244
});
239245

240-
test('calls global with async done when cb function has more args than params of given test row', () => {
241-
const globalTestMocks = getGlobalTestMocks();
242-
const eachObject = each.withGlobal(globalTestMocks)([['hello']]);
243-
244-
const testFunction = get(eachObject, keyPath);
245-
testFunction('expected string', (hello, done) => {
246-
expect(hello).toBe('hello');
247-
expect(done).toBe('DONE');
248-
});
249-
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
250-
});
251-
252246
test('calls global with given timeout', () => {
253247
const globalTestMocks = getGlobalTestMocks();
254248
const eachObject = each.withGlobal(globalTestMocks)([['hello']]);
@@ -265,6 +259,45 @@ describe('jest-each', () => {
265259
});
266260
});
267261

262+
describe('done callback', () => {
263+
test.each([
264+
[['test']],
265+
[['test', 'only']],
266+
[['it']],
267+
[['fit']],
268+
[['it', 'only']],
269+
])(
270+
'calls %O with done when cb function has more args than params of given test row',
271+
keyPath => {
272+
const globalTestMocks = getGlobalTestMocks();
273+
const eachObject = each.withGlobal(globalTestMocks)([['hello']]);
274+
275+
const testFunction = get(eachObject, keyPath);
276+
testFunction('expected string', (hello, done) => {
277+
expect(hello).toBe('hello');
278+
expect(done).toBe('DONE');
279+
});
280+
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
281+
},
282+
);
283+
284+
test.each([[['describe']], [['fdescribe']], [['describe', 'only']]])(
285+
'does not call %O with done when test function has more args than params of given test row',
286+
keyPath => {
287+
const globalTestMocks = getGlobalTestMocks();
288+
const eachObject = each.withGlobal(globalTestMocks)([['hello']]);
289+
290+
const testFunction = get(eachObject, keyPath);
291+
testFunction('expected string', function(hello, done) {
292+
expect(hello).toBe('hello');
293+
expect(arguments.length).toBe(1);
294+
expect(done).toBe(undefined);
295+
});
296+
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
297+
},
298+
);
299+
});
300+
268301
[
269302
['xtest'],
270303
['test', 'skip'],
@@ -274,24 +307,6 @@ describe('jest-each', () => {
274307
['describe', 'skip'],
275308
].forEach(keyPath => {
276309
describe(`.${keyPath.join('.')}`, () => {
277-
const getGlobalTestMocks = () => {
278-
const globals = {
279-
describe: {
280-
skip: jest.fn(),
281-
},
282-
it: {
283-
skip: jest.fn(),
284-
},
285-
test: {
286-
skip: jest.fn(),
287-
},
288-
xdescribe: jest.fn(),
289-
xit: jest.fn(),
290-
xtest: jest.fn(),
291-
};
292-
return globals;
293-
};
294-
295310
test('calls global with given title', () => {
296311
const globalTestMocks = getGlobalTestMocks();
297312
const eachObject = each.withGlobal(globalTestMocks)([[]]);

packages/jest-each/src/__tests__/template.test.js

Lines changed: 67 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,26 @@ const expectFunction = expect.any(Function);
1414
const get = (object, lensPath) =>
1515
lensPath.reduce((acc, key) => acc[key], object);
1616

17+
const getGlobalTestMocks = () => {
18+
const globals = {
19+
describe: jest.fn(),
20+
fdescribe: jest.fn(),
21+
fit: jest.fn(),
22+
it: jest.fn(),
23+
test: jest.fn(),
24+
xdescribe: jest.fn(),
25+
xit: jest.fn(),
26+
xtest: jest.fn(),
27+
};
28+
globals.test.only = jest.fn();
29+
globals.test.skip = jest.fn();
30+
globals.it.only = jest.fn();
31+
globals.it.skip = jest.fn();
32+
globals.describe.only = jest.fn();
33+
globals.describe.skip = jest.fn();
34+
return globals;
35+
};
36+
1737
describe('jest-each', () => {
1838
[
1939
['test'],
@@ -26,20 +46,6 @@ describe('jest-each', () => {
2646
['describe', 'only'],
2747
].forEach(keyPath => {
2848
describe(`.${keyPath.join('.')}`, () => {
29-
const getGlobalTestMocks = () => {
30-
const globals = {
31-
describe: jest.fn(),
32-
fdescribe: jest.fn(),
33-
fit: jest.fn(),
34-
it: jest.fn(),
35-
test: jest.fn(),
36-
};
37-
globals.test.only = jest.fn();
38-
globals.it.only = jest.fn();
39-
globals.describe.only = jest.fn();
40-
return globals;
41-
};
42-
4349
test('throws error when there are fewer arguments than headings when given one row', () => {
4450
const globalTestMocks = getGlobalTestMocks();
4551
const eachObject = each.withGlobal(globalTestMocks)`
@@ -228,22 +234,6 @@ describe('jest-each', () => {
228234
expect(testCallBack).toHaveBeenCalledWith({a: 1, b: 1, expected: 2});
229235
});
230236

231-
test('calls global with async done when cb function has more than one argument', () => {
232-
const globalTestMocks = getGlobalTestMocks();
233-
const eachObject = each.withGlobal(globalTestMocks)`
234-
a | b | expected
235-
${0} | ${1} | ${1}
236-
`;
237-
const testFunction = get(eachObject, keyPath);
238-
testFunction('expected string', ({a, b, expected}, done) => {
239-
expect(a).toBe(0);
240-
expect(b).toBe(1);
241-
expect(expected).toBe(1);
242-
expect(done).toBe('DONE');
243-
});
244-
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
245-
});
246-
247237
test('calls global with given timeout', () => {
248238
const globalTestMocks = getGlobalTestMocks();
249239
const eachObject = each.withGlobal(globalTestMocks)`
@@ -263,6 +253,53 @@ describe('jest-each', () => {
263253
});
264254
});
265255

256+
describe('done callback', () => {
257+
test.each([
258+
[['test']],
259+
[['test', 'only']],
260+
[['it']],
261+
[['fit']],
262+
[['it', 'only']],
263+
])(
264+
'calls %O with done when cb function has more args than params of given test row',
265+
keyPath => {
266+
const globalTestMocks = getGlobalTestMocks();
267+
const eachObject = each.withGlobal(globalTestMocks)`
268+
a | b | expected
269+
${0} | ${1} | ${1}
270+
`;
271+
const testFunction = get(eachObject, keyPath);
272+
testFunction('expected string', ({a, b, expected}, done) => {
273+
expect(a).toBe(0);
274+
expect(b).toBe(1);
275+
expect(expected).toBe(1);
276+
expect(done).toBe('DONE');
277+
});
278+
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
279+
},
280+
);
281+
282+
test.each([[['describe']], [['fdescribe']], [['describe', 'only']]])(
283+
'does not call %O with done when test function has more args than params of given test row',
284+
keyPath => {
285+
const globalTestMocks = getGlobalTestMocks();
286+
const eachObject = each.withGlobal(globalTestMocks)`
287+
a | b | expected
288+
${0} | ${1} | ${1}
289+
`;
290+
const testFunction = get(eachObject, keyPath);
291+
testFunction('expected string', function({a, b, expected}, done) {
292+
expect(a).toBe(0);
293+
expect(b).toBe(1);
294+
expect(expected).toBe(1);
295+
expect(done).toBe(undefined);
296+
expect(arguments.length).toBe(1);
297+
});
298+
get(globalTestMocks, keyPath).mock.calls[0][1]('DONE');
299+
},
300+
);
301+
});
302+
266303
[
267304
['xtest'],
268305
['test', 'skip'],
@@ -272,24 +309,6 @@ describe('jest-each', () => {
272309
['describe', 'skip'],
273310
].forEach(keyPath => {
274311
describe(`.${keyPath.join('.')}`, () => {
275-
const getGlobalTestMocks = () => {
276-
const globals = {
277-
describe: {
278-
skip: jest.fn(),
279-
},
280-
it: {
281-
skip: jest.fn(),
282-
},
283-
test: {
284-
skip: jest.fn(),
285-
},
286-
xdescribe: jest.fn(),
287-
xit: jest.fn(),
288-
xtest: jest.fn(),
289-
};
290-
return globals;
291-
};
292-
293312
test('calls global with given title', () => {
294313
const globalTestMocks = getGlobalTestMocks();
295314
const eachObject = each.withGlobal(globalTestMocks)`

packages/jest-each/src/bind.js

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@ const SUPPORTED_PLACEHOLDERS = /%[sdifjoOp%]/g;
2323
const PRETTY_PLACEHOLDER = '%p';
2424
const INDEX_PLACEHOLDER = '%#';
2525

26-
export default (cb: Function) => (...args: any) =>
26+
export default (cb: Function, supportsDone: boolean = true) => (...args: any) =>
2727
function eachBind(title: string, test: Function, timeout: number): void {
2828
if (args.length === 1) {
2929
const table: Table = args[0].every(Array.isArray)
3030
? args[0]
3131
: args[0].map(entry => [entry]);
3232
return table.forEach((row, i) =>
33-
cb(arrayFormat(title, i, ...row), applyRestParams(row, test), timeout),
33+
cb(
34+
arrayFormat(title, i, ...row),
35+
applyRestParams(supportsDone, row, test),
36+
timeout,
37+
),
3438
);
3539
}
3640

@@ -66,7 +70,11 @@ export default (cb: Function) => (...args: any) =>
6670
}
6771

6872
return table.forEach(row =>
69-
cb(interpolate(title, row), applyObjectParams(row, test), timeout),
73+
cb(
74+
interpolate(title, row),
75+
applyObjectParams(supportsDone, row, test),
76+
timeout,
77+
),
7078
);
7179
};
7280

@@ -107,11 +115,14 @@ const arrayFormat = (title, rowIndex, ...args) => {
107115
);
108116
};
109117

110-
const applyRestParams = (params: Array<any>, test: Function) => {
111-
if (params.length < test.length) return done => test(...params, done);
112-
113-
return () => test(...params);
114-
};
118+
const applyRestParams = (
119+
supportsDone: boolean,
120+
params: Array<any>,
121+
test: Function,
122+
) =>
123+
supportsDone && params.length < test.length
124+
? done => test(...params, done)
125+
: () => test(...params);
115126

116127
const getHeadingKeys = (headings: string): Array<string> =>
117128
headings.replace(/\s/g, '').split('|');
@@ -144,11 +155,8 @@ const interpolate = (title: string, data: any) =>
144155
.reduce(getMatchingKeyPaths(title), []) // aka flatMap
145156
.reduce(replaceKeyPathWithValue(data), title);
146157

147-
const applyObjectParams = (obj: any, test: Function) => {
148-
if (test.length > 1) return done => test(obj, done);
149-
150-
return () => test(obj);
151-
};
158+
const applyObjectParams = (supportsDone: boolean, obj: any, test: Function) =>
159+
supportsDone && test.length > 1 ? done => test(obj, done) : () => test(obj);
152160

153161
const pluralize = (word: string, count: number) =>
154162
word + (count === 1 ? '' : 's');

packages/jest-each/src/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ const install = (g: GlobalCallbacks, ...args: Array<mixed>) => {
3636
const xtest = bind(g.xtest)(...args);
3737

3838
const describe = (title: string, suite: Function, timeout: number) =>
39-
bind(g.describe)(...args)(title, suite, timeout);
40-
describe.skip = bind(g.describe.skip)(...args);
41-
describe.only = bind(g.describe.only)(...args);
42-
const fdescribe = bind(g.fdescribe)(...args);
43-
const xdescribe = bind(g.xdescribe)(...args);
39+
bind(g.describe, false)(...args)(title, suite, timeout);
40+
describe.skip = bind(g.describe.skip, false)(...args);
41+
describe.only = bind(g.describe.only, false)(...args);
42+
const fdescribe = bind(g.fdescribe, false)(...args);
43+
const xdescribe = bind(g.xdescribe, false)(...args);
4444

4545
return {describe, fdescribe, fit, it, test, xdescribe, xit, xtest};
4646
};

0 commit comments

Comments
 (0)