--- 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