Vitest setup and best practices. Use when configuring Vitest for TypeScript projects.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill covers Vitest configuration for TypeScript projects.
Use this skill when:
FAST, NATIVE ESM TESTING - Vitest provides Jest-compatible API with native ESM support and Vite-powered performance.
npm install -D vitest @vitest/coverage-v8
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: ['src/**/__tests__/**/*.test.{ts,tsx}'],
exclude: ['node_modules', 'dist'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/',
'dist/',
'**/*.test.ts',
'**/__tests__/**',
'**/*.d.ts',
],
thresholds: {
lines: 80,
functions: 80,
branches: 80,
statements: 80,
},
},
typecheck: {
enabled: true,
tsconfig: './tsconfig.json',
},
},
});
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"test:ui": "vitest --ui"
}
}
export default defineConfig({
test: {
environment: 'node',
},
});
npm install -D jsdom
export default defineConfig({
test: {
environment: 'jsdom',
},
});
npm install -D happy-dom
export default defineConfig({
test: {
environment: 'happy-dom',
},
});
// In test file header
// @vitest-environment jsdom
import { describe, it, expect } from 'vitest';
// vitest.config.ts
export default defineConfig({
test: {
setupFiles: ['./src/test/setup.ts'],
globalSetup: ['./src/test/global-setup.ts'],
},
});
// src/test/setup.ts
import { beforeAll, afterAll, afterEach } from 'vitest';
beforeAll(() => {
// Runs once before all tests
});
afterEach(() => {
// Runs after each test
});
afterAll(() => {
// Runs once after all tests
});
// src/test/global-setup.ts
export default async function setup() {
// Global setup (runs before all test files)
console.log('Starting test suite');
}
export async function teardown() {
// Global teardown (runs after all test files)
console.log('Test suite complete');
}
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html', 'lcov'],
reportsDirectory: './coverage',
exclude: [
'node_modules/',
'dist/',
'**/*.test.ts',
'**/*.test.tsx',
'**/__tests__/**',
'**/__mocks__/**',
'**/*.d.ts',
'**/types/**',
'**/index.ts', // Re-export files
],
thresholds: {
lines: 80,
functions: 80,
branches: 80,
statements: 80,
},
// Fail if coverage drops
thresholds: {
'100': true, // Enforce 100% on new code
},
},
},
});
export default defineConfig({
test: {
typecheck: {
enabled: true,
tsconfig: './tsconfig.json',
include: ['**/*.test.ts', '**/*.test.tsx'],
},
},
});
{
"compilerOptions": {
"types": ["vitest/globals"]
},
"include": ["src/**/*", "src/**/__tests__/**/*"]
}
import { defineConfig } from 'vitest/config';
import path from 'node:path';
export default defineConfig({
test: {
alias: {
'@': path.resolve(__dirname, './src'),
'@test': path.resolve(__dirname, './src/test'),
},
},
});
export default defineConfig({
test: {
// Run tests in parallel (default)
pool: 'threads',
poolOptions: {
threads: {
singleThread: false,
maxThreads: 4,
minThreads: 1,
},
},
// Or run tests sequentially
// sequence: {
// concurrent: false,
// },
},
});
# Run tests matching pattern
vitest run --grep="user"
# Run specific file
vitest run src/utils/__tests__/format.test.ts
import { describe, it, expect } from 'vitest';
describe('feature', () => {
it.skip('skipped test', () => {
// This test is skipped
});
it.only('only this test runs', () => {
// Only this test runs when using .only
});
it.todo('not yet implemented');
});
import { describe, it, expect } from 'vitest';
describe('snapshots', () => {
it('should match snapshot', () => {
const result = { id: 1, name: 'test' };
expect(result).toMatchSnapshot();
});
it('should match inline snapshot', () => {
const result = { id: 1, name: 'test' };
expect(result).toMatchInlineSnapshot(`
{
"id": 1,
"name": "test",
}
`);
});
});
export default defineConfig({
test: {
snapshotFormat: {
printBasicPrototype: false,
},
},
});
export default defineConfig({
test: {
mockReset: true, // Reset mocks before each test
clearMocks: true, // Clear mock calls before each test
restoreMocks: true, // Restore original implementations
},
});
export default defineConfig({
test: {
deps: {
interopDefault: true,
},
},
});
export default defineConfig({
test: {
reporters: ['default', 'json', 'html'],
outputFile: {
json: './test-results/results.json',
html: './test-results/results.html',
},
},
});
export default defineConfig({
test: {
watch: true,
watchExclude: ['**/node_modules/**', '**/dist/**'],
forceRerunTriggers: ['**/vitest.config.ts', '**/vite.config.ts'],
},
});
export default defineConfig({
test: {
// CI-specific settings
...(process.env.CI
? {
minWorkers: 1,
maxWorkers: 2,
coverage: {
reporter: ['text', 'json', 'lcov'],
},
}
: {}),
},
});
npm install -D @vitest/ui
vitest --ui
Opens interactive UI at http://localhost:51204/__vitest__/
| Jest | Vitest |
|---|---|
testEnvironment | environment |
setupFilesAfterEnv | setupFiles |
testMatch | include |
testPathIgnorePatterns | exclude |
moduleNameMapper | alias |
collectCoverageFrom | coverage.include |
// Jest
import { jest } from '@jest/globals';
// Vitest
import { vi } from 'vitest';
// Jest mock
jest.fn();
jest.mock('./module');
// Vitest mock
vi.fn();
vi.mock('./module');