diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b7e320792a7..9703ece8938b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - `[jest-mock]` Improve `isMockFunction` to infer types of passed function ([#12442](https://github.com/facebook/jest/pull/12442)) - `[jest-mock]` [**BREAKING**] Improve the usage of `jest.fn` generic type argument ([#12489](https://github.com/facebook/jest/pull/12489)) - `[jest-mock]` Add support for auto-mocking async generator functions ([#11080](https://github.com/facebook/jest/pull/11080)) +- `[jest-mock]` [**BREAKING**] Make `jest.mocked()` helper to always return deeply mock-typed object. The `MaybeMockedDeep`, `MockedFunctionDeep` and `MockedObjectDeep` types are now exposed as `MaybeMocked`, `MockedFunction` and `MockedObject` ([#12516](https://github.com/facebook/jest/pull/12516)) - `[jest-resolve]` [**BREAKING**] Add support for `package.json` `exports` ([#11961](https://github.com/facebook/jest/pull/11961), [#12373](https://github.com/facebook/jest/pull/12373)) - `[jest-resolve, jest-runtime]` Add support for `data:` URI import and mock ([#12392](https://github.com/facebook/jest/pull/12392)) - `[jest-resolve, jest-runtime]` Add support for async resolver ([#11540](https://github.com/facebook/jest/pull/11540)) diff --git a/docs/JestObjectAPI.md b/docs/JestObjectAPI.md index 0449d43a24bd..6fe431a2f39b 100644 --- a/docs/JestObjectAPI.md +++ b/docs/JestObjectAPI.md @@ -584,16 +584,13 @@ Returns the `jest` object for chaining. Restores all mocks back to their original value. Equivalent to calling [`.mockRestore()`](MockFunctionAPI.md#mockfnmockrestore) on every mocked function. Beware that `jest.restoreAllMocks()` only works when the mock was created with `jest.spyOn`; other mocks will require you to manually restore them. -### `jest.mocked(item: T, deep = false)` +### `jest.mocked(mockedObject)` -The `mocked` test helper provides typings on your mocked modules and even their deep methods, based on the typing of its source. It makes use of the latest TypeScript feature, so you even have argument types completion in the IDE (as opposed to `jest.MockInstance`). +The `mocked` test helper provides typings on your mocked modules and even their deep methods, based on the typing of its source. _Note: while it needs to be a function so that input type is changed, the helper itself does nothing else than returning the given input value._ -Example: - -```ts -// foo.ts +```ts title="foo.ts" export const foo = { a: { b: { @@ -602,17 +599,14 @@ export const foo = { }, }, }, - name: () => 'foo', }; ``` -```ts -// foo.spec.ts +```ts title="foo.test.ts" import {foo} from './foo'; jest.mock('./foo'); -// here the whole foo var is mocked deeply -const mockedFoo = jest.mocked(foo, true); +const mockedFoo = jest.mocked(foo); test('deep', () => { // there will be no TS error here, and you'll have completion in modern IDEs @@ -620,12 +614,6 @@ test('deep', () => { // same here expect(mockedFoo.a.b.c.hello.mock.calls).toHaveLength(1); }); - -test('direct', () => { - foo.name(); - // here only foo.name is mocked (or its methods if it's an object) - expect(jest.mocked(foo.name).mock.calls).toHaveLength(1); -}); ``` ## Mock Timers diff --git a/packages/jest-mock/__typetests__/mocked.test.ts b/packages/jest-mock/__typetests__/mocked.test.ts new file mode 100644 index 000000000000..556f1c701a57 --- /dev/null +++ b/packages/jest-mock/__typetests__/mocked.test.ts @@ -0,0 +1,25 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {expectType} from 'tsd-lite'; +import {mocked} from 'jest-mock'; + +const foo = { + a: { + b: { + c: { + hello: (name: string): string => `Hello, ${name}`, + }, + }, + }, +}; + +const mockedFoo = mocked(foo); + +expectType(mockedFoo.a.b.c.hello('me')); + +expectType>(mockedFoo.a.b.c.hello.mock.calls); diff --git a/packages/jest-mock/src/index.ts b/packages/jest-mock/src/index.ts index a478f0f1689f..8c7647a5f2d4 100644 --- a/packages/jest-mock/src/index.ts +++ b/packages/jest-mock/src/index.ts @@ -67,24 +67,14 @@ export interface MockWithArgs extends MockInstance { (...args: Parameters): ReturnType; } -export type MockedFunction = MockWithArgs & { - [K in keyof T]: T[K]; -}; - -export type MockedFunctionDeep = MockWithArgs & - MockedObjectDeep; +export type MockedFunction = MockWithArgs & + MockedObject; export type MockedObject = MaybeMockedConstructor & { [K in MethodLikeKeys]: T[K] extends FunctionLike ? MockedFunction : T[K]; -} & {[K in PropertyLikeKeys]: T[K]}; - -export type MockedObjectDeep = MaybeMockedConstructor & { - [K in MethodLikeKeys]: T[K] extends FunctionLike - ? MockedFunctionDeep - : T[K]; -} & {[K in PropertyLikeKeys]: MaybeMockedDeep}; +} & {[K in PropertyLikeKeys]: MaybeMocked}; export type MaybeMocked = T extends FunctionLike ? MockedFunction @@ -92,12 +82,6 @@ export type MaybeMocked = T extends FunctionLike ? MockedObject : T; -export type MaybeMockedDeep = T extends FunctionLike - ? MockedFunctionDeep - : T extends object - ? MockedObjectDeep - : T; - export type Mocked = { [P in keyof T]: T[P] extends FunctionLike ? MockInstance @@ -1216,13 +1200,8 @@ export class ModuleMocker { return value == null ? `${value}` : typeof value; } - // the typings test helper - mocked(item: T, deep?: false): MaybeMocked; - - mocked(item: T, deep: true): MaybeMockedDeep; - - mocked(item: T, _deep = false): MaybeMocked | MaybeMockedDeep { - return item as any; + mocked(mockedObject: T): MaybeMocked { + return mockedObject as MaybeMocked; } }