From 5915f91eb8b699e17b3d481fb5fd97f36f153137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Sentkiewicz?= Date: Mon, 13 Nov 2017 17:00:37 +0100 Subject: [PATCH 1/4] fix .toThrow for promises MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #3601 Signed-off-by: Łukasz Sentkiewicz --- docs/ExpectAPI.md | 4 +-- .../expect/src/__tests__/matchers.test.js | 13 +++++--- packages/expect/src/index.js | 22 ++++++++++--- packages/expect/src/to_throw_matchers.js | 32 +++++++++++-------- 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/docs/ExpectAPI.md b/docs/ExpectAPI.md index 58b95414ec30..07e626e7ce74 100644 --- a/docs/ExpectAPI.md +++ b/docs/ExpectAPI.md @@ -416,7 +416,7 @@ For example, this code tests that the promise rejects with reason `'octopus'`: ```js test('rejects to octopus', () => { // make sure to add a return statement - return expect(Promise.reject('octopus')).rejects.toBe('octopus'); + return expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus'); }); ``` @@ -424,7 +424,7 @@ Alternatively, you can use `async/await` in combination with `.rejects`. ```js test('rejects to octopus', async () => { - await expect(Promise.reject('octopus')).rejects.toBe('octopus'); + await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus'); }); ``` diff --git a/packages/expect/src/__tests__/matchers.test.js b/packages/expect/src/__tests__/matchers.test.js index de3db5d90046..c0f368dcf059 100644 --- a/packages/expect/src/__tests__/matchers.test.js +++ b/packages/expect/src/__tests__/matchers.test.js @@ -27,11 +27,14 @@ describe('.rejects', () => { await jestExpect(Promise.reject({a: 1, b: 2})).rejects.not.toMatchObject({ c: 1, }); - await jestExpect( - Promise.reject(() => { - throw new Error(); - }), - ).rejects.toThrow(); + await jestExpect(Promise.reject(new Error())).rejects.toThrow(); + }); + + it('should reject with toThrow', async () => { + async function fn() { + throw new Error('some error'); + } + await jestExpect(fn()).rejects.toThrow('some error'); }); [4, [1], {a: 1}, 'a', true, null, undefined, () => {}].forEach(value => { diff --git a/packages/expect/src/index.js b/packages/expect/src/index.js index e43ebb343987..c3ead6bdb2ec 100644 --- a/packages/expect/src/index.js +++ b/packages/expect/src/index.js @@ -51,6 +51,13 @@ const isPromise = obj => { ); }; +const getPromiseMatcher = name => { + if (name === 'toThrow' || name === 'toThrowError') { + return 'toThrowFromPromise'; + } + return name; +}; + const expect = (actual: any, ...rest): ExpectationObject => { if (rest.length !== 0) { throw new Error('Expect takes at most one argument.'); @@ -64,7 +71,12 @@ const expect = (actual: any, ...rest): ExpectationObject => { }; Object.keys(allMatchers).forEach(name => { - expectation[name] = makeThrowingMatcher(allMatchers[name], false, actual); + const targetName = getPromiseMatcher(name); + expectation[name] = makeThrowingMatcher( + allMatchers[targetName], + false, + actual, + ); expectation.not[name] = makeThrowingMatcher( allMatchers[name], true, @@ -73,26 +85,26 @@ const expect = (actual: any, ...rest): ExpectationObject => { expectation.resolves[name] = makeResolveMatcher( name, - allMatchers[name], + allMatchers[targetName], false, actual, ); expectation.resolves.not[name] = makeResolveMatcher( name, - allMatchers[name], + allMatchers[targetName], true, actual, ); expectation.rejects[name] = makeRejectMatcher( name, - allMatchers[name], + allMatchers[targetName], false, actual, ); expectation.rejects.not[name] = makeRejectMatcher( name, - allMatchers[name], + allMatchers[targetName], true, actual, ); diff --git a/packages/expect/src/to_throw_matchers.js b/packages/expect/src/to_throw_matchers.js index 3a448df231d6..013a3975446e 100644 --- a/packages/expect/src/to_throw_matchers.js +++ b/packages/expect/src/to_throw_matchers.js @@ -21,26 +21,29 @@ import { } from 'jest-matcher-utils'; import {equals} from './jasmine_utils'; -const createMatcher = matcherName => ( +const createMatcher = (matcherName, fromPromise) => ( actual: Function, expected: string | Error | RegExp, ) => { const value = expected; let error; - if (typeof actual !== 'function') { - throw new Error( - matcherHint(matcherName, 'function', getType(value)) + - '\n\n' + - 'Received value must be a function, but instead ' + - `"${getType(actual)}" was found`, - ); - } - - try { - actual(); - } catch (e) { - error = e; + if (fromPromise) { + error = actual; + } else { + if (typeof actual !== 'function') { + throw new Error( + matcherHint(matcherName, 'function', getType(value)) + + '\n\n' + + 'Received value must be a function, but instead ' + + `"${getType(actual)}" was found`, + ); + } + try { + actual(); + } catch (e) { + error = e; + } } if (typeof expected === 'string') { @@ -85,6 +88,7 @@ const createMatcher = matcherName => ( const matchers: MatchersObject = { toThrow: createMatcher('.toThrow'), toThrowError: createMatcher('.toThrowError'), + toThrowFromPromise: createMatcher('.toThrowFromPromise', true), }; const toThrowMatchingStringOrRegexp = ( From 4bbccfdb49b77361c4741b671d6fef1418e4a946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Sentkiewicz?= Date: Mon, 13 Nov 2017 17:16:09 +0100 Subject: [PATCH 2/4] keep original matcherName MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Sentkiewicz --- packages/expect/src/index.js | 31 ++++++++++-------------- packages/expect/src/to_throw_matchers.js | 3 +-- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/packages/expect/src/index.js b/packages/expect/src/index.js index c3ead6bdb2ec..aae81704bc66 100644 --- a/packages/expect/src/index.js +++ b/packages/expect/src/index.js @@ -21,7 +21,9 @@ import type { import * as utils from 'jest-matcher-utils'; import matchers from './matchers'; import spyMatchers from './spy_matchers'; -import toThrowMatchers from './to_throw_matchers'; +import toThrowMatchers, { + createMatcher as createThrowMatcher, +} from './to_throw_matchers'; import {equals} from './jasmine_utils'; import { any, @@ -53,9 +55,9 @@ const isPromise = obj => { const getPromiseMatcher = name => { if (name === 'toThrow' || name === 'toThrowError') { - return 'toThrowFromPromise'; + return createThrowMatcher('.' + name, true); } - return name; + return null; }; const expect = (actual: any, ...rest): ExpectationObject => { @@ -71,40 +73,33 @@ const expect = (actual: any, ...rest): ExpectationObject => { }; Object.keys(allMatchers).forEach(name => { - const targetName = getPromiseMatcher(name); - expectation[name] = makeThrowingMatcher( - allMatchers[targetName], - false, - actual, - ); - expectation.not[name] = makeThrowingMatcher( - allMatchers[name], - true, - actual, - ); + const matcher = allMatchers[name]; + const promiseMatcher = getPromiseMatcher(name) || matcher; + expectation[name] = makeThrowingMatcher(matcher, false, actual); + expectation.not[name] = makeThrowingMatcher(matcher, true, actual); expectation.resolves[name] = makeResolveMatcher( name, - allMatchers[targetName], + promiseMatcher, false, actual, ); expectation.resolves.not[name] = makeResolveMatcher( name, - allMatchers[targetName], + promiseMatcher, true, actual, ); expectation.rejects[name] = makeRejectMatcher( name, - allMatchers[targetName], + promiseMatcher, false, actual, ); expectation.rejects.not[name] = makeRejectMatcher( name, - allMatchers[targetName], + matcher, true, actual, ); diff --git a/packages/expect/src/to_throw_matchers.js b/packages/expect/src/to_throw_matchers.js index 013a3975446e..634700204e34 100644 --- a/packages/expect/src/to_throw_matchers.js +++ b/packages/expect/src/to_throw_matchers.js @@ -21,7 +21,7 @@ import { } from 'jest-matcher-utils'; import {equals} from './jasmine_utils'; -const createMatcher = (matcherName, fromPromise) => ( +export const createMatcher = (matcherName, fromPromise) => ( actual: Function, expected: string | Error | RegExp, ) => { @@ -88,7 +88,6 @@ const createMatcher = (matcherName, fromPromise) => ( const matchers: MatchersObject = { toThrow: createMatcher('.toThrow'), toThrowError: createMatcher('.toThrowError'), - toThrowFromPromise: createMatcher('.toThrowFromPromise', true), }; const toThrowMatchingStringOrRegexp = ( From b778d5d040b91ce3922c5503969c45b233ea8d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Sentkiewicz?= Date: Mon, 13 Nov 2017 17:25:21 +0100 Subject: [PATCH 3/4] fix flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Sentkiewicz --- packages/expect/src/to_throw_matchers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/expect/src/to_throw_matchers.js b/packages/expect/src/to_throw_matchers.js index 634700204e34..9bab72a182c5 100644 --- a/packages/expect/src/to_throw_matchers.js +++ b/packages/expect/src/to_throw_matchers.js @@ -21,7 +21,7 @@ import { } from 'jest-matcher-utils'; import {equals} from './jasmine_utils'; -export const createMatcher = (matcherName, fromPromise) => ( +export const createMatcher = (matcherName: string, fromPromise?: boolean) => ( actual: Function, expected: string | Error | RegExp, ) => { From b492b59e03f394a4ba1f5f449e2a2680a9d660c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Sentkiewicz?= Date: Tue, 14 Nov 2017 08:11:45 +0100 Subject: [PATCH 4/4] update changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Łukasz Sentkiewicz --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index abc4bd929f62..905ce31c0884 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Fixes +* `[expect]` fix .toThrow for promises + ([#4884](https://github.com/facebook/jest/pull/4884)) * `[jest-docblock]` pragmas should preserve urls ([#4837](https://github.com/facebook/jest/pull/4629)) * `[jest-cli]` Check if `npm_lifecycle_script` calls Jest directly