From 8cf95595d5465ff4f5d371b699df7ae2e08afd23 Mon Sep 17 00:00:00 2001 From: chaptergy Date: Thu, 5 Dec 2024 15:56:05 +0000 Subject: [PATCH 1/2] feat: add getNextMockImplementation --- docs/api/mock.md | 14 +++++++++++++- packages/spy/src/index.ts | 17 +++++++++++++---- test/core/test/jest-mock.test.ts | 31 +++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/docs/api/mock.md b/docs/api/mock.md index 9579cc03f29b..1790c96bbee0 100644 --- a/docs/api/mock.md +++ b/docs/api/mock.md @@ -30,7 +30,19 @@ The custom function implementation in the types below is marked with a generic ` function getMockImplementation(): T | undefined ``` -Returns current mock implementation if there is one. +Returns current mock implementation if there is one. Temporary implementations with `mock...Once` are ignored. + +If the mock was created with [`vi.fn`](/api/vi#vi-fn), it will use the provided method as the mock implementation. + +If the mock was created with [`vi.spyOn`](/api/vi#vi-spyon), it will return `undefined` unless a custom implementation is provided. + +## getNextMockImplementation + +```ts +function getNextMockImplementation(): T | undefined +``` + +Returns the mock implementation used for the next mock call if there is one. This includes temporary implementations created with `mock...Once`. If the mock was created with [`vi.fn`](/api/vi#vi-fn), it will use the provided method as the mock implementation. diff --git a/packages/spy/src/index.ts b/packages/spy/src/index.ts index 2de229bb9908..ad299620a9da 100644 --- a/packages/spy/src/index.ts +++ b/packages/spy/src/index.ts @@ -215,14 +215,21 @@ export interface MockInstance { */ mockRestore(): void /** - * Performs the same actions as `mockReset` and restores the inner implementation to the original function. + * Returns current permanent mock implementation if there is one. Temporary implementations with `mock...Once` are ignored. * - * Note that restoring a mock created with `vi.fn()` will set the implementation to an empty function that returns `undefined`. Restoring a mock created with `vi.fn(impl)` will restore the implementation to `impl`. + * If mock was created with `vi.fn`, it will consider passed down method as a mock implementation. * - * To automatically call this method before each test, enable the [`restoreMocks`](https://vitest.dev/config/#restoremocks) setting in the configuration. - * @see https://vitest.dev/api/mock#getmockimplementation + * If mock was created with `vi.spyOn`, it will return `undefined` unless a custom implementation was provided. */ getMockImplementation(): NormalizedPrecedure | undefined + /** + * Returns the mock implementation used for the next mock call if there is one. This includes temporary implementations created with `mock...Once`. + * + * If mock was created with `vi.fn`, it will consider passed down method as a mock implementation. + * + * If mock was created with `vi.spyOn`, it will return `undefined` unless a custom implementation was provided. + */ + getNextMockImplementation(): NormalizedPrecedure | undefined /** * Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. * @see https://vitest.dev/api/mock#mockimplementation @@ -551,6 +558,8 @@ function enhanceSpy( } stub.getMockImplementation = () => implementation + stub.getNextMockImplementation = () => + implementationChangedTemporarily ? implementation : (onceImplementations.at(0) || implementation) stub.mockImplementation = (fn: T) => { implementation = fn state.willCall(mockCall) diff --git a/test/core/test/jest-mock.test.ts b/test/core/test/jest-mock.test.ts index a6a888c6cfd1..99e59611b3b4 100644 --- a/test/core/test/jest-mock.test.ts +++ b/test/core/test/jest-mock.test.ts @@ -493,4 +493,35 @@ describe('jest mock compat layer', () => { vi.mocked(dogMax.speak).mockReturnValue('woof woof') expect(dogMax.speak()).toBe('woof woof') }) + + it('returns only permanent implementations from getMockImplementation()', () => { + const fn = vi.fn() + + fn.mockImplementationOnce(() => 'mocked value') + expect(fn.getMockImplementation()).toBe(undefined) + + const mockImplementation = () => 'other mocked value' + fn.mockImplementation(mockImplementation) + expect(fn.getMockImplementation()).toBe(mockImplementation) + }) + + it('returns temporary implementations from getNextMockImplementation()', () => { + const fn = vi.fn() + + const temporaryMockImplementation = () => 'mocked value' + fn.mockImplementationOnce(temporaryMockImplementation) + expect(fn.getNextMockImplementation()).toBe(temporaryMockImplementation) + + // After calling it, it should be back to undefined + fn() + expect(fn.getNextMockImplementation()).toBe(undefined) + + const mockImplementation = () => 'other mocked value' + fn.mockImplementation(mockImplementation) + expect(fn.getNextMockImplementation()).toBe(mockImplementation) + + // It should also overwrite permanent implementations + fn.mockImplementationOnce(temporaryMockImplementation) + expect(fn.getNextMockImplementation()).toBe(temporaryMockImplementation) + }) }) From eaee0c239b997595767618a23709da19f4afef00 Mon Sep 17 00:00:00 2001 From: chaptergy Date: Mon, 6 Jan 2025 12:44:30 +0000 Subject: [PATCH 2/2] fix(vitest)!: replaces getMockImplementation with logic of getNextMockImplementation --- docs/api/mock.md | 14 +------------- packages/spy/src/index.ts | 13 ++----------- test/core/test/jest-mock.test.ts | 21 +++++---------------- 3 files changed, 8 insertions(+), 40 deletions(-) diff --git a/docs/api/mock.md b/docs/api/mock.md index 1790c96bbee0..9579cc03f29b 100644 --- a/docs/api/mock.md +++ b/docs/api/mock.md @@ -30,19 +30,7 @@ The custom function implementation in the types below is marked with a generic ` function getMockImplementation(): T | undefined ``` -Returns current mock implementation if there is one. Temporary implementations with `mock...Once` are ignored. - -If the mock was created with [`vi.fn`](/api/vi#vi-fn), it will use the provided method as the mock implementation. - -If the mock was created with [`vi.spyOn`](/api/vi#vi-spyon), it will return `undefined` unless a custom implementation is provided. - -## getNextMockImplementation - -```ts -function getNextMockImplementation(): T | undefined -``` - -Returns the mock implementation used for the next mock call if there is one. This includes temporary implementations created with `mock...Once`. +Returns current mock implementation if there is one. If the mock was created with [`vi.fn`](/api/vi#vi-fn), it will use the provided method as the mock implementation. diff --git a/packages/spy/src/index.ts b/packages/spy/src/index.ts index ad299620a9da..cc27ac1c52fa 100644 --- a/packages/spy/src/index.ts +++ b/packages/spy/src/index.ts @@ -215,21 +215,13 @@ export interface MockInstance { */ mockRestore(): void /** - * Returns current permanent mock implementation if there is one. Temporary implementations with `mock...Once` are ignored. + * Returns current permanent mock implementation if there is one. * * If mock was created with `vi.fn`, it will consider passed down method as a mock implementation. * * If mock was created with `vi.spyOn`, it will return `undefined` unless a custom implementation was provided. */ getMockImplementation(): NormalizedPrecedure | undefined - /** - * Returns the mock implementation used for the next mock call if there is one. This includes temporary implementations created with `mock...Once`. - * - * If mock was created with `vi.fn`, it will consider passed down method as a mock implementation. - * - * If mock was created with `vi.spyOn`, it will return `undefined` unless a custom implementation was provided. - */ - getNextMockImplementation(): NormalizedPrecedure | undefined /** * Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. * @see https://vitest.dev/api/mock#mockimplementation @@ -557,8 +549,7 @@ function enhanceSpy( return stub } - stub.getMockImplementation = () => implementation - stub.getNextMockImplementation = () => + stub.getMockImplementation = () => implementationChangedTemporarily ? implementation : (onceImplementations.at(0) || implementation) stub.mockImplementation = (fn: T) => { implementation = fn diff --git a/test/core/test/jest-mock.test.ts b/test/core/test/jest-mock.test.ts index 99e59611b3b4..08ae89cb860c 100644 --- a/test/core/test/jest-mock.test.ts +++ b/test/core/test/jest-mock.test.ts @@ -494,34 +494,23 @@ describe('jest mock compat layer', () => { expect(dogMax.speak()).toBe('woof woof') }) - it('returns only permanent implementations from getMockImplementation()', () => { - const fn = vi.fn() - - fn.mockImplementationOnce(() => 'mocked value') - expect(fn.getMockImplementation()).toBe(undefined) - - const mockImplementation = () => 'other mocked value' - fn.mockImplementation(mockImplementation) - expect(fn.getMockImplementation()).toBe(mockImplementation) - }) - - it('returns temporary implementations from getNextMockImplementation()', () => { + it('returns temporary implementations from getMockImplementation()', () => { const fn = vi.fn() const temporaryMockImplementation = () => 'mocked value' fn.mockImplementationOnce(temporaryMockImplementation) - expect(fn.getNextMockImplementation()).toBe(temporaryMockImplementation) + expect(fn.getMockImplementation()).toBe(temporaryMockImplementation) // After calling it, it should be back to undefined fn() - expect(fn.getNextMockImplementation()).toBe(undefined) + expect(fn.getMockImplementation()).toBe(undefined) const mockImplementation = () => 'other mocked value' fn.mockImplementation(mockImplementation) - expect(fn.getNextMockImplementation()).toBe(mockImplementation) + expect(fn.getMockImplementation()).toBe(mockImplementation) // It should also overwrite permanent implementations fn.mockImplementationOnce(temporaryMockImplementation) - expect(fn.getNextMockImplementation()).toBe(temporaryMockImplementation) + expect(fn.getMockImplementation()).toBe(temporaryMockImplementation) }) })