diff --git a/CHANGELOG.md b/CHANGELOG.md index b4c5c7c9a190..2ae290315327 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - `[jest-jasmine2]` Fix describe return value warning being shown if the describe function throws ([#8335](https://github.com/facebook/jest/pull/8335)) - `[jest-environment-jsdom]` Re-declare global prototype of JSDOMEnvironment ([#8352](https://github.com/facebook/jest/pull/8352)) - `[jest-snapshot]` Handle arrays when merging snapshots ([#7089](https://github.com/facebook/jest/pull/7089)) +- `[expect]` Extract names of async and generator functions ([#8362](https://github.com/facebook/jest/pull/8362)) ### Chore & Maintenance diff --git a/packages/expect/src/__tests__/asymmetricMatchers.test.js b/packages/expect/src/__tests__/asymmetricMatchers.test.js index 9b1d55074cad..f0166e38d04b 100644 --- a/packages/expect/src/__tests__/asymmetricMatchers.test.js +++ b/packages/expect/src/__tests__/asymmetricMatchers.test.js @@ -42,6 +42,47 @@ test('Any.toAsymmetricMatcher()', () => { jestExpect(any(Number).toAsymmetricMatcher()).toBe('Any'); }); +test('Any.toAsymmetricMatcher() with function name', () => { + [ + ['someFunc', function someFunc() {}], + ['$someFunc', function $someFunc() {}], + [ + '$someFunc2', + (function() { + function $someFunc2() {} + Object.defineProperty($someFunc2, 'name', {value: ''}); + return $someFunc2; + })(), + ], + [ + '$someAsyncFunc', + (function() { + async function $someAsyncFunc() {} + Object.defineProperty($someAsyncFunc, 'name', {value: ''}); + return $someAsyncFunc; + })(), + ], + [ + '$someGeneratorFunc', + (function() { + function* $someGeneratorFunc() {} + Object.defineProperty($someGeneratorFunc, 'name', {value: ''}); + return $someGeneratorFunc; + })(), + ], + [ + '$someFuncWithFakeToString', + (function() { + function $someFuncWithFakeToString() {} + $someFuncWithFakeToString.toString = () => 'Fake to string'; + return $someFuncWithFakeToString; + })(), + ], + ].forEach(([name, fn]: [string, any]) => { + jestExpect(any(fn).toAsymmetricMatcher()).toBe(`Any<${name}>`); + }); +}); + test('Any throws when called with empty constructor', () => { jestExpect(() => any()).toThrow(); }); diff --git a/packages/expect/src/jasmineUtils.ts b/packages/expect/src/jasmineUtils.ts index 8c98416fbd66..3bf94b3cc3c8 100644 --- a/packages/expect/src/jasmineUtils.ts +++ b/packages/expect/src/jasmineUtils.ts @@ -37,6 +37,8 @@ export function equals( return eq(a, b, [], [], customTesters, strictCheck ? hasKey : hasDefinedKey); } +const functionToString = Function.prototype.toString; + function isAsymmetric(obj: any) { return !!obj && isA('Function', obj.asymmetricMatch); } @@ -258,7 +260,9 @@ export function fnNameFor(func: Function) { return func.name; } - const matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/); + const matches = functionToString + .call(func) + .match(/^(?:async)?\s*function\s*\*?\s*([\w$]+)\s*\(/); return matches ? matches[1] : ''; }