Skip to content

Commit f438ca8

Browse files
committed
Expect only overrides error stack for built-in matchers
1 parent e879099 commit f438ca8

5 files changed

Lines changed: 37 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
## master
22

3-
None for now
4-
53
### Fixes
64

75
* `[babel-jest]` moduleFileExtensions not passed to babel transformer.
86
([#4637](https://github.com/facebook/jest/issues/4637))
7+
* Do not override `Error` stack (with `Error.captureStackTrace`) for custom matchers.
8+
([#5138](https://github.com/facebook/jest/pull/5138))
99

1010
### Features
1111

packages/expect/src/__tests__/stacktrace.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,19 @@ it('stack trace points to correct location when using nested matchers', () => {
3535
expect(error.stack).toContain('stacktrace.test.js:32');
3636
}
3737
});
38+
39+
it('stack trace points to correct location when throwing from a custom matcher', () => {
40+
try {
41+
jestExpect(() => {
42+
const foo = () => bar();
43+
const bar = () => baz();
44+
const baz = () => {
45+
throw new Error('Expected');
46+
};
47+
48+
foo();
49+
}).toMatchPredicate(value => {});
50+
} catch (error) {
51+
expect(error.stack).toContain('stacktrace.test.js:61');
52+
}
53+
});

packages/expect/src/index.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ const makeThrowingMatcher = (
214214
result = matcher.apply(matcherContext, [actual].concat(args));
215215
} catch (error) {
216216
if (
217+
matcher.__jestInternal === true &&
217218
!(error instanceof JestAssertionError) &&
218219
error.name !== 'PrettyFormatPluginError' &&
219220
// Guard for some environments (browsers) that do not support this feature.
@@ -252,7 +253,8 @@ const makeThrowingMatcher = (
252253
};
253254
};
254255

255-
expect.extend = (matchers: MatchersObject): void => setMatchers(matchers);
256+
expect.extend = (matchers: MatchersObject): void =>
257+
setMatchers(matchers, false);
256258

257259
expect.anything = anything;
258260
expect.any = any;
@@ -280,9 +282,9 @@ const _validateResult = result => {
280282
};
281283

282284
// add default jest matchers
283-
expect.extend(matchers);
284-
expect.extend(spyMatchers);
285-
expect.extend(toThrowMatchers);
285+
setMatchers(matchers, true);
286+
setMatchers(spyMatchers, true);
287+
setMatchers(toThrowMatchers, true);
286288

287289
expect.addSnapshotSerializer = () => void 0;
288290
expect.assertions = (expected: number) => {
@@ -296,4 +298,8 @@ expect.getState = getState;
296298
expect.setState = setState;
297299
expect.extractExpectedAssertionsErrors = extractExpectedAssertionsErrors;
298300

301+
// Expose JestAssertionError for custom matchers
302+
// This enables them to preserve the stack for specific errors
303+
expect.JestAssertionError = JestAssertionError;
304+
299305
module.exports = (expect: Expect);

packages/expect/src/jest_matchers_object.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ export const setState = (state: Object) => {
3535

3636
export const getMatchers = () => global[JEST_MATCHERS_OBJECT].matchers;
3737

38-
export const setMatchers = (matchers: MatchersObject) => {
38+
export const setMatchers = (matchers: MatchersObject, isInternal: boolean) => {
39+
for (const key in matchers) {
40+
const matcher = matchers[key];
41+
Object.defineProperty(matcher, '__jestInternal', {
42+
value: isInternal,
43+
});
44+
}
45+
3946
Object.assign(global[JEST_MATCHERS_OBJECT].matchers, matchers);
4047
};

types/Matchers.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type RawMatcherFn = (
1919
expected: any,
2020
actual: any,
2121
options: any,
22+
__jestInternal?: boolean,
2223
) => ExpectationResult;
2324

2425
export type ThrowingMatcherFn = (actual: any) => void;

0 commit comments

Comments
 (0)