diff --git a/CHANGELOG.md b/CHANGELOG.md index e927e97d6a87..fb598b891946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[expect]` Support `async function`s in `toThrow` ([#9817](https://github.com/facebook/jest/pull/9817)) - `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) - `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) diff --git a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap index e442e66efcaf..652e3020ab90 100644 --- a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap @@ -10,7 +10,7 @@ Resolved to value: 4 exports[`.rejects fails non-promise value "a" 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: string Received has value: "a" @@ -19,7 +19,7 @@ Received has value: "a" exports[`.rejects fails non-promise value [1] 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: array Received has value: [1] @@ -28,7 +28,7 @@ Received has value: [1] exports[`.rejects fails non-promise value [Function anonymous] 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: function Received has value: [Function anonymous] @@ -37,7 +37,7 @@ Received has value: [Function anonymous] exports[`.rejects fails non-promise value {"a": 1} 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: object Received has value: {"a": 1} @@ -46,7 +46,7 @@ Received has value: {"a": 1} exports[`.rejects fails non-promise value 4 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: number Received has value: 4 @@ -55,7 +55,7 @@ Received has value: 4 exports[`.rejects fails non-promise value null 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has value: null `; @@ -63,7 +63,7 @@ Received has value: null exports[`.rejects fails non-promise value true 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: boolean Received has value: true @@ -72,7 +72,7 @@ Received has value: true exports[`.rejects fails non-promise value undefined 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has value: undefined `; diff --git a/packages/expect/src/__tests__/matchers.test.js b/packages/expect/src/__tests__/matchers.test.js index 89f25a561ea8..4223f4e53475 100644 --- a/packages/expect/src/__tests__/matchers.test.js +++ b/packages/expect/src/__tests__/matchers.test.js @@ -56,6 +56,12 @@ describe('.rejects', () => { await jestExpect(fn()).rejects.toThrow('some error'); }); + it('should reject async function to toThrow', async () => { + await expect(async () => { + throw new Error('Test'); + }).rejects.toThrow('Test'); + }); + ['a', [1], () => {}, {a: 1}].forEach(value => { it(`fails non-promise value ${stringify(value)} synchronously`, () => { let error; diff --git a/packages/expect/src/index.ts b/packages/expect/src/index.ts index 80adf7d3c686..c715cd97354d 100644 --- a/packages/expect/src/index.ts +++ b/packages/expect/src/index.ts @@ -189,7 +189,7 @@ const makeRejectMatcher = ( matcherName: string, matcher: RawMatcherFn, isNot: boolean, - actual: Promise, + actual: Promise | (() => Promise), outerErr: JestAssertionError, ): PromiseMatcherFn => (...args) => { const options = { @@ -197,11 +197,16 @@ const makeRejectMatcher = ( promise: 'rejects', }; - if (!isPromise(actual)) { + const actualWrapper: Promise = + typeof actual === 'function' ? actual() : actual; + + if (!isPromise(actualWrapper)) { throw new JestAssertionError( matcherUtils.matcherErrorMessage( matcherUtils.matcherHint(matcherName, undefined, '', options), - `${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`, + `${matcherUtils.RECEIVED_COLOR( + 'received', + )} value must be a promise or a function returning a promise`, matcherUtils.printWithType( 'Received', actual, @@ -213,7 +218,7 @@ const makeRejectMatcher = ( const innerErr = new JestAssertionError(); - return actual.then( + return actualWrapper.then( result => { outerErr.message = matcherUtils.matcherHint(matcherName, undefined, '', options) +