| name | vitest-configuration |
| description | Use when vitest configuration, Vite integration, workspace setup, and test environment configuration for modern testing. |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
Vitest Configuration
Master Vitest configuration, Vite integration, workspace setup, and test environment configuration for modern testing. This skill covers comprehensive configuration strategies for Vitest, the blazing-fast unit test framework powered by Vite.
Installation and Setup
Basic Installation
npm install -D vitest
# or
yarn add -D vitest
# or
pnpm add -D vitest
Additional Packages
# UI for vitest
npm install -D @vitest/ui
# Browser mode
npm install -D @vitest/browser playwright
# Coverage
npm install -D @vitest/coverage-v8
# or
npm install -D @vitest/coverage-istanbul
Configuration Files
vitest.config.ts (Recommended)
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
// Test environment
environment: 'node', // 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime'
// Global test files
globals: true,
setupFiles: ['./vitest.setup.ts'],
// Include/exclude patterns
include: ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
exclude: ['node_modules', 'dist', '.idea', '.git', '.cache'],
// Coverage configuration
coverage: {
provider: 'v8', // 'v8' | 'istanbul'
reporter: ['text', 'json', 'html'],
include: ['src/**/*.{js,ts,jsx,tsx}'],
exclude: [
'node_modules/',
'src/**/*.test.{js,ts,jsx,tsx}',
'src/**/*.spec.{js,ts,jsx,tsx}',
'src/**/__tests__/**'
],
thresholds: {
lines: 80,
functions: 80,
branches: 80,
statements: 80
}
},
// Performance
pool: 'threads', // 'threads' | 'forks' | 'vmThreads'
poolOptions: {
threads: {
singleThread: false,
minThreads: 1,
maxThreads: 4
}
},
// Timeouts
testTimeout: 10000,
hookTimeout: 10000,
// Watch options
watch: false,
watchExclude: ['**/node_modules/**', '**/dist/**'],
// Reporters
reporters: ['default'],
// Mock options
mockReset: true,
restoreMocks: true,
clearMocks: true
}
});
Extending Vite Config
import { defineConfig, mergeConfig } from 'vitest/config';
import viteConfig from './vite.config';
export default mergeConfig(
viteConfig,
defineConfig({
test: {
// Vitest-specific configuration
}
})
);
Workspace Configuration
// vitest.workspace.ts
import { defineWorkspace } from 'vitest/config';
export default defineWorkspace([
// Multiple projects
{
extends: './vitest.config.ts',
test: {
name: 'unit',
include: ['src/**/*.test.ts'],
environment: 'node'
}
},
{
extends: './vitest.config.ts',
test: {
name: 'browser',
include: ['src/**/*.browser.test.ts'],
environment: 'jsdom'
}
},
{
extends: './vitest.config.ts',
test: {
name: 'integration',
include: ['tests/integration/**/*.test.ts'],
environment: 'node'
}
}
]);
Environment Configuration
Node Environment
// vitest.config.ts
export default defineConfig({
test: {
environment: 'node',
environmentOptions: {
// Node-specific options
}
}
});
JSDOM Environment
// vitest.config.ts
export default defineConfig({
test: {
environment: 'jsdom',
environmentOptions: {
jsdom: {
resources: 'usable',
url: 'http://localhost:3000'
}
}
}
});
Happy DOM Environment
// vitest.config.ts
export default defineConfig({
test: {
environment: 'happy-dom',
environmentOptions: {
happyDOM: {
width: 1024,
height: 768
}
}
}
});
Custom Environment
// custom-environment.ts
import type { Environment } from 'vitest';
export default <Environment>{
name: 'custom',
transformMode: 'ssr',
setup() {
// Setup custom environment
return {
teardown() {
// Cleanup
}
};
}
};
// vitest.config.ts
export default defineConfig({
test: {
environment: './custom-environment.ts'
}
});
Setup Files
vitest.setup.ts
import { expect, afterEach, vi } from 'vitest';
import { cleanup } from '@testing-library/react';
import matchers from '@testing-library/jest-dom/matchers';
// Extend Vitest matchers
expect.extend(matchers);
// Cleanup after each test
afterEach(() => {
cleanup();
});
// Mock global objects
global.fetch = vi.fn();
// Setup global test utilities
global.testUtils = {
// Custom test utilities
};
// Configure test environment
beforeAll(() => {
// Global setup
});
afterAll(() => {
// Global teardown
});
Setup for React Testing
import { expect, afterEach } from 'vitest';
import { cleanup } from '@testing-library/react';
import * as matchers from '@testing-library/jest-dom/matchers';
expect.extend(matchers);
afterEach(() => {
cleanup();
});
// Mock window.matchMedia
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(),
removeListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn()
}))
});
Coverage Configuration
V8 Provider
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html', 'lcov'],
reportsDirectory: './coverage',
include: ['src/**/*.ts'],
exclude: [
'**/*.test.ts',
'**/*.spec.ts',
'**/types/**',
'**/*.d.ts'
],
thresholds: {
lines: 80,
functions: 80,
branches: 80,
statements: 80,
perFile: true
},
all: true,
clean: true,
cleanOnRerun: true
}
}
});
Istanbul Provider
export default defineConfig({
test: {
coverage: {
provider: 'istanbul',
reporter: ['text', 'json', 'html'],
watermarks: {
lines: [80, 95],
functions: [80, 95],
branches: [80, 95],
statements: [80, 95]
}
}
}
});
Module Resolution
Path Aliases
import { defineConfig } from 'vitest/config';
import path from 'path';
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@utils': path.resolve(__dirname, './src/utils'),
'@hooks': path.resolve(__dirname, './src/hooks'),
'@services': path.resolve(__dirname, './src/services')
}
},
test: {
// Test configuration
}
});
External Dependencies
export default defineConfig({
test: {
// Don't externalize these packages
deps: {
inline: ['package-to-inline']
},
// Externalize these packages
server: {
deps: {
external: ['package-to-external']
}
}
}
});
Package.json Scripts
{
"scripts": {
"test": "vitest",
"test:ui": "vitest --ui",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage",
"test:watch": "vitest watch",
"test:ci": "vitest run --coverage --reporter=json --reporter=default"
}
}
Advanced Configuration
Browser Mode
export default defineConfig({
test: {
browser: {
enabled: true,
name: 'chrome', // 'chrome' | 'firefox' | 'safari'
provider: 'playwright', // 'playwright' | 'webdriverio'
headless: true,
screenshotFailures: true
}
}
});
Performance Optimization
export default defineConfig({
test: {
// Use threads for parallel execution
pool: 'threads',
poolOptions: {
threads: {
singleThread: false,
minThreads: 1,
maxThreads: 4,
useAtomics: true
}
},
// Isolate tests
isolate: true,
// Sequence tests
sequence: {
shuffle: false,
concurrent: false
},
// File parallelism
fileParallelism: true,
// Max concurrency
maxConcurrency: 5,
// Bail on failure
bail: 1
}
});
Type Checking
export default defineConfig({
test: {
typecheck: {
enabled: true,
checker: 'tsc', // 'tsc' | 'vue-tsc'
tsconfig: './tsconfig.json',
include: ['**/*.{test,spec}-d.ts']
}
}
});
Best Practices
- Use TypeScript configuration - Leverage type safety in configuration files
- Configure appropriate environments - Choose the right environment for your tests (node vs jsdom)
- Set up coverage thresholds - Define realistic coverage goals
- Use workspace for monorepos - Leverage workspace config for multiple projects
- Configure path aliases - Match your application's import paths
- Optimize thread usage - Balance parallelism with system resources
- Use globals sparingly - Prefer explicit imports for better tree-shaking
- Configure appropriate timeouts - Set realistic timeouts for async operations
- Enable coverage reporting - Track test coverage consistently
- Use setup files effectively - Centralize common setup logic
Common Pitfalls
- Incorrect environment selection - Using wrong environment causes undefined errors
- Missing path aliases - Forgetting to configure aliases from vite.config
- Overly aggressive coverage thresholds - Unrealistic goals discourage testing
- Not configuring globals - Leads to verbose imports in every test file
- Incorrect thread configuration - Too many threads overwhelm system
- Missing setup files - Repetitive boilerplate in every test
- Wrong coverage provider - V8 vs Istanbul have different capabilities
- Not cleaning mocks - Shared mock state causes flaky tests
- Ignoring watch exclude - Unnecessary file watching slows development
- Misconfigured module resolution - Import errors in test files
When to Use This Skill
- Setting up Vitest in a new Vite project
- Migrating from Jest to Vitest
- Configuring Vitest for TypeScript projects
- Setting up testing in monorepos with workspaces
- Optimizing test performance for large codebases
- Configuring browser testing with Playwright
- Setting up coverage reporting for CI/CD
- Debugging module resolution issues
- Implementing custom test environments
- Configuring type checking for tests