diff --git a/docs/api/mock.md b/docs/api/mock.md index 17843f0d6..9e051cb89 100644 --- a/docs/api/mock.md +++ b/docs/api/mock.md @@ -20,41 +20,55 @@ getApplesSpy.mock.calls.length === 1 You should use mock assertions (e.g., [`toHaveBeenCalled`](/api/expect#tohavebeencalled)) on [`expect`](/api/expect) to assert mock result. This API reference describes available properties and methods to manipulate mock behavior. +::: tip +The custom function implementation in the types below is marked with a generic ``. +::: + ## getMockImplementation -- **Type:** `(...args: any) => any` +```ts +function getMockImplementation(): T | undefined +``` Returns current mock implementation if there is one. -If mock was created with [`vi.fn`](/api/vi#vi-fn), it will consider passed down method as a mock implementation. +If the mock was created with [`vi.fn`](/api/vi#vi-fn), it will use the provided method as the mock implementation. -If mock was created with [`vi.spyOn`](/api/vi#vi-spyon), it will return `undefined` unless a custom implementation was provided. +If the mock was created with [`vi.spyOn`](/api/vi#vi-spyon), it will return `undefined` unless a custom implementation is provided. ## getMockName -- **Type:** `() => string` +```ts +function getMockName(): string +``` -Use it to return the name given to mock with method `.mockName(name)`. +Use it to return the name assigned to the mock with the `.mockName(name)` method. By default, it will return `vi.fn()`. ## mockClear -- **Type:** `() => MockInstance` +```ts +function mockClear(): MockInstance +``` -Clears all information about every call. After calling it, all properties on `.mock` will return empty state. This method does not reset implementations. It is useful if you need to clean up mock between different assertions. +Clears all information about every call. After calling it, all properties on `.mock` will return to their initial state. This method does not reset implementations. It is useful for cleaning up mocks between different assertions. -If you want this method to be called before each test automatically, you can enable [`clearMocks`](/config/#clearmocks) setting in config. +To automatically call this method before each test, enable the [`clearMocks`](/config/#clearmocks) setting in the configuration. ## mockName -- **Type:** `(name: string) => MockInstance` +```ts +function mockName(name: string): MockInstance +``` -Sets internal mock name. Useful to see the name of the mock if assertion fails. +Sets the internal mock name. This is useful for identifying the mock when an assertion fails. ## mockImplementation -- **Type:** `(fn: Function) => MockInstance` +```ts +function mockImplementation(fn: T): MockInstance +``` -Accepts a function that will be used as an implementation of the mock. +Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. ```ts const mockFn = vi.fn().mockImplementation((apples: number) => apples + 1) @@ -72,21 +86,23 @@ mockFn.mock.calls[1][0] === 1 // true ## mockImplementationOnce -- **Type:** `(fn: Function) => MockInstance` +```ts +function mockImplementationOnce(fn: T): MockInstance +``` -Accepts a function that will be used as mock's implementation during the next call. Can be chained so that multiple function calls produce different results. +Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. This method can be chained to produce different results for multiple function calls. ```ts const myMockFn = vi .fn() - .mockImplementationOnce(() => true) - .mockImplementationOnce(() => false) + .mockImplementationOnce(() => true) // 1st call + .mockImplementationOnce(() => false) // 2nd call -myMockFn() // true -myMockFn() // false +myMockFn() // 1st call: true +myMockFn() // 2nd call: false ``` -When the mocked function runs out of implementations, it will invoke the default implementation that was set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called: +When the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called: ```ts const myMockFn = vi @@ -100,8 +116,16 @@ console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn()) ## withImplementation -- **Type:** `(fn: Function, callback: () => void) => MockInstance` -- **Type:** `(fn: Function, callback: () => Promise) => Promise` +```ts +function withImplementation( + fn: T, + cb: () => void +): MockInstance +function withImplementation( + fn: T, + cb: () => Promise +): Promise> +``` Overrides the original mock implementation temporarily while the callback is being executed. @@ -137,21 +161,25 @@ Note that this method takes precedence over the [`mockImplementationOnce`](#mock ## mockRejectedValue -- **Type:** `(value: any) => MockInstance` +```ts +function mockRejectedValue(value: unknown): MockInstance +``` Accepts an error that will be rejected when async function is called. ```ts const asyncMock = vi.fn().mockRejectedValue(new Error('Async error')) -await asyncMock() // throws "Async error" +await asyncMock() // throws Error<'Async error'> ``` ## mockRejectedValueOnce -- **Type:** `(value: any) => MockInstance` +```ts +function mockRejectedValueOnce(value: unknown): MockInstance +``` -Accepts a value that will be rejected during the next function call. If chained, every consecutive call will reject specified value. +Accepts a value that will be rejected during the next function call. If chained, each consecutive call will reject the specified value. ```ts const asyncMock = vi @@ -159,33 +187,39 @@ const asyncMock = vi .mockResolvedValueOnce('first call') .mockRejectedValueOnce(new Error('Async error')) -await asyncMock() // first call -await asyncMock() // throws "Async error" +await asyncMock() // 'first call' +await asyncMock() // throws Error<'Async error'> ``` ## mockReset -- **Type:** `() => MockInstance` +```ts +function mockReset(): MockInstance +``` -Does what `mockClear` does and makes inner implementation an empty function (returning `undefined` when invoked). This also resets all "once" implementations. This is useful when you want to completely reset a mock to the default state. +Performs the same actions as `mockClear` and sets the inner implementation to an empty function (returning `undefined` when invoked). This also resets all "once" implementations. It is useful for completely resetting a mock to its default state. -If you want this method to be called before each test automatically, you can enable [`mockReset`](/config/#mockreset) setting in config. +To automatically call this method before each test, enable the [`mockReset`](/config/#mockreset) setting in the configuration. ## mockRestore -- **Type:** `() => MockInstance` +```ts +function mockRestore(): MockInstance +``` -Does what `mockReset` does and restores inner implementation to the original function. +Performs the same actions as `mockReset` and restores the inner implementation to the original function. -Note that restoring mock from `vi.fn()` will set implementation to an empty function that returns `undefined`. Restoring a `vi.fn(impl)` will restore implementation to `impl`. +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 you want this method to be called before each test automatically, you can enable [`restoreMocks`](/config/#restoremocks) setting in config. +To automatically call this method before each test, enable the [`restoreMocks`](/config/#restoremocks) setting in the configuration. ## mockResolvedValue -- **Type:** `(value: any) => MockInstance` +```ts +function mockResolvedValue(value: Awaited>): MockInstance +``` -Accepts a value that will be resolved when async function is called. +Accepts a value that will be resolved when the async function is called. TypeScript will only accept values that match the return type of the original function. ```ts const asyncMock = vi.fn().mockResolvedValue(42) @@ -195,9 +229,11 @@ await asyncMock() // 42 ## mockResolvedValueOnce -- **Type:** `(value: any) => MockInstance` +```ts +function mockResolvedValueOnce(value: Awaited>): MockInstance +``` -Accepts a value that will be resolved during the next function call. If chained, every consecutive call will resolve specified value. +Accepts a value that will be resolved during the next function call. TypeScript will only accept values that match the return type of the original function. If chained, each consecutive call will resolve the specified value. ```ts const asyncMock = vi @@ -214,9 +250,11 @@ await asyncMock() // default ## mockReturnThis -- **Type:** `() => MockInstance` +```ts +function mockReturnThis(): MockInstance +``` -Use this if you need to return `this` context from the method without invoking actual implementation. This is a shorthand for: +Use this if you need to return the `this` context from the method without invoking the actual implementation. This is a shorthand for: ```ts spy.mockImplementation(function () { @@ -226,9 +264,11 @@ spy.mockImplementation(function () { ## mockReturnValue -- **Type:** `(value: any) => MockInstance` +```ts +function mockReturnValue(value: ReturnType): MockInstance +``` -Accepts a value that will be returned whenever the mock function is called. +Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function. ```ts const mock = vi.fn() @@ -240,11 +280,13 @@ mock() // 43 ## mockReturnValueOnce -- **Type:** `(value: any) => MockInstance` +```ts +function mockReturnValueOnce(value: ReturnType): MockInstance +``` -Accepts a value that will be returned during the next function call. If chained, every consecutive call will return the specified value. +Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function. -When there are no more `mockReturnValueOnce` values to use, mock will fallback to previously defined implementation if there is one. +When the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called: ```ts const myMockFn = vi @@ -259,6 +301,10 @@ console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn()) ## mock.calls +```ts +const calls: Parameters[] +``` + This is an array containing all arguments for each call. One item of the array is the arguments of that call. ```js @@ -275,10 +321,45 @@ fn.mock.calls === [ ## mock.lastCall -This contains the arguments of the last call. If mock wasn't called, will return `undefined`. +```ts +const lastCall: Parameters | undefined +``` + +This contains the arguments of the last call. If mock wasn't called, it will return `undefined`. ## mock.results +```ts +interface MockResultReturn { + type: 'return' + /** + * The value that was returned from the function. + * If function returned a Promise, then this will be a resolved value. + */ + value: T +} + +interface MockResultIncomplete { + type: 'incomplete' + value: undefined +} + +interface MockResultThrow { + type: 'throw' + /** + * An error that was thrown during function execution. + */ + value: any +} + +type MockResult = + | MockResultReturn + | MockResultThrow + | MockResultIncomplete + +const results: MockResult>[] +``` + This is an array containing all values that were `returned` from the function. One item of the array is an object with properties `type` and `value`. Available types are: - `'return'` - function returned without throwing. @@ -314,6 +395,24 @@ fn.mock.results === [ ## mock.settledResults +```ts +interface MockSettledResultFulfilled { + type: 'fulfilled' + value: T +} + +interface MockSettledResultRejected { + type: 'rejected' + value: any +} + +export type MockSettledResult = + | MockSettledResultFulfilled + | MockSettledResultRejected + +const settledResults: MockSettledResult>>[] +``` + An array containing all values that were `resolved` or `rejected` from the function. This array will be empty if the function was never resolved or rejected. @@ -337,6 +436,10 @@ fn.mock.settledResults === [ ## mock.invocationCallOrder +```ts +const invocationCallOrder: number[] +``` + This property returns the order of the mock function's execution. It is an array of numbers that are shared between all defined mocks. ```js @@ -353,6 +456,10 @@ fn2.mock.invocationCallOrder === [2] ## mock.contexts +```ts +const contexts: ThisParameterType[] +``` + This property is an array of `this` values used during each call to the mock function. ```js @@ -368,6 +475,10 @@ fn.mock.contexts[1] === context ## mock.instances +```ts +const instances: ReturnType[] +``` + This property is an array containing all instances that were created when the mock was called with the `new` keyword. Note that this is an actual context (`this`) of the function, not a return value. ::: warning diff --git a/packages/spy/src/index.ts b/packages/spy/src/index.ts index 86e5e404f..ea8bf2708 100644 --- a/packages/spy/src/index.ts +++ b/packages/spy/src/index.ts @@ -42,6 +42,7 @@ export interface MockContext { /** * This is an array containing all arguments for each call. One item of the array is the arguments of that call. * + * @see https://vitest.dev/api/mock#mock-calls * @example * const fn = vi.fn() * @@ -56,15 +57,18 @@ export interface MockContext { calls: Parameters[] /** * This is an array containing all instances that were instantiated when mock was called with a `new` keyword. Note that this is an actual context (`this`) of the function, not a return value. + * @see https://vitest.dev/api/mock#mock-instances */ instances: ReturnType[] /** * An array of `this` values that were used during each call to the mock function. + * @see https://vitest.dev/api/mock#mock-contexts */ contexts: ThisParameterType[] /** * The order of mock's execution. This returns an array of numbers which are shared between all defined mocks. * + * @see https://vitest.dev/api/mock#mock-invocationcallorder * @example * const fn1 = vi.fn() * const fn2 = vi.fn() @@ -82,6 +86,7 @@ export interface MockContext { * * The `value` property contains the returned value or thrown error. If the function returned a `Promise`, then `result` will always be `'return'` even if the promise was rejected. * + * @see https://vitest.dev/api/mock#mock-results * @example * const fn = vi.fn() * .mockReturnValueOnce('result') @@ -111,6 +116,7 @@ export interface MockContext { * * This array will be empty if the function was never resolved or rejected. * + * @see https://vitest.dev/api/mock#mock-settledresults * @example * const fn = vi.fn().mockResolvedValueOnce('result') * @@ -136,6 +142,7 @@ export interface MockContext { settledResults: MockSettledResult>>[] /** * This contains the arguments of the last call. If spy wasn't called, will return `undefined`. + * @see https://vitest.dev/api/mock#mock-lastcall */ lastCall: Parameters | undefined } @@ -170,52 +177,62 @@ Jest uses the latter for `MockInstance.mockImplementation` etc... and it allows /* eslint-disable ts/method-signature-style */ export interface MockInstance { /** - * Use it to return the name given to mock with method `.mockName(name)`. + * Use it to return the name assigned to the mock with the `.mockName(name)` method. By default, it will return `vi.fn()`. + * @see https://vitest.dev/api/mock#getmockname */ getMockName(): string /** - * Sets internal mock name. Useful to see the name of the mock if an assertion fails. + * Sets the internal mock name. This is useful for identifying the mock when an assertion fails. + * @see https://vitest.dev/api/mock#mockname */ - mockName(n: string): this + mockName(name: string): this /** * Current context of the mock. It stores information about all invocation calls, instances, and results. */ mock: MockContext /** - * Clears all information about every call. After calling it, all properties on `.mock` will return an empty state. This method does not reset implementations. + * Clears all information about every call. After calling it, all properties on `.mock` will return to their initial state. This method does not reset implementations. It is useful for cleaning up mocks between different assertions. * - * It is useful if you need to clean up mock between different assertions. + * To automatically call this method before each test, enable the [`clearMocks`](https://vitest.dev/config/#clearmocks) setting in the configuration. + * @see https://vitest.dev/api/mock#mockclear */ mockClear(): this /** - * Does what `mockClear` does and makes inner implementation an empty function (returning `undefined` when invoked). This also resets all "once" implementations. + * Performs the same actions as `mockClear` and sets the inner implementation to an empty function (returning `undefined` when invoked). This also resets all "once" implementations. It is useful for completely resetting a mock to its default state. * - * This is useful when you want to completely reset a mock to the default state. + * To automatically call this method before each test, enable the [`mockReset`](https://vitest.dev/config/#mockreset) setting in the configuration. + * @see https://vitest.dev/api/mock#mockreset */ mockReset(): this /** * Does what `mockReset` does and restores inner implementation to the original function. * * Note that restoring mock from `vi.fn()` will set implementation to an empty function that returns `undefined`. Restoring a `vi.fn(impl)` will restore implementation to `impl`. + * @see https://vitest.dev/api/mock#mockrestore */ mockRestore(): void /** - * Returns current mock implementation if there is one. + * Performs the same actions as `mockReset` and restores the inner implementation to the original function. * - * If mock was created with `vi.fn`, it will consider passed down method as a mock implementation. + * 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.spyOn`, it will return `undefined` unless a custom implementation was provided. + * 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 */ getMockImplementation(): NormalizedPrecedure | undefined /** - * Accepts a function that will be used as an implementation of the mock. + * 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 * @example * const increment = vi.fn().mockImplementation(count => count + 1); * expect(increment(3)).toBe(4); */ mockImplementation(fn: NormalizedPrecedure): this /** - * Accepts a function that will be used as a mock implementation during the next call. Can be chained so that multiple function calls produce different results. + * Accepts a function to be used as the mock implementation. TypeScript expects the arguments and return type to match those of the original function. This method can be chained to produce different results for multiple function calls. + * + * When the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called. + * @see https://vitest.dev/api/mock#mockimplementationonce * @example * const fn = vi.fn(count => count).mockImplementationOnce(count => count + 1); * expect(fn(3)).toBe(4); @@ -224,6 +241,9 @@ export interface MockInstance { mockImplementationOnce(fn: NormalizedPrecedure): this /** * Overrides the original mock implementation temporarily while the callback is being executed. + * + * Note that this method takes precedence over the [`mockImplementationOnce`](https://vitest.dev/api/mock#mockimplementationonce). + * @see https://vitest.dev/api/mock#withimplementation * @example * const myMockFn = vi.fn(() => 'original') * @@ -236,17 +256,25 @@ export interface MockInstance { withImplementation(fn: NormalizedPrecedure, cb: () => T2): T2 extends Promise ? Promise : this /** - * Use this if you need to return `this` context from the method without invoking actual implementation. + * Use this if you need to return the `this` context from the method without invoking the actual implementation. + * @see https://vitest.dev/api/mock#mockreturnthis */ mockReturnThis(): this /** - * Accepts a value that will be returned whenever the mock function is called. + * Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function. + * @see https://vitest.dev/api/mock#mockreturnvalue + * @example + * const mock = vi.fn() + * mock.mockReturnValue(42) + * mock() // 42 + * mock.mockReturnValue(43) + * mock() // 43 */ - mockReturnValue(obj: ReturnType): this + mockReturnValue(value: ReturnType): this /** - * Accepts a value that will be returned during the next function call. If chained, every consecutive call will return the specified value. + * Accepts a value that will be returned whenever the mock function is called. TypeScript will only accept values that match the return type of the original function. * - * When there are no more `mockReturnValueOnce` values to use, mock will fallback to the previously defined implementation if there is one. + * When the mocked function runs out of implementations, it will invoke the default implementation set with `vi.fn(() => defaultValue)` or `.mockImplementation(() => defaultValue)` if they were called. * @example * const myMockFn = vi * .fn() @@ -257,16 +285,16 @@ export interface MockInstance { * // 'first call', 'second call', 'default' * console.log(myMockFn(), myMockFn(), myMockFn()) */ - mockReturnValueOnce(obj: ReturnType): this + mockReturnValueOnce(value: ReturnType): this /** - * Accepts a value that will be resolved when async function is called. + * Accepts a value that will be resolved when the async function is called. TypeScript will only accept values that match the return type of the original function. * @example * const asyncMock = vi.fn().mockResolvedValue(42) * asyncMock() // Promise<42> */ - mockResolvedValue(obj: Awaited>): this + mockResolvedValue(value: Awaited>): this /** - * Accepts a value that will be resolved during the next function call. If chained, every consecutive call will resolve specified value. + * Accepts a value that will be resolved during the next function call. TypeScript will only accept values that match the return type of the original function. If chained, each consecutive call will resolve the specified value. * @example * const myMockFn = vi * .fn() @@ -277,16 +305,16 @@ export interface MockInstance { * // Promise<'first call'>, Promise<'second call'>, Promise<'default'> * console.log(myMockFn(), myMockFn(), myMockFn()) */ - mockResolvedValueOnce(obj: Awaited>): this + mockResolvedValueOnce(value: Awaited>): this /** * Accepts an error that will be rejected when async function is called. * @example * const asyncMock = vi.fn().mockRejectedValue(new Error('Async error')) - * await asyncMock() // throws 'Async error' + * await asyncMock() // throws Error<'Async error'> */ - mockRejectedValue(obj: any): this + mockRejectedValue(error: unknown): this /** - * Accepts a value that will be rejected during the next function call. If chained, every consecutive call will reject specified value. + * Accepts a value that will be rejected during the next function call. If chained, each consecutive call will reject the specified value. * @example * const asyncMock = vi * .fn() @@ -294,9 +322,9 @@ export interface MockInstance { * .mockRejectedValueOnce(new Error('Async error')) * * await asyncMock() // first call - * await asyncMock() // throws "Async error" + * await asyncMock() // throws Error<'Async error'> */ - mockRejectedValueOnce(obj: any): this + mockRejectedValueOnce(error: unknown): this } /* eslint-enable ts/method-signature-style */