Skip to content

Commit

Permalink
feat: add getNextMockImplementation
Browse files Browse the repository at this point in the history
  • Loading branch information
chaptergy committed Dec 5, 2024
1 parent aa1dac3 commit 8cf9559
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
14 changes: 13 additions & 1 deletion docs/api/mock.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
17 changes: 13 additions & 4 deletions packages/spy/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,21 @@ export interface MockInstance<T extends Procedure = Procedure> {
*/
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<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 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<T> | 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
Expand Down Expand Up @@ -551,6 +558,8 @@ function enhanceSpy<T extends Procedure>(
}

stub.getMockImplementation = () => implementation
stub.getNextMockImplementation = () =>
implementationChangedTemporarily ? implementation : (onceImplementations.at(0) || implementation)
stub.mockImplementation = (fn: T) => {
implementation = fn
state.willCall(mockCall)
Expand Down
31 changes: 31 additions & 0 deletions test/core/test/jest-mock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
})

0 comments on commit 8cf9559

Please sign in to comment.