Skip to content

Commit 02e1c66

Browse files
SimenBcpojer
authored andcommitted
add stack trace on expect.(has)Assertions (#5997)
* add stack trace on expect.(has)Assertions * guard against missing `Error.captureStackTrace` * please flow gods
1 parent bf654e1 commit 02e1c66

File tree

5 files changed

+93
-46
lines changed

5 files changed

+93
-46
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272

7373
### Fixes
7474

75+
* `[expect]` Add stack trace when `expect.assertions` and `expect.hasAssertions`
76+
causes test failures. ([#5997](https://github.com/facebook/jest/pull/5997))
7577
* `[jest-runtime]` Throw a more useful error when trying to require modules
7678
after the test environment is torn down
7779
([#5888](https://github.com/facebook/jest/pull/5888))

integration-tests/__tests__/__snapshots__/failures.test.js.snap

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,37 +36,87 @@ exports[`not throwing Error objects 4`] = `
3636
✕ throws on assertion
3737
.hasAssertions()
3838
✕ throws when there are not assertions
39+
3940
● .assertions() › throws
41+
4042
expect(received).toBeTruthy()
43+
4144
Received: false
45+
4246
11 | const throws = () => {
4347
12 | expect.assertions(2);
4448
> 13 | expect(false).toBeTruthy();
4549
| ^
4650
14 | };
4751
15 | const redeclare = () => {
4852
16 | expect.assertions(1);
53+
4954
at __tests__/assertion_count.test.js:13:17
55+
5056
● .assertions() › throws
57+
5158
expect.assertions(2)
59+
5260
Expected two assertions to be called but received one assertion call.
61+
62+
10 |
63+
11 | const throws = () => {
64+
> 12 | expect.assertions(2);
65+
| ^
66+
13 | expect(false).toBeTruthy();
67+
14 | };
68+
15 | const redeclare = () => {
69+
70+
at __tests__/assertion_count.test.js:12:10
71+
5372
● .assertions() › throws on redeclare of assertion count
73+
5474
expect(received).toBeTruthy()
75+
5576
Received: false
77+
5678
15 | const redeclare = () => {
5779
16 | expect.assertions(1);
5880
> 17 | expect(false).toBeTruthy();
5981
| ^
6082
18 | expect.assertions(2);
6183
19 | };
62-
20 |
84+
20 |
85+
6386
at __tests__/assertion_count.test.js:17:17
87+
6488
● .assertions() › throws on assertion
89+
6590
expect.assertions(0)
91+
6692
Expected zero assertions to be called but received one assertion call.
93+
94+
20 |
95+
21 | const noAssertions = () => {
96+
> 22 | expect.assertions(0);
97+
| ^
98+
23 | expect(true).toBeTruthy();
99+
24 | };
100+
25 |
101+
102+
at __tests__/assertion_count.test.js:22:10
103+
67104
● .hasAssertions() › throws when there are not assertions
105+
68106
expect.hasAssertions()
107+
69108
Expected at least one assertion to be called but received none.
109+
110+
25 |
111+
26 | const hasNoAssertions = () => {
112+
> 27 | expect.hasAssertions();
113+
| ^
114+
28 | };
115+
29 |
116+
30 | describe('.assertions()', () => {
117+
118+
at __tests__/assertion_count.test.js:27:10
119+
70120
"
71121
`;
72122

integration-tests/__tests__/failures.test.js

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,6 @@ const normalizeDots = text => text.replace(/\.{1,}$/gm, '.');
1818

1919
SkipOnWindows.suite();
2020

21-
const cleanupStackTrace = stderr => {
22-
const STACK_REGEXP = /^.*at.*(setup-jest-globals|extractExpectedAssertionsErrors).*\n/gm;
23-
if (!STACK_REGEXP.test(stderr)) {
24-
throw new Error(
25-
`
26-
This function is used to remove inconsistent stack traces between
27-
jest-jasmine2 and jest-circus. If you see this error, that means the
28-
stack traces are no longer inconsistent and this function can be
29-
safely removed.
30-
31-
output:
32-
${stderr}
33-
`,
34-
);
35-
}
36-
37-
return (
38-
stderr
39-
.replace(STACK_REGEXP, '')
40-
// Also remove trailing whitespace.
41-
.replace(/\s+$/gm, '')
42-
);
43-
};
44-
4521
test('not throwing Error objects', () => {
4622
let stderr;
4723
stderr = runJest(dir, ['throw_number.test.js']).stderr;
@@ -51,7 +27,7 @@ test('not throwing Error objects', () => {
5127
stderr = runJest(dir, ['throw_object.test.js']).stderr;
5228
expect(extractSummary(stderr).rest).toMatchSnapshot();
5329
stderr = runJest(dir, ['assertion_count.test.js']).stderr;
54-
expect(extractSummary(cleanupStackTrace(stderr)).rest).toMatchSnapshot();
30+
expect(extractSummary(stderr).rest).toMatchSnapshot();
5531
stderr = runJest(dir, ['during_tests.test.js']).stderr;
5632
expect(extractSummary(stderr).rest).toMatchSnapshot();
5733
});

packages/expect/src/extract_expected_assertions_errors.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ const resetAssertionsLocalState = () => {
2525
};
2626

2727
// Create and format all errors related to the mismatched number of `expect`
28-
// calls and reset the matchers state.
28+
// calls and reset the matcher's state.
2929
const extractExpectedAssertionsErrors = () => {
3030
const result = [];
3131
const {
3232
assertionCalls,
3333
expectedAssertionsNumber,
34+
expectedAssertionsNumberError,
3435
isExpectingAssertions,
36+
isExpectingAssertionsError,
3537
} = getState();
3638

3739
resetAssertionsLocalState();
@@ -43,34 +45,36 @@ const extractExpectedAssertionsErrors = () => {
4345
const numOfAssertionsExpected = EXPECTED_COLOR(
4446
pluralize('assertion', expectedAssertionsNumber),
4547
);
46-
const error = new Error(
48+
49+
expectedAssertionsNumberError.message =
4750
matcherHint('.assertions', '', String(expectedAssertionsNumber), {
4851
isDirectExpectCall: true,
4952
}) +
50-
'\n\n' +
51-
`Expected ${numOfAssertionsExpected} to be called but received ` +
52-
RECEIVED_COLOR(pluralize('assertion call', assertionCalls || 0)) +
53-
'.',
54-
);
53+
'\n\n' +
54+
`Expected ${numOfAssertionsExpected} to be called but received ` +
55+
RECEIVED_COLOR(pluralize('assertion call', assertionCalls || 0)) +
56+
'.';
57+
5558
result.push({
5659
actual: assertionCalls,
57-
error,
60+
error: expectedAssertionsNumberError,
5861
expected: expectedAssertionsNumber,
5962
});
6063
}
6164
if (isExpectingAssertions && assertionCalls === 0) {
6265
const expected = EXPECTED_COLOR('at least one assertion');
6366
const received = RECEIVED_COLOR('received none');
64-
const error = new Error(
67+
68+
isExpectingAssertionsError.message =
6569
matcherHint('.hasAssertions', '', '', {
6670
isDirectExpectCall: true,
6771
}) +
68-
'\n\n' +
69-
`Expected ${expected} to be called but ${received}.`,
70-
);
72+
'\n\n' +
73+
`Expected ${expected} to be called but ${received}.`;
74+
7175
result.push({
7276
actual: 'none',
73-
error,
77+
error: isExpectingAssertionsError,
7478
expected: 'at least one',
7579
});
7680
}

packages/expect/src/index.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,19 +335,34 @@ const _validateResult = result => {
335335
}
336336
};
337337

338+
function assertions(expected: number) {
339+
const error = new Error();
340+
if (Error.captureStackTrace) {
341+
Error.captureStackTrace(error, assertions);
342+
}
343+
344+
getState().expectedAssertionsNumber = expected;
345+
getState().expectedAssertionsNumberError = error;
346+
}
347+
function hasAssertions(...args) {
348+
const error = new Error();
349+
if (Error.captureStackTrace) {
350+
Error.captureStackTrace(error, hasAssertions);
351+
}
352+
353+
utils.ensureNoExpected(args[0], '.hasAssertions');
354+
getState().isExpectingAssertions = true;
355+
getState().isExpectingAssertionsError = error;
356+
}
357+
338358
// add default jest matchers
339359
setMatchers(matchers, true, expect);
340360
setMatchers(spyMatchers, true, expect);
341361
setMatchers(toThrowMatchers, true, expect);
342362

343363
expect.addSnapshotSerializer = () => void 0;
344-
expect.assertions = (expected: number) => {
345-
getState().expectedAssertionsNumber = expected;
346-
};
347-
expect.hasAssertions = (expected: any) => {
348-
utils.ensureNoExpected(expected, '.hasAssertions');
349-
getState().isExpectingAssertions = true;
350-
};
364+
expect.assertions = assertions;
365+
expect.hasAssertions = hasAssertions;
351366
expect.getState = getState;
352367
expect.setState = setState;
353368
expect.extractExpectedAssertionsErrors = extractExpectedAssertionsErrors;

0 commit comments

Comments
 (0)