[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix!(spy): simplify mock function generic types and align with jest (#4784)

authored by

Hiroshi Ogawa and committed by
GitHub
(Jun 23, 2024, 6:09 PM +0200) a0c1d371 70805131

+160 -129
+20 -4
docs/guide/migration.md
··· 78 78 79 79 This change also removes the file from `expect.getState().currentTestName` and makes `expect.getState().testPath` required. 80 80 81 + ### Simplified generic types of mock functions (e.g. `vi.fn<T>`, `Mock<T>`) 82 + 83 + Previously `vi.fn<TArgs, TReturn>` accepted two generic types separately for arguemnts and return value. This is changed to directly accept a function type `vi.fn<T>` to simplify the usage. 84 + 85 + ```ts 86 + import { type Mock, vi } from 'vitest' 87 + 88 + const add = (x: number, y: number): number => x + y 89 + 90 + // using vi.fn<T> 91 + const mockAdd = vi.fn<Parameters<typeof add>, ReturnType<typeof add>>() // [!code --] 92 + const mockAdd = vi.fn<typeof add>() // [!code ++] 93 + 94 + // using Mock<T> 95 + const mockAdd: Mock<Parameters<typeof add>, ReturnType<typeof add>> = vi.fn() // [!code --] 96 + const mockAdd: Mock<typeof add> = vi.fn() // [!code ++] 97 + ``` 98 + 81 99 ## Migrating to Vitest 1.0 82 100 83 101 <!-- introduction --> ··· 324 342 Vitest doesn't have an equivalent to `jest` namespace, so you will need to import types directly from `vitest`: 325 343 326 344 ```ts 327 - let fn: jest.Mock<string, [string]> // [!code --] 345 + let fn: jest.Mock<(name: string) => number> // [!code --] 328 346 import type { Mock } from 'vitest' // [!code ++] 329 - let fn: Mock<[string], string> // [!code ++] 347 + let fn: Mock<(name: string) => number> // [!code ++] 330 348 ``` 331 - 332 - Also, Vitest has `Args` type as a first argument instead of `Returns`, as you can see in diff. 333 349 334 350 ### Timers 335 351
+92 -111
packages/spy/src/index.ts
··· 38 38 | MockSettledResultFulfilled<T> 39 39 | MockSettledResultRejected 40 40 41 - export interface MockContext<TArgs, TReturns> { 41 + export interface MockContext<T extends Procedure> { 42 42 /** 43 43 * This is an array containing all arguments for each call. One item of the array is the arguments of that call. 44 44 * ··· 53 53 * ['arg3'], // second call 54 54 * ] 55 55 */ 56 - calls: TArgs[] 56 + calls: Parameters<T>[] 57 57 /** 58 58 * 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. 59 59 */ 60 - instances: TReturns[] 60 + instances: ReturnType<T>[] 61 61 /** 62 62 * The order of mock's execution. This returns an array of numbers which are shared between all defined mocks. 63 63 * ··· 101 101 * }, 102 102 * ] 103 103 */ 104 - results: MockResult<TReturns>[] 104 + results: MockResult<ReturnType<T>>[] 105 105 /** 106 106 * An array containing all values that were `resolved` or `rejected` from the function. 107 107 * ··· 129 129 * }, 130 130 * ] 131 131 */ 132 - settledResults: MockSettledResult<Awaited<TReturns>>[] 132 + settledResults: MockSettledResult<Awaited<ReturnType<T>>>[] 133 133 /** 134 134 * This contains the arguments of the last call. If spy wasn't called, will return `undefined`. 135 135 */ 136 - lastCall: TArgs | undefined 136 + lastCall: Parameters<T> | undefined 137 137 } 138 138 139 139 type Procedure = (...args: any[]) => any ··· 150 150 }[keyof T] & 151 151 (string | symbol) 152 152 153 - /** 154 - * @deprecated Use MockInstance<A, R> instead 155 - */ 156 - export interface SpyInstance<TArgs extends any[] = any[], TReturns = any> 157 - extends MockInstance<TArgs, TReturns> {} 153 + /* 154 + cf. https://typescript-eslint.io/rules/method-signature-style/ 158 155 159 - export interface MockInstance<TArgs extends any[] = any[], TReturns = any> { 156 + Typescript assignability is different between 157 + { foo: (f: T) => U } (this is "method-signature-style") 158 + and 159 + { foo(f: T): U } 160 + 161 + Jest uses the latter for `MockInstance.mockImplementation` etc... and it allows assignment such as: 162 + const boolFn: Jest.Mock<() => boolean> = jest.fn<() => true>(() => true) 163 + */ 164 + /* eslint-disable ts/method-signature-style */ 165 + export interface MockInstance<T extends Procedure = Procedure> { 160 166 /** 161 167 * Use it to return the name given to mock with method `.mockName(name)`. 162 168 */ 163 - getMockName: () => string 169 + getMockName(): string 164 170 /** 165 171 * Sets internal mock name. Useful to see the name of the mock if an assertion fails. 166 172 */ 167 - mockName: (n: string) => this 173 + mockName(n: string): this 168 174 /** 169 175 * Current context of the mock. It stores information about all invocation calls, instances, and results. 170 176 */ 171 - mock: MockContext<TArgs, TReturns> 177 + mock: MockContext<T> 172 178 /** 173 179 * Clears all information about every call. After calling it, all properties on `.mock` will return an empty state. This method does not reset implementations. 174 180 * 175 181 * It is useful if you need to clean up mock between different assertions. 176 182 */ 177 - mockClear: () => this 183 + mockClear(): this 178 184 /** 179 185 * Does what `mockClear` does and makes inner implementation an empty function (returning `undefined` when invoked). This also resets all "once" implementations. 180 186 * 181 187 * This is useful when you want to completely reset a mock to the default state. 182 188 */ 183 - mockReset: () => this 189 + mockReset(): this 184 190 /** 185 191 * Does what `mockReset` does and restores inner implementation to the original function. 186 192 * 187 193 * 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`. 188 194 */ 189 - mockRestore: () => void 195 + mockRestore(): void 190 196 /** 191 197 * Returns current mock implementation if there is one. 192 198 * ··· 194 200 * 195 201 * If mock was created with `vi.spyOn`, it will return `undefined` unless a custom implementation was provided. 196 202 */ 197 - getMockImplementation: () => ((...args: TArgs) => TReturns) | undefined 203 + getMockImplementation(): T | undefined 198 204 /** 199 205 * Accepts a function that will be used as an implementation of the mock. 200 206 * @example 201 207 * const increment = vi.fn().mockImplementation(count => count + 1); 202 208 * expect(increment(3)).toBe(4); 203 209 */ 204 - mockImplementation: (fn: (...args: TArgs) => TReturns) => this 210 + mockImplementation(fn: T): this 205 211 /** 206 212 * 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. 207 213 * @example ··· 209 215 * expect(fn(3)).toBe(4); 210 216 * expect(fn(3)).toBe(3); 211 217 */ 212 - mockImplementationOnce: (fn: (...args: TArgs) => TReturns) => this 218 + mockImplementationOnce(fn: T): this 213 219 /** 214 220 * Overrides the original mock implementation temporarily while the callback is being executed. 215 221 * @example ··· 221 227 * 222 228 * myMockFn() // 'original' 223 229 */ 224 - withImplementation: <T>( 225 - fn: (...args: TArgs) => TReturns, 226 - cb: () => T 227 - ) => T extends Promise<unknown> ? Promise<this> : this 230 + withImplementation<T2>(fn: T, cb: () => T2): T2 extends Promise<unknown> ? Promise<this> : this 231 + 228 232 /** 229 233 * Use this if you need to return `this` context from the method without invoking actual implementation. 230 234 */ 231 - mockReturnThis: () => this 235 + mockReturnThis(): this 232 236 /** 233 237 * Accepts a value that will be returned whenever the mock function is called. 234 238 */ 235 - mockReturnValue: (obj: TReturns) => this 239 + mockReturnValue(obj: ReturnType<T>): this 236 240 /** 237 241 * Accepts a value that will be returned during the next function call. If chained, every consecutive call will return the specified value. 238 242 * ··· 247 251 * // 'first call', 'second call', 'default' 248 252 * console.log(myMockFn(), myMockFn(), myMockFn()) 249 253 */ 250 - mockReturnValueOnce: (obj: TReturns) => this 254 + mockReturnValueOnce(obj: ReturnType<T>): this 251 255 /** 252 256 * Accepts a value that will be resolved when async function is called. 253 257 * @example 254 258 * const asyncMock = vi.fn().mockResolvedValue(42) 255 259 * asyncMock() // Promise<42> 256 260 */ 257 - mockResolvedValue: (obj: Awaited<TReturns>) => this 261 + mockResolvedValue(obj: Awaited<ReturnType<T>>): this 258 262 /** 259 263 * Accepts a value that will be resolved during the next function call. If chained, every consecutive call will resolve specified value. 260 264 * @example ··· 267 271 * // Promise<'first call'>, Promise<'second call'>, Promise<'default'> 268 272 * console.log(myMockFn(), myMockFn(), myMockFn()) 269 273 */ 270 - mockResolvedValueOnce: (obj: Awaited<TReturns>) => this 274 + mockResolvedValueOnce(obj: Awaited<ReturnType<T>>): this 271 275 /** 272 276 * Accepts an error that will be rejected when async function is called. 273 277 * @example 274 278 * const asyncMock = vi.fn().mockRejectedValue(new Error('Async error')) 275 279 * await asyncMock() // throws 'Async error' 276 280 */ 277 - mockRejectedValue: (obj: any) => this 281 + mockRejectedValue(obj: any): this 278 282 /** 279 283 * Accepts a value that will be rejected during the next function call. If chained, every consecutive call will reject specified value. 280 284 * @example ··· 286 290 * await asyncMock() // first call 287 291 * await asyncMock() // throws "Async error" 288 292 */ 289 - mockRejectedValueOnce: (obj: any) => this 293 + mockRejectedValueOnce(obj: any): this 294 + } 295 + /* eslint-enable ts/method-signature-style */ 296 + 297 + export interface Mock<T extends Procedure = Procedure> 298 + extends MockInstance<T> { 299 + new (...args: Parameters<T>): ReturnType<T> 300 + (...args: Parameters<T>): ReturnType<T> 290 301 } 291 302 292 - export interface Mock<TArgs extends any[] = any, TReturns = any> 293 - extends MockInstance<TArgs, TReturns> { 294 - new (...args: TArgs): TReturns 295 - (...args: TArgs): TReturns 296 - } 297 - export interface PartialMock<TArgs extends any[] = any, TReturns = any> 303 + type PartialMaybePromise<T> = T extends Promise<Awaited<T>> 304 + ? Promise<Partial<Awaited<T>>> 305 + : Partial<T> 306 + 307 + export interface PartialMock<T extends Procedure = Procedure> 298 308 extends MockInstance< 299 - TArgs, 300 - TReturns extends Promise<Awaited<TReturns>> 301 - ? Promise<Partial<Awaited<TReturns>>> 302 - : Partial<TReturns> 309 + (...args: Parameters<T>) => PartialMaybePromise<ReturnType<T>> 303 310 > { 304 - new (...args: TArgs): TReturns 305 - (...args: TArgs): TReturns 311 + new (...args: Parameters<T>): ReturnType<T> 312 + (...args: Parameters<T>): ReturnType<T> 306 313 } 307 314 308 315 export type MaybeMockedConstructor<T> = T extends new ( 309 316 ...args: Array<any> 310 317 ) => infer R 311 - ? Mock<ConstructorParameters<T>, R> 318 + ? Mock<(...args: ConstructorParameters<T>) => R> 312 319 : T 313 - export type MockedFunction<T extends Procedure> = Mock< 314 - Parameters<T>, 315 - ReturnType<T> 316 - > & { 320 + export type MockedFunction<T extends Procedure> = Mock<T> & { 317 321 [K in keyof T]: T[K]; 318 322 } 319 - export type PartiallyMockedFunction<T extends Procedure> = PartialMock< 320 - Parameters<T>, 321 - ReturnType<T> 322 - > & { 323 + export type PartiallyMockedFunction<T extends Procedure> = PartialMock<T> & { 323 324 [K in keyof T]: T[K]; 324 325 } 325 - export type MockedFunctionDeep<T extends Procedure> = Mock< 326 - Parameters<T>, 327 - ReturnType<T> 328 - > & 329 - MockedObjectDeep<T> 330 - export type PartiallyMockedFunctionDeep<T extends Procedure> = PartialMock< 331 - Parameters<T>, 332 - ReturnType<T> 333 - > & 334 - MockedObjectDeep<T> 326 + export type MockedFunctionDeep<T extends Procedure> = Mock<T> & 327 + MockedObjectDeep<T> 328 + export type PartiallyMockedFunctionDeep<T extends Procedure> = PartialMock<T> & 329 + MockedObjectDeep<T> 335 330 export type MockedObject<T> = MaybeMockedConstructor<T> & { 336 331 [K in Methods<T>]: T[K] extends Procedure ? MockedFunction<T[K]> : T[K]; 337 332 } & { [K in Properties<T>]: T[K] } ··· 368 363 } 369 364 370 365 export type MockedClass<T extends Constructable> = MockInstance< 371 - T extends new (...args: infer P) => any ? P : never, 372 - InstanceType<T> 366 + (...args: ConstructorParameters<T>) => InstanceType<T> 373 367 > & { 374 368 prototype: T extends { prototype: any } ? Mocked<T['prototype']> : never 375 369 } & T 376 370 377 371 export type Mocked<T> = { 378 - [P in keyof T]: T[P] extends (...args: infer Args) => infer Returns 379 - ? MockInstance<Args, Returns> 372 + [P in keyof T]: T[P] extends Procedure 373 + ? MockInstance<T[P]> 380 374 : T[P] extends Constructable 381 375 ? MockedClass<T[P]> 382 376 : T[P]; ··· 394 388 obj: T, 395 389 methodName: S, 396 390 accessType: 'get' 397 - ): MockInstance<[], T[S]> 391 + ): MockInstance<() => T[S]> 398 392 export function spyOn<T, G extends Properties<Required<T>>>( 399 393 obj: T, 400 394 methodName: G, 401 395 accessType: 'set' 402 - ): MockInstance<[T[G]], void> 396 + ): MockInstance<(arg: T[G]) => void> 403 397 export function spyOn<T, M extends Classes<Required<T>> | Methods<Required<T>>>( 404 398 obj: T, 405 399 methodName: M 406 400 ): Required<T>[M] extends 407 401 | { new (...args: infer A): infer R } 408 402 | ((...args: infer A) => infer R) 409 - ? MockInstance<A, R> 403 + ? MockInstance<(...args: A) => R> 410 404 : never 411 405 export function spyOn<T, K extends keyof T>( 412 406 obj: T, ··· 426 420 427 421 let callOrder = 0 428 422 429 - function enhanceSpy<TArgs extends any[], TReturns>( 430 - spy: SpyInternalImpl<TArgs, TReturns>, 431 - ): MockInstance<TArgs, TReturns> { 432 - const stub = spy as unknown as MockInstance<TArgs, TReturns> 423 + function enhanceSpy<T extends Procedure>( 424 + spy: SpyInternalImpl<Parameters<T>, ReturnType<T>>, 425 + ): MockInstance<T> { 426 + type TArgs = Parameters<T> 427 + type TReturns = ReturnType<T> 433 428 434 - let implementation: ((...args: TArgs) => TReturns) | undefined 429 + const stub = spy as unknown as MockInstance<T> 430 + 431 + let implementation: T | undefined 435 432 436 433 let instances: any[] = [] 437 434 let invocations: number[] = [] 438 435 439 436 const state = tinyspy.getInternalState(spy) 440 437 441 - const mockContext: MockContext<TArgs, TReturns> = { 438 + const mockContext: MockContext<T> = { 442 439 get calls() { 443 440 return state.calls 444 441 }, ··· 499 496 500 497 stub.mockReset = () => { 501 498 stub.mockClear() 502 - implementation = () => undefined as unknown as TReturns 499 + implementation = (() => undefined) as T 503 500 onceImplementations = [] 504 501 return stub 505 502 } ··· 512 509 } 513 510 514 511 stub.getMockImplementation = () => implementation 515 - stub.mockImplementation = (fn: (...args: TArgs) => TReturns) => { 512 + stub.mockImplementation = (fn: T) => { 516 513 implementation = fn 517 514 state.willCall(mockCall) 518 515 return stub 519 516 } 520 517 521 - stub.mockImplementationOnce = (fn: (...args: TArgs) => TReturns) => { 518 + stub.mockImplementationOnce = (fn: T) => { 522 519 onceImplementations.push(fn) 523 520 return stub 524 521 } 525 522 526 - function withImplementation( 527 - fn: (...args: TArgs) => TReturns, 528 - cb: () => void 529 - ): MockInstance<TArgs, TReturns> 530 - function withImplementation( 531 - fn: (...args: TArgs) => TReturns, 532 - cb: () => Promise<void> 533 - ): Promise<MockInstance<TArgs, TReturns>> 534 - function withImplementation( 535 - fn: (...args: TArgs) => TReturns, 536 - cb: () => void | Promise<void>, 537 - ): MockInstance<TArgs, TReturns> | Promise<MockInstance<TArgs, TReturns>> { 523 + function withImplementation(fn: T, cb: () => void): MockInstance<T> 524 + function withImplementation(fn: T, cb: () => Promise<void>): Promise<MockInstance<T>> 525 + function withImplementation(fn: T, cb: () => void | Promise<void>): MockInstance<T> | Promise<MockInstance<T>> { 538 526 const originalImplementation = implementation 539 527 540 528 implementation = fn ··· 563 551 stub.withImplementation = withImplementation 564 552 565 553 stub.mockReturnThis = () => 566 - stub.mockImplementation(function (this: TReturns) { 554 + stub.mockImplementation((function (this: TReturns) { 567 555 return this 568 - }) 556 + }) as any) 569 557 570 - stub.mockReturnValue = (val: TReturns) => stub.mockImplementation(() => val) 571 - stub.mockReturnValueOnce = (val: TReturns) => 572 - stub.mockImplementationOnce(() => val) 558 + stub.mockReturnValue = (val: TReturns) => stub.mockImplementation((() => val) as any) 559 + stub.mockReturnValueOnce = (val: TReturns) => stub.mockImplementationOnce((() => val) as any) 573 560 574 561 stub.mockResolvedValue = (val: Awaited<TReturns>) => 575 - stub.mockImplementation(() => Promise.resolve(val as TReturns) as any) 562 + stub.mockImplementation((() => Promise.resolve(val as TReturns)) as any) 576 563 577 564 stub.mockResolvedValueOnce = (val: Awaited<TReturns>) => 578 - stub.mockImplementationOnce(() => Promise.resolve(val as TReturns) as any) 565 + stub.mockImplementationOnce((() => Promise.resolve(val as TReturns)) as any) 579 566 580 567 stub.mockRejectedValue = (val: unknown) => 581 - stub.mockImplementation(() => Promise.reject(val) as any) 568 + stub.mockImplementation((() => Promise.reject(val)) as any) 582 569 583 570 stub.mockRejectedValueOnce = (val: unknown) => 584 - stub.mockImplementationOnce(() => Promise.reject(val) as any) 571 + stub.mockImplementationOnce((() => Promise.reject(val)) as any) 585 572 586 573 Object.defineProperty(stub, 'mock', { 587 574 get: () => mockContext, ··· 594 581 return stub as any 595 582 } 596 583 597 - export function fn<TArgs extends any[] = any, R = any>(): Mock<TArgs, R> 598 - export function fn<TArgs extends any[] = any[], R = any>( 599 - implementation: (...args: TArgs) => R 600 - ): Mock<TArgs, R> 601 - export function fn<TArgs extends any[] = any[], R = any>( 602 - implementation?: (...args: TArgs) => R, 603 - ): Mock<TArgs, R> { 604 - const enhancedSpy = enhanceSpy( 605 - tinyspy.internalSpyOn({ spy: implementation || (() => {}) }, 'spy'), 606 - ) 584 + export function fn<T extends Procedure = Procedure>( 585 + implementation?: T, 586 + ): Mock<T> { 587 + const enhancedSpy = enhanceSpy(tinyspy.internalSpyOn({ spy: implementation || (() => {}) }, 'spy')) 607 588 if (implementation) { 608 589 enhancedSpy.mockImplementation(implementation) 609 590 } 610 591 611 - return enhancedSpy as Mock 592 + return enhancedSpy as any 612 593 }
+2 -2
test/core/test/mock-internals.test.ts
··· 1 1 import childProcess, { exec } from 'node:child_process' 2 2 import timers from 'node:timers' 3 - import { type SpyInstance, afterEach, beforeEach, describe, expect, test, vi } from 'vitest' 3 + import { type MockInstance, afterEach, beforeEach, describe, expect, test, vi } from 'vitest' 4 4 import { execDefault, execHelloWorld, execImportAll } from '../src/exec' 5 5 import { dynamicImport } from '../src/dynamic-import' 6 6 ··· 31 31 32 32 describe('Math.random', () => { 33 33 describe('mock is restored', () => { 34 - let spy: SpyInstance 34 + let spy: MockInstance 35 35 36 36 beforeEach(() => { 37 37 spy = vi.spyOn(Math, 'random').mockReturnValue(0.1)
+45 -10
test/core/test/vi.spec.ts
··· 2 2 * @vitest-environment jsdom 3 3 */ 4 4 5 - import type { MockedFunction, MockedObject } from 'vitest' 6 - import { describe, expect, test, vi } from 'vitest' 5 + import type { Mock, MockedFunction, MockedObject } from 'vitest' 6 + import { describe, expect, expectTypeOf, test, vi } from 'vitest' 7 7 import { getWorkerState } from '../../../packages/vitest/src/utils' 8 8 9 9 function expectType<T>(obj: T) { ··· 41 41 }) 42 42 expectType<MockedFunction<() => boolean>>(vi.fn(() => true)) 43 43 expectType<MockedFunction<() => boolean>>(vi.fn()) 44 + 45 + expectType<MockedFunction<() => boolean>>(vi.fn<() => boolean>(() => true)) 46 + expectType<Mock<() => boolean>>(vi.fn<() => boolean>(() => true)) 47 + expectType<() => boolean>(vi.fn(() => true)) 48 + 49 + expectType<(v: number) => boolean>(vi.fn()) 44 50 }) 45 51 46 52 test('vi partial mocked', () => { ··· 50 56 baz: string 51 57 } 52 58 53 - type FooBarFactory = () => FooBar 54 - 55 - const mockFactory: FooBarFactory = vi.fn() 59 + const mockFactory = vi.fn<() => FooBar>() 56 60 57 61 vi.mocked(mockFactory, { partial: true }).mockReturnValue({ 58 62 foo: vi.fn(), 59 63 }) 60 64 61 65 vi.mocked(mockFactory, { partial: true, deep: false }).mockReturnValue({ 62 - bar: vi.fn(), 66 + bar: vi.fn<FooBar['bar']>(), 63 67 }) 64 68 65 69 vi.mocked(mockFactory, { partial: true, deep: true }).mockReturnValue({ 66 70 baz: 'baz', 67 71 }) 68 72 69 - type FooBarAsyncFactory = () => Promise<FooBar> 70 - 71 - const mockFactoryAsync: FooBarAsyncFactory = vi.fn() 73 + const mockFactoryAsync = vi.fn<() => Promise<FooBar>>() 72 74 73 75 vi.mocked(mockFactoryAsync, { partial: true }).mockResolvedValue({ 74 76 foo: vi.fn(), 75 77 }) 76 78 77 79 vi.mocked(mockFactoryAsync, { partial: true, deep: false }).mockResolvedValue({ 78 - bar: vi.fn(), 80 + bar: vi.fn<FooBar['bar']>(), 79 81 }) 80 82 81 83 vi.mocked(mockFactoryAsync, { partial: true, deep: true }).mockResolvedValue({ 82 84 baz: 'baz', 83 85 }) 86 + }) 87 + 88 + test('vi.fn and Mock type', () => { 89 + // use case from https://github.com/vitest-dev/vitest/issues/4723#issuecomment-1851034249 90 + 91 + // hypotetical library to be tested 92 + type SomeFn = (v: string) => number 93 + function acceptSomeFn(f: SomeFn) { 94 + f('hi') 95 + } 96 + 97 + // SETUP 98 + // no args are allowed even though it's not type safe 99 + const someFn1: Mock<SomeFn> = vi.fn() 100 + 101 + // argument types are infered 102 + const someFn2: Mock<SomeFn> = vi.fn((v) => { 103 + expectTypeOf(v).toEqualTypeOf<string>() 104 + return 0 105 + }) 106 + 107 + // arguments are not necessary 108 + const someFn3: Mock<SomeFn> = vi.fn(() => 0) 109 + 110 + // @ts-expect-error wrong return type will be caught 111 + const someFn4: Mock<SomeFn> = vi.fn(() => '0') 112 + 113 + // TEST 114 + acceptSomeFn(someFn1) 115 + expect(someFn1).toBeCalledWith('hi') 116 + expect(someFn2).not.toBeCalled() 117 + expect(someFn3).not.toBeCalled() 118 + expect(someFn4).not.toBeCalled() 84 119 }) 85 120 86 121 test('can change config', () => {
-1
packages/vitest/src/types/index.ts
··· 18 18 export type { 19 19 MockedFunction, 20 20 MockedObject, 21 - SpyInstance, 22 21 MockInstance, 23 22 Mock, 24 23 MockContext,
+1 -1
packages/vitest/src/integrations/chai/chai-subset.d.ts
··· 1 1 declare module 'chai-subset' { 2 2 const chaiSubset: Chai.ChaiPlugin 3 - // eslint-disable-next-line no-restricted-syntax 3 + 4 4 export = chaiSubset 5 5 }