Vitest unit and integration testing patterns, commands, mocking (vi.mock), and coverage. Use when writing .test.ts files, configuring the test runner, or adding coverage thresholds.
100
100%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
For project-specific test configuration, see testing-config.md.
npx vitest # Run in watch mode
npx vitest run # Run once (CI)
npx vitest run --coverage # Run with coverage report
npx vitest run src/utils/ # Run specific directory
npx vitest run auth.test.ts # Run specific file
npx vitest run -t "should validate" # Filter by test name
npx vitest --ui # Open Vitest UI
npx vitest --reporter=json # JSON output for CI
npx vitest typecheck # Run type-checking testssrc/
├── utils/
│ ├── format.ts
│ └── format.test.ts # Co-located test
├── components/
│ ├── Button.tsx
│ └── Button.test.tsx # Component test
└── __tests__/ # Integration tests
└── auth-flow.test.tsimport { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { formatPrice } from './format';
describe('formatPrice', () => {
it('should format USD prices', () => {
expect(formatPrice(9.99, 'USD')).toBe('$9.99');
});
it('should handle zero', () => {
expect(formatPrice(0, 'USD')).toBe('$0.00');
});
it('should throw for negative values', () => {
expect(() => formatPrice(-1, 'USD')).toThrow('Price cannot be negative');
});
});import { vi, describe, it, expect } from 'vitest';
// Mock entire module
vi.mock('./database', () => ({
getUser: vi.fn().mockResolvedValue({ id: '1', name: 'Alice' }),
}));
// Mock specific export
vi.mock('./config', async (importOriginal) => {
const original = await importOriginal<typeof import('./config')>();
return { ...original, API_URL: 'http://test-api.example.com' };
});import { vi, describe, it, expect } from 'vitest';
describe('notifications', () => {
it('should call the API', async () => {
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
new Response(JSON.stringify({ ok: true }))
);
await sendNotification('Hello');
expect(fetchSpy).toHaveBeenCalledWith('/api/notify', expect.objectContaining({
method: 'POST',
}));
fetchSpy.mockRestore();
});
});import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
describe('debounce', () => {
beforeEach(() => vi.useFakeTimers());
afterEach(() => vi.useRealTimers());
it('should debounce calls', () => {
const fn = vi.fn();
const debounced = debounce(fn, 300);
debounced();
debounced();
debounced();
expect(fn).not.toHaveBeenCalled();
vi.advanceTimersByTime(300);
expect(fn).toHaveBeenCalledOnce();
});
});import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true, // Use describe/it/expect without imports
environment: 'jsdom', // 'node' | 'jsdom' | 'happy-dom'
include: ['src/**/*.test.{ts,tsx}'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
include: ['src/**/*.{ts,tsx}'],
exclude: ['src/**/*.test.{ts,tsx}', 'src/**/*.d.ts'],
thresholds: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
setupFiles: ['./src/test-setup.ts'],
},
});*.test.ts adjacent to the source file.vi.mock() before imports; restore in afterEach with vi.restoreAllMocks().npx vitest run <file> — fix failures.npx vitest run <file> --reporter=verbose to inspect, fix, re-run.npx vitest run --coverage --reporter=json (CI) or npx vitest run --coverage --reporter=text (local) to generate coverage reports. Inspect coverage/coverage-final.json or the human-readable summary to find uncovered files/branches. If coverage is below thresholds, add targeted tests for uncovered branches, then re-run npx vitest run --coverage until thresholds pass.f5c8508
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.