--- name: vi-utilities description: vi helper for mocking, timers, utilities --- # Vi Utilities The `vi` helper provides mocking and utility functions. ```ts import { vi } from 'vitest' ``` ## Mock Functions ```ts // Create mock const fn = vi.fn() const fnWithImpl = vi.fn((x) => x * 2) // Check if mock vi.isMockFunction(fn) // true // Mock methods fn.mockReturnValue(42) fn.mockReturnValueOnce(1) fn.mockResolvedValue(data) fn.mockRejectedValue(error) fn.mockImplementation(() => 'result') fn.mockImplementationOnce(() => 'once') // Clear/reset fn.mockClear() // Clear call history fn.mockReset() // Clear history + implementation fn.mockRestore() // Restore original (for spies) ``` ## Spying ```ts const obj = { method: () => 'original' } const spy = vi.spyOn(obj, 'method') obj.method() expect(spy).toHaveBeenCalled() // Mock implementation spy.mockReturnValue('mocked') // Spy on getter/setter vi.spyOn(obj, 'prop', 'get').mockReturnValue('value') ``` ## Module Mocking ```ts // Hoisted to top of file vi.mock('./module', () => ({ fn: vi.fn(), })) // Partial mock vi.mock('./module', async (importOriginal) => ({ ...(await importOriginal()), specificFn: vi.fn(), })) // Spy mode - keep implementation vi.mock('./module', { spy: true }) // Import actual module inside mock const actual = await vi.importActual('./module') // Import as mock const mocked = await vi.importMock('./module') ``` ## Dynamic Mocking ```ts // Not hoisted - use with dynamic imports vi.doMock('./config', () => ({ key: 'value' })) const config = await import('./config') // Unmock vi.doUnmock('./config') vi.unmock('./module') // Hoisted ``` ## Reset Modules ```ts // Clear module cache vi.resetModules() // Wait for dynamic imports await vi.dynamicImportSettled() ``` ## Fake Timers ```ts vi.useFakeTimers() setTimeout(() => console.log('done'), 1000) // Advance time vi.advanceTimersByTime(1000) vi.advanceTimersByTimeAsync(1000) // For async callbacks vi.advanceTimersToNextTimer() vi.advanceTimersToNextFrame() // requestAnimationFrame // Run all timers vi.runAllTimers() vi.runAllTimersAsync() vi.runOnlyPendingTimers() // Clear timers vi.clearAllTimers() // Check state vi.getTimerCount() vi.isFakeTimers() // Restore vi.useRealTimers() ``` ## Mock Date/Time ```ts vi.setSystemTime(new Date('2024-01-01')) expect(new Date().getFullYear()).toBe(2024) vi.getMockedSystemTime() // Get mocked date vi.getRealSystemTime() // Get real time (ms) ``` ## Global/Env Mocking ```ts // Stub global vi.stubGlobal('fetch', vi.fn()) vi.unstubAllGlobals() // Stub environment vi.stubEnv('API_KEY', 'test') vi.stubEnv('NODE_ENV', 'test') vi.unstubAllEnvs() ``` ## Hoisted Code Run code before imports: ```ts const mock = vi.hoisted(() => vi.fn()) vi.mock('./module', () => ({ fn: mock, // Can reference hoisted variable })) ``` ## Waiting Utilities ```ts // Wait for callback to succeed await vi.waitFor(async () => { const el = document.querySelector('.loaded') expect(el).toBeTruthy() }, { timeout: 5000, interval: 100 }) // Wait for truthy value const element = await vi.waitUntil( () => document.querySelector('.loaded'), { timeout: 5000 } ) ``` ## Mock Object Mock all methods of an object: ```ts const original = { method: () => 'real', nested: { fn: () => 'nested' }, } const mocked = vi.mockObject(original) mocked.method() // undefined (mocked) mocked.method.mockReturnValue('mocked') // Spy mode const spied = vi.mockObject(original, { spy: true }) spied.method() // 'real' expect(spied.method).toHaveBeenCalled() ``` ## Test Configuration ```ts vi.setConfig({ testTimeout: 10_000, hookTimeout: 10_000, }) vi.resetConfig() ``` ## Global Mock Management ```ts vi.clearAllMocks() // Clear all mock call history vi.resetAllMocks() // Reset + clear implementation vi.restoreAllMocks() // Restore originals (spies) ``` ## vi.mocked Type Helper TypeScript helper for mocked values: ```ts import { myFn } from './module' vi.mock('./module') // Type as mock vi.mocked(myFn).mockReturnValue('typed') // Deep mocking vi.mocked(myModule, { deep: true }) // Partial mock typing vi.mocked(fn, { partial: true }).mockResolvedValue({ ok: true }) ``` ## Key Points - `vi.mock` is hoisted - use `vi.doMock` for dynamic mocking - `vi.hoisted` lets you reference variables in mock factories - Use `vi.spyOn` to spy on existing methods - Fake timers require explicit setup and teardown - `vi.waitFor` retries until assertion passes