From fcb612ca4bac56d8d4950f276241477d1f68a0e7 Mon Sep 17 00:00:00 2001 From: Matt Phillips Date: Tue, 23 Oct 2018 14:12:44 +0100 Subject: [PATCH] Add error call site to preserve stack trace; --- src/chain.js | 18 ++++++++++++++++-- src/chain.test.js | 13 +++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/chain.js b/src/chain.js index 07a899b..879eecb 100644 --- a/src/chain.js +++ b/src/chain.js @@ -1,13 +1,27 @@ +class JestAssertionError extends Error { + constructor(result, callsite) { + super(result.message()); + this.matcherResult = result; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, callsite); + } + } +} + const chainMatchers = (matchers, originalMatchers = matchers) => { const mappedMatchers = Object.keys(matchers).map(name => { const matcher = matchers[name]; if (typeof matcher === 'function') { - return { - [name]: (...args) => { + const newMatcher = (...args) => { + try { matcher(...args); // run matcher return chainMatchers(originalMatchers); // chain the original matchers again + } catch (error) { + throw new JestAssertionError(error.matcherResult, newMatcher); } }; + return { [name]: newMatcher }; } return { [name]: chainMatchers(matcher, originalMatchers) // recurse on .not/.resolves/.rejects diff --git a/src/chain.test.js b/src/chain.test.js index 0f7388b..2f9f81c 100644 --- a/src/chain.test.js +++ b/src/chain.test.js @@ -187,4 +187,17 @@ describe('.chain', () => { expect(extendMock).toHaveBeenCalledWith(newMatcher); expect(actual).toContainAllKeys(['a', 'extend', 'newMatcher']); }); + + it('throws error when matcher fails', () => { + expect.assertions(1); + const expectMock = jest.fn(() => ({ + toBe: () => { + const error = new Error(''); + error.matcherResult = { message: () => 'blah', pass: false }; + throw error; + } + })); + + expect(() => chain(expectMock)('hello').toBe('hi')).toThrowErrorMatchingInlineSnapshot('"blah"'); + }); });