vitest
This skill should be used when the user asks to write, run, or debug tests with Vitest in TypeScript React/Next.js projects, or mentions unit/component tests, mocking, or testing utilities. Trigger phrases include "write tests", "run tests", "mock functions", "test coverage".
What it does
Your Role
You are an expert in writing tests with Vitest v4 for TypeScript React/Next.js projects. You help users write high-quality tests, debug failures, and maintain test suites efficiently.
Typical setup:
- Vitest v4 with jsdom environment
- Globals enabled (
describe,test,expect,vi) - Path aliases configured per project
Quick Start
Running Tests
# Run all unit tests
nlx vitest run
# Run tests matching pattern
nlx vitest run tokens
# Run specific test file
nlx vitest run src/utils/format.test.ts
# Run tests with matching name
nlx vitest run -t "adds token"
# Watch mode
nlx vitest
Writing Your First Test
File naming: *.test.ts or *.test.tsx
Location: Colocate with source files
import { describe, test, expect } from "vitest";
import { myFunction } from "./my-function";
describe("myFunction", () => {
test("returns expected value", () => {
expect(myFunction(5)).toBe(10);
});
});
Project-Specific Patterns
Test Organization
Use visual separators and descriptive blocks:
describe("TokenStore", () => {
/* ----------------------------------------------------------------
* Setup
* ------------------------------------------------------------- */
const validToken = { address: "0x123", symbol: "TEST" };
afterEach(() => {
// Reset state between tests
useTokensStore.getState().clearAll();
});
/* ----------------------------------------------------------------
* Adding tokens
* ------------------------------------------------------------- */
describe("addToken", () => {
test("adds valid token and returns true", () => {
const success = useTokensStore.getState().addToken(validToken);
expect(success).toBe(true);
});
});
});
Cleanup Pattern
Always reset state in afterEach():
import { afterEach } from "vitest";
afterEach(() => {
// Reset mocks
vi.clearAllMocks();
// Reset environment
process.env.NODE_ENV = originalEnv;
// Reset stores
});
Factory Mock Pattern
Prefer factory functions for complex mocks:
// __mocks__/localStorage.ts
import { vi } from "vitest";
export function createLocalStorageMock() {
const store = new Map<string, string>();
return {
getItem: vi.fn((key: string) => store.get(key) ?? null),
setItem: vi.fn((key: string, value: string) => {
store.set(key, value);
}),
removeItem: vi.fn((key: string) => {
store.delete(key);
}),
clear: vi.fn(() => {
store.clear();
})
};
}
// Usage in tests
import { createLocalStorageMock } from "./__mocks__/localStorage";
const mockStorage = createLocalStorageMock();
global.localStorage = mockStorage as Storage;
Shared Setup File
Global mocks and configuration live in a setup file (e.g., tests/setup.ts):
import { vi } from "vitest";
// Mock logger for all tests
vi.mock("@/utils/logger", () => ({
createLogger: vi.fn(() => ({
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn()
}))
}));
Common Testing Scenarios
Testing Utilities
import { describe, test, expect, afterEach } from "vitest";
import { getEnvironment } from "./environment";
describe("getEnvironment", () => {
const originalEnv = process.env.NODE_ENV;
afterEach(() => {
process.env.NODE_ENV = originalEnv;
});
test("returns production when NODE_ENV is production", () => {
process.env.NODE_ENV = "production";
expect(getEnvironment()).toBe("production");
});
test("returns development by default", () => {
process.env.NODE_ENV = undefined;
expect(getEnvironment()).toBe("development");
});
});
Async Testing
test("async function resolves correctly", async () => {
const result = await fetchData();
expect(result).toEqual({ data: "value" });
});
test("async function rejects with error", async () => {
await expect(failingFunction()).rejects.toThrow("Error message");
});
Mocking
For function mocks (vi.fn, spyOn), module mocks (vi.mock, vi.doMock), and timer mocks (vi.useFakeTimers), see references/mocking.md.
Debugging Failed Tests
Reading Test Output
Focus on these signals:
- File and line number - Where the failure occurred
- Expected vs. received - What went wrong
- Stack trace - Ignore framework internals, focus on your code
Common Failures
For known failure modes and how to recover (timeouts, async assertions, mock not called, snapshot drift, etc.), see references/troubleshooting.md.
Debugging Tools
nlx vitest --reporter=verbose # Detailed output
nlx vitest --ui # Visual debugging interface
nlx vitest --coverage # See what's tested
nlx vitest --inspect # Node debugger
nlx vitest --run # Disable watch mode
Best Practices
DO
- Colocate tests with source files (
feature.ts+feature.test.ts) - Use
describeblocks to group related tests - Add
afterEach()cleanup for state/mocks - Use visual separators for clarity (
/* --- */) - Test behavior, not implementation
- Use explicit type annotations for mocks
- Keep tests focused and independent
- Write tests before fixing bugs (reproduce the bug first)
DON'T
- Test implementation details (internal variables)
- Share state between tests
- Mock everything (only mock boundaries: network, storage, time)
- Forget to restore mocks/timers
- Use
anytypes in tests - Create brittle tests tied to DOM structure
- Add backward-compatibility hacks for test utilities
Advanced Topics
For deeper dives, see the ./references/ directory:
testing-patterns.md- Complete pattern library (component tests, complex mocking, async patterns)monorepo-testing.md- Workspace-specific strategies (shared vs. app tests, path aliases, organization)troubleshooting.md- Debug guide (common errors, performance, coverage, CI/CD)
Coverage Analysis
To add coverage:
// vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: "v8",
reporter: ["text", "html", "json"],
exclude: ["**/*.test.ts", "**/__mocks__/**", "**/node_modules/**"]
}
}
});
Run with: nlx vitest --coverage
Configuration Reference
Example config: vitest.config.ts
{
environment: "jsdom", // React/DOM APIs available
globals: true, // No imports needed for describe/test/expect
include: ["**/*.test.{js,ts,tsx}"],
exclude: ["**/node_modules/**", "**/e2e/**"],
setupFiles: ["./tests/setup.ts"],
alias: {
"@": "./src",
// Add your project's path aliases
},
}
Next Steps
- For component testing - See
./references/testing-patterns.md(React Testing Library setup) - For monorepo-specific strategies - See
./references/monorepo-testing.md - For debugging help - See
./references/troubleshooting.md
Start with simple unit tests, add component tests as needed.
Capabilities
Install
Quality
deterministic score 0.48 from registry signals: · indexed on github topic:agent-skills · 56 github stars · SKILL.md body (7,137 chars)