Files
stack/v1/packages/mosaic/framework/skills/vitest/references/advanced-vi.md
T

4.5 KiB

name, description
name description
vi-utilities vi helper for mocking, timers, utilities

Vi Utilities

The vi helper provides mocking and utility functions.

import { vi } from 'vitest';

Mock Functions

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

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

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

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

// Clear module cache
vi.resetModules();

// Wait for dynamic imports
await vi.dynamicImportSettled();

Fake Timers

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

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

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

const mock = vi.hoisted(() => vi.fn());

vi.mock('./module', () => ({
  fn: mock, // Can reference hoisted variable
}));

Waiting Utilities

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

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

vi.setConfig({
  testTimeout: 10_000,
  hookTimeout: 10_000,
});

vi.resetConfig();

Global Mock Management

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:

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