@@ -11,7 +11,7 @@ import {
11
11
RouterOptions ,
12
12
START_LOCATION ,
13
13
} from 'vue-router'
14
- import type { SinonStatic } from 'sinon'
14
+ import type { SinonSpy , SinonStatic } from 'sinon'
15
15
16
16
export const EmptyView = defineComponent ( {
17
17
name : 'RouterMockEmptyView' ,
@@ -28,28 +28,48 @@ function getJestGlobal() {
28
28
}
29
29
30
30
/**
31
- * Creates a spy on a function and allows clearing the mock.
31
+ * Creates a spy on a function
32
32
*
33
33
* @param fn function to spy on
34
- * @returns [ spy, mockClear()]
34
+ * @returns spy
35
35
*/
36
- function createSpy < Fn extends ( ...args : any [ ] ) => any > (
37
- fn : Fn
38
- ) : [ Fn , ( ) => void ] {
36
+ function createSpyAuto < Fn extends ( ...args : any [ ] ) => any > ( fn : Fn ) : Fn {
39
37
const sinon = getSinonGlobal ( )
40
38
if ( sinon ) {
41
- const spy = sinon . spy ( fn )
42
- return [ spy as unknown as Fn , ( ) => spy . resetHistory ( ) ]
39
+ return sinon . spy ( fn ) as unknown as Fn
43
40
}
44
41
45
42
const jest = getJestGlobal ( )
46
43
if ( jest ) {
47
- const spy = jest . fn ( fn )
48
- return [ spy as unknown as Fn , ( ) => spy . mockClear ( ) ]
44
+ return jest . fn ( fn ) as unknown as Fn
49
45
}
50
46
51
47
console . error (
52
- `Couldn't detect a global spy (tried jest and sinon). Make sure to provide a "createSpy" option when creating the router mock.`
48
+ `Couldn't detect a global spy (tried jest and sinon). Make sure to provide a "spy.create" option when creating the router mock.`
49
+ )
50
+ throw new Error ( 'No Spy Available' )
51
+ }
52
+
53
+ /**
54
+ * Restores a mock
55
+ *
56
+ * @param spy the spy to restore
57
+ */
58
+ function restoreSpyAuto < Fn extends ( ...args : any [ ] ) => any > (
59
+ spy : Fn
60
+ ) : ( ) => void {
61
+ const sinon = getSinonGlobal ( )
62
+ if ( sinon ) {
63
+ return ( ) => ( spy as unknown as SinonSpy ) . resetHistory ( )
64
+ }
65
+
66
+ const jest = getJestGlobal ( )
67
+ if ( jest ) {
68
+ return ( ) => ( spy as unknown as jest . Mock ) . mockClear ( )
69
+ }
70
+
71
+ console . error (
72
+ `Couldn't detect a global spy (tried jest and sinon). Make sure to provide a "spy.restore" option when creating the router mock.`
53
73
)
54
74
throw new Error ( 'No Spy Available' )
55
75
}
@@ -112,6 +132,21 @@ export interface RouterMock extends Router {
112
132
reset ( ) : void
113
133
}
114
134
135
+ /**
136
+ * Options passed to the `spy` option of the `createRouterMock` function
137
+ */
138
+ export interface RouterMockSpyOptions {
139
+ /**
140
+ * Creates a spy (for example, `create: fn => vi.fn(fn)` with vitest)
141
+ */
142
+ create : ( ...args : any [ ] ) => any
143
+
144
+ /**
145
+ * function to restore a spy (for example, `restore: spy => () => spy.restore()` with vitest)
146
+ */
147
+ restore : ( spy : any ) => ( ) => void
148
+ }
149
+
115
150
/**
116
151
* TODO: Allow passing a custom spy and detect common global ones like jest and cypress.
117
152
*/
@@ -155,6 +190,22 @@ export interface RouterMockOptions extends Partial<RouterOptions> {
155
190
* disable that behavior and throw when `router.push()` fails.
156
191
*/
157
192
noUndeclaredRoutes ?: boolean
193
+
194
+ /**
195
+ * By default the mock will use sinon or jest support to create and restore spies.
196
+ * This option allows to use a different testing framework,
197
+ * by providing a method to create spies, and one to restore them.
198
+ * For example, with vitest:
199
+ * ```
200
+ * const router = createRouterMock({
201
+ * spy: {
202
+ * create: fn => vi.fn(fn),
203
+ * restore: spy => () => spy.restore()
204
+ * }
205
+ * });
206
+ * ```
207
+ */
208
+ spy ?: RouterMockSpyOptions
158
209
}
159
210
160
211
/**
@@ -188,7 +239,10 @@ export function createRouterMock(options: RouterMockOptions = {}): RouterMock {
188
239
189
240
const { push, addRoute, replace, beforeEach, beforeResolve } = router
190
241
191
- const [ addRouteMock , addRouteMockClear ] = createSpy (
242
+ const createSpy = options . spy ?. create ?? createSpyAuto
243
+ const restoreSpy = options . spy ?. restore ?? restoreSpyAuto
244
+
245
+ const addRouteMock = createSpy (
192
246
(
193
247
parentRecordName : Required < RouteRecordRaw > [ 'name' ] | RouteRecordRaw ,
194
248
record ?: RouteRecordRaw
@@ -206,14 +260,20 @@ export function createRouterMock(options: RouterMockOptions = {}): RouterMock {
206
260
}
207
261
)
208
262
209
- const [ pushMock , pushMockClear ] = createSpy ( ( to : RouteLocationRaw ) => {
263
+ const addRouteMockClear = restoreSpy ( addRouteMock )
264
+
265
+ const pushMock = createSpy ( ( to : RouteLocationRaw ) => {
210
266
return consumeNextReturn ( to )
211
267
} )
212
268
213
- const [ replaceMock , replaceMockClear ] = createSpy ( ( to : RouteLocationRaw ) => {
269
+ const pushMockClear = restoreSpy ( pushMock )
270
+
271
+ const replaceMock = createSpy ( ( to : RouteLocationRaw ) => {
214
272
return consumeNextReturn ( to , { replace : true } )
215
273
} )
216
274
275
+ const replaceMockClear = restoreSpy ( replaceMock )
276
+
217
277
router . push = pushMock
218
278
router . replace = replaceMock
219
279
router . addRoute = addRouteMock
0 commit comments