Skip to content

Commit 46fb4cb

Browse files
authored
fix(types): accept MockInstance as stubbing target (#16)
1 parent cbe8f01 commit 46fb4cb

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

src/stubs.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import type { Mock } from 'vitest'
21
import {
32
createBehaviorStack,
43
type BehaviorStack,
54
BehaviorType,
65
} from './behaviors.ts'
76
import { NotAMockFunctionError } from './errors.ts'
8-
import type { AnyFunction } from './types.ts'
7+
import type { AnyFunction, MockInstance } from './types.ts'
98

109
const BEHAVIORS_KEY = Symbol('behaviors')
1110

@@ -63,7 +62,7 @@ export const configureStub = <TFunc extends AnyFunction>(
6362
return behaviors
6463
}
6564

66-
export const validateSpy = (maybeSpy: unknown): Mock => {
65+
export const validateSpy = (maybeSpy: unknown): MockInstance => {
6766
if (
6867
typeof maybeSpy === 'function' &&
6968
'mockImplementation' in maybeSpy &&
@@ -73,14 +72,14 @@ export const validateSpy = (maybeSpy: unknown): Mock => {
7372
'getMockName' in maybeSpy &&
7473
typeof maybeSpy.getMockName === 'function'
7574
) {
76-
return maybeSpy as Mock
75+
return maybeSpy as unknown as MockInstance
7776
}
7877

7978
throw new NotAMockFunctionError(maybeSpy)
8079
}
8180

8281
export const getBehaviorStack = <TFunc extends AnyFunction>(
83-
spy: Mock,
82+
spy: MockInstance,
8483
): BehaviorStack<TFunc> | undefined => {
8584
const existingImplementation = spy.getMockImplementation() as
8685
| WhenStubImplementation<TFunc>

src/types.ts

+17
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,20 @@
22

33
/** Any function, for use in `extends` */
44
export type AnyFunction = (...args: never[]) => unknown
5+
6+
/**
7+
* Minimally typed version of Vitest's `MockInstance`.
8+
*
9+
* Used to ensure backwards compatibility
10+
* with older versions of Vitest.
11+
*/
12+
export interface MockInstance<TFunc extends AnyFunction = AnyFunction> {
13+
getMockName(): string
14+
getMockImplementation(): TFunc | undefined
15+
mockImplementation: (impl: TFunc) => this
16+
mock: MockContext<TFunc>
17+
}
18+
19+
export interface MockContext<TFunc extends AnyFunction> {
20+
calls: Parameters<TFunc>[]
21+
}

src/vitest-when.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { configureStub } from './stubs.ts'
22
import type { WhenOptions } from './behaviors.ts'
3-
import type { AnyFunction } from './types.ts'
3+
import type { AnyFunction, MockInstance } from './types.ts'
44
import { getDebug, type DebugResult } from './debug.ts'
55

66
export { type WhenOptions, type Behavior, BehaviorType } from './behaviors.ts'
@@ -22,7 +22,7 @@ export interface Stub<TArgs extends unknown[], TReturn> {
2222
}
2323

2424
export const when = <TFunc extends AnyFunction>(
25-
spy: TFunc,
25+
spy: TFunc | MockInstance<TFunc>,
2626
options: WhenOptions = {},
2727
): StubWrapper<TFunc> => {
2828
const behaviorStack = configureStub(spy)

test/typing.test-d.ts

+10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ describe('vitest-when type signatures', () => {
2323
assertType<subject.Stub<[number], any>>(stub)
2424
})
2525

26+
it('should handle an spied function', () => {
27+
const target = { simple }
28+
const spy = vi.spyOn(target, 'simple')
29+
const stub = subject.when(spy).calledWith(1)
30+
31+
stub.thenReturn('hello')
32+
33+
assertType<subject.Stub<[number], any>>(stub)
34+
})
35+
2636
it('should handle a simple function', () => {
2737
const stub = subject.when(simple).calledWith(1)
2838

0 commit comments

Comments
 (0)