diff --git a/CHANGELOG.md b/CHANGELOG.md index fa9845797717..36dab227162f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ ### Fixes - `[expect]` Move typings of `.not`, `.rejects` and `.resolves` modifiers outside of `Matchers` interface ([#12346](https://github.com/facebook/jest/pull/12346)) +- `[expect]` Throw useful error if `expect.extend` is called with invalid matchers ([#12488](https://github.com/facebook/jest/pull/12488)) - `[jest-config]` Correctly detect CI environment and update snapshots accordingly ([#12378](https://github.com/facebook/jest/pull/12378)) - `[jest-config]` Pass `moduleTypes` to `ts-node` to enforce CJS when transpiling ([#12397](https://github.com/facebook/jest/pull/12397)) - `[jest-config, jest-haste-map]` Allow searching for tests in `node_modules` by exposing `retainAllFiles` ([#11084](https://github.com/facebook/jest/pull/11084)) diff --git a/packages/expect/src/__tests__/extend.test.ts b/packages/expect/src/__tests__/extend.test.ts index 852dfb139f09..9ad98e356f9c 100644 --- a/packages/expect/src/__tests__/extend.test.ts +++ b/packages/expect/src/__tests__/extend.test.ts @@ -184,3 +184,27 @@ it('allows overriding existing extension', () => { jestExpect('foo').toAllowOverridingExistingMatcher(); }); + +it('throws descriptive errors for invalid matchers', () => { + expect(() => + jestExpect.extend({ + default: undefined, + }), + ).toThrow( + 'expect.extend: `default` is not a valid matcher. Must be a function, is "undefined"', + ); + expect(() => + jestExpect.extend({ + default: 42, + }), + ).toThrow( + 'expect.extend: `default` is not a valid matcher. Must be a function, is "number"', + ); + expect(() => + jestExpect.extend({ + default: 'foobar', + }), + ).toThrow( + 'expect.extend: `default` is not a valid matcher. Must be a function, is "string"', + ); +}); diff --git a/packages/expect/src/jestMatchersObject.ts b/packages/expect/src/jestMatchersObject.ts index 90e26e6b7779..121a3116f26d 100644 --- a/packages/expect/src/jestMatchersObject.ts +++ b/packages/expect/src/jestMatchersObject.ts @@ -6,6 +6,7 @@ * */ +import {getType} from 'jest-get-type'; import {AsymmetricMatcher} from './asymmetricMatchers'; import type { Expect, @@ -56,6 +57,15 @@ export const setMatchers = ( ): void => { Object.keys(matchers).forEach(key => { const matcher = matchers[key]; + + if (typeof matcher !== 'function') { + throw new TypeError( + `expect.extend: \`${key}\` is not a valid matcher. Must be a function, is "${getType( + matcher, + )}"`, + ); + } + Object.defineProperty(matcher, INTERNAL_MATCHER_FLAG, { value: isInternal, });