From a3110911c57a19c820464df16ada6f178165c5d6 Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 8 Dec 2021 12:44:13 +0530 Subject: [PATCH 1/5] Adding mocked in JestObject --- packages/jest-environment/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/jest-environment/src/index.ts b/packages/jest-environment/src/index.ts index 42cb7f8927c1..b5920f7d00e9 100644 --- a/packages/jest-environment/src/index.ts +++ b/packages/jest-environment/src/index.ts @@ -10,6 +10,7 @@ import type {LegacyFakeTimers, ModernFakeTimers} from '@jest/fake-timers'; import type {Circus, Config, Global} from '@jest/types'; import type { fn as JestMockFn, + mocked as JestMockMocked, spyOn as JestMockSpyOn, ModuleMocker, } from 'jest-mock'; @@ -191,6 +192,7 @@ export interface Jest { * jest.spyOn; other mocks will require you to manually restore them. */ restoreAllMocks(): Jest; + mocked: typeof JestMockMocked; /** * Runs failed tests n-times until they pass or until the max number of * retries is exhausted. This only works with `jest-circus`! From 0847c2be924f0b53a3adbdf3d7fe07db21cf0798 Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 8 Dec 2021 13:12:41 +0530 Subject: [PATCH 2/5] update versioned docs --- .../version-27.2/JestObjectAPI.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/website/versioned_docs/version-27.2/JestObjectAPI.md b/website/versioned_docs/version-27.2/JestObjectAPI.md index ddfd7fafea74..e5c4f19a5a06 100644 --- a/website/versioned_docs/version-27.2/JestObjectAPI.md +++ b/website/versioned_docs/version-27.2/JestObjectAPI.md @@ -578,6 +578,47 @@ 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)` + +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`). + +_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 +export const foo = { + a: { + b: { + c: { + hello: (name: string) => `Hello, ${name}`, + }, + }, + }, + name: () => 'foo', +}; +``` + +```ts +// foo.spec.ts +import {foo} from './foo'; +jest.mock('./foo'); +// here the whole foo var is mocked deeply +const mockedFoo = jest.mocked(foo, true); +test('deep', () => { + // there will be no TS error here, and you'll have completion in modern IDEs + mockedFoo.a.b.c.hello('me'); + // 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(mocked(foo.name).mock.calls).toHaveLength(1); +}); +``` + ## Mock Timers ### `jest.useFakeTimers(implementation?: 'modern' | 'legacy')` From 96dd2c3b0fc915b71e946129fde0396266fd01fb Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 8 Dec 2021 13:38:26 +0530 Subject: [PATCH 3/5] jest-runtime --- packages/jest-runtime/src/index.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 8640b45ea405..34bc710da54b 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1924,6 +1924,7 @@ export default class Runtime { }; const fn = this._moduleMocker.fn.bind(this._moduleMocker); const spyOn = this._moduleMocker.spyOn.bind(this._moduleMocker); + const mocked = this._moduleMocker.mocked.bind(this._moduleMocker); const setTimeout = (timeout: number) => { if (this._environment.global.jasmine) { @@ -1942,24 +1943,20 @@ export default class Runtime { }; const jestObject: Jest = { - advanceTimersByTime: (msToRun: number) => - _getFakeTimers().advanceTimersByTime(msToRun), - advanceTimersToNextTimer: (steps?: number) => - _getFakeTimers().advanceTimersToNextTimer(steps), + advanceTimersByTime: (msToRun: number) => _getFakeTimers().advanceTimersByTime(msToRun), + advanceTimersToNextTimer: (steps?: number) => _getFakeTimers().advanceTimersToNextTimer(steps), autoMockOff: disableAutomock, autoMockOn: enableAutomock, clearAllMocks, clearAllTimers: () => _getFakeTimers().clearAllTimers(), - createMockFromModule: (moduleName: string) => - this._generateMock(from, moduleName), + createMockFromModule: (moduleName: string) => this._generateMock(from, moduleName), deepUnmock, disableAutomock, doMock: mock, dontMock: unmock, enableAutomock, fn, - genMockFromModule: (moduleName: string) => - this._generateMock(from, moduleName), + genMockFromModule: (moduleName: string) => this._generateMock(from, moduleName), getRealSystemTime: () => { const fakeTimers = _getFakeTimers(); @@ -1967,7 +1964,7 @@ export default class Runtime { return fakeTimers.getRealSystemTime(); } else { throw new TypeError( - 'getRealSystemTime is not available when not using modern timers', + 'getRealSystemTime is not available when not using modern timers' ); } }, @@ -1988,15 +1985,14 @@ export default class Runtime { fakeTimers.runAllImmediates(); } else { throw new TypeError( - 'runAllImmediates is not available when using modern timers', + 'runAllImmediates is not available when using modern timers' ); } }, runAllTicks: () => _getFakeTimers().runAllTicks(), runAllTimers: () => _getFakeTimers().runAllTimers(), runOnlyPendingTimers: () => _getFakeTimers().runOnlyPendingTimers(), - setMock: (moduleName: string, mock: unknown) => - setMockFactory(moduleName, () => mock), + setMock: (moduleName: string, mock: unknown) => setMockFactory(moduleName, () => mock), setSystemTime: (now?: number | Date) => { const fakeTimers = _getFakeTimers(); @@ -2004,7 +2000,7 @@ export default class Runtime { fakeTimers.setSystemTime(now); } else { throw new TypeError( - 'setSystemTime is not available when not using modern timers', + 'setSystemTime is not available when not using modern timers' ); } }, @@ -2014,6 +2010,7 @@ export default class Runtime { unstable_mockModule: mockModule, useFakeTimers, useRealTimers, + mocked, }; return jestObject; } From 3094fdfaf1444d82d80b02bf15c1f5e7f1b51048 Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 8 Dec 2021 15:47:34 +0530 Subject: [PATCH 4/5] remove docs changes --- .../version-27.2/JestObjectAPI.md | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/website/versioned_docs/version-27.2/JestObjectAPI.md b/website/versioned_docs/version-27.2/JestObjectAPI.md index e5c4f19a5a06..ddfd7fafea74 100644 --- a/website/versioned_docs/version-27.2/JestObjectAPI.md +++ b/website/versioned_docs/version-27.2/JestObjectAPI.md @@ -578,47 +578,6 @@ 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)` - -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`). - -_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 -export const foo = { - a: { - b: { - c: { - hello: (name: string) => `Hello, ${name}`, - }, - }, - }, - name: () => 'foo', -}; -``` - -```ts -// foo.spec.ts -import {foo} from './foo'; -jest.mock('./foo'); -// here the whole foo var is mocked deeply -const mockedFoo = jest.mocked(foo, true); -test('deep', () => { - // there will be no TS error here, and you'll have completion in modern IDEs - mockedFoo.a.b.c.hello('me'); - // 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(mocked(foo.name).mock.calls).toHaveLength(1); -}); -``` - ## Mock Timers ### `jest.useFakeTimers(implementation?: 'modern' | 'legacy')` From 55c9faa8f33bfaf4b94adf9684d7a2ba4d7923d5 Mon Sep 17 00:00:00 2001 From: Rajat Date: Wed, 8 Dec 2021 23:59:31 +0530 Subject: [PATCH 5/5] eslint --- packages/jest-runtime/src/index.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 34bc710da54b..2746f303b1f8 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1943,20 +1943,24 @@ export default class Runtime { }; const jestObject: Jest = { - advanceTimersByTime: (msToRun: number) => _getFakeTimers().advanceTimersByTime(msToRun), - advanceTimersToNextTimer: (steps?: number) => _getFakeTimers().advanceTimersToNextTimer(steps), + advanceTimersByTime: (msToRun: number) => + _getFakeTimers().advanceTimersByTime(msToRun), + advanceTimersToNextTimer: (steps?: number) => + _getFakeTimers().advanceTimersToNextTimer(steps), autoMockOff: disableAutomock, autoMockOn: enableAutomock, clearAllMocks, clearAllTimers: () => _getFakeTimers().clearAllTimers(), - createMockFromModule: (moduleName: string) => this._generateMock(from, moduleName), + createMockFromModule: (moduleName: string) => + this._generateMock(from, moduleName), deepUnmock, disableAutomock, doMock: mock, dontMock: unmock, enableAutomock, fn, - genMockFromModule: (moduleName: string) => this._generateMock(from, moduleName), + genMockFromModule: (moduleName: string) => + this._generateMock(from, moduleName), getRealSystemTime: () => { const fakeTimers = _getFakeTimers(); @@ -1964,7 +1968,7 @@ export default class Runtime { return fakeTimers.getRealSystemTime(); } else { throw new TypeError( - 'getRealSystemTime is not available when not using modern timers' + 'getRealSystemTime is not available when not using modern timers', ); } }, @@ -1972,6 +1976,7 @@ export default class Runtime { isMockFunction: this._moduleMocker.isMockFunction, isolateModules, mock, + mocked, requireActual: this.requireActual.bind(this, from), requireMock: this.requireMock.bind(this, from), resetAllMocks, @@ -1985,14 +1990,15 @@ export default class Runtime { fakeTimers.runAllImmediates(); } else { throw new TypeError( - 'runAllImmediates is not available when using modern timers' + 'runAllImmediates is not available when using modern timers', ); } }, runAllTicks: () => _getFakeTimers().runAllTicks(), runAllTimers: () => _getFakeTimers().runAllTimers(), runOnlyPendingTimers: () => _getFakeTimers().runOnlyPendingTimers(), - setMock: (moduleName: string, mock: unknown) => setMockFactory(moduleName, () => mock), + setMock: (moduleName: string, mock: unknown) => + setMockFactory(moduleName, () => mock), setSystemTime: (now?: number | Date) => { const fakeTimers = _getFakeTimers(); @@ -2000,7 +2006,7 @@ export default class Runtime { fakeTimers.setSystemTime(now); } else { throw new TypeError( - 'setSystemTime is not available when not using modern timers' + 'setSystemTime is not available when not using modern timers', ); } }, @@ -2010,7 +2016,6 @@ export default class Runtime { unstable_mockModule: mockModule, useFakeTimers, useRealTimers, - mocked, }; return jestObject; }