Claude-skills vitest-testing
Modern TypeScript/JavaScript testing with Vitest. Fast unit and integration tests, native ESM support, Vite-powered HMR, and comprehensive mocking. Use for testing TS/JS projects.
install
source · Clone the upstream repo
git clone https://github.com/secondsky/claude-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/secondsky/claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/vitest-testing/skills/vitest-testing" ~/.claude/skills/secondsky-claude-skills-vitest-testing && rm -rf "$T"
manifest:
plugins/vitest-testing/skills/vitest-testing/SKILL.mdsource content
Vitest Testing
Expert knowledge for testing JavaScript/TypeScript projects using Vitest - a blazingly fast testing framework powered by Vite.
Quick Start
Installation
# Using Bun (recommended) bun add -d vitest # Using npm npm install -D vitest
Configuration
// vitest.config.ts import { defineConfig } from 'vitest/config' export default defineConfig({ test: { globals: true, environment: 'node', // or 'jsdom' coverage: { provider: 'v8', reporter: ['text', 'json', 'html'], thresholds: { lines: 80, functions: 80, branches: 80 }, }, include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'], }, })
Running Tests
# Run all tests (prefer bun) bun test # Watch mode (default) bun test --watch # Run once (CI mode) bun test --run # With coverage bun test --coverage # Specific file bun test src/utils/math.test.ts # Pattern matching bun test --grep="calculates sum" # UI mode (interactive) bun test --ui # Verbose output bun test --reporter=verbose
Writing Tests
Basic Structure
import { describe, it, expect, beforeEach, afterEach } from 'vitest' import { add, subtract } from './math' describe('Math utilities', () => { beforeEach(() => { // Setup before each test }) it('adds two numbers correctly', () => { expect(add(2, 3)).toBe(5) }) it('subtracts two numbers correctly', () => { expect(subtract(5, 3)).toBe(2) }) })
Parametrized Tests
describe.each([ { input: 2, expected: 4 }, { input: 3, expected: 9 }, ])('square function', ({ input, expected }) => { it(`squares ${input} to ${expected}`, () => { expect(square(input)).toBe(expected) }) })
Assertions
// Equality expect(value).toBe(expected) expect(value).toEqual(expected) // Truthiness expect(value).toBeTruthy() expect(value).toBeNull() expect(value).toBeDefined() // Numbers expect(number).toBeGreaterThan(3) expect(number).toBeCloseTo(0.3, 1) // Strings/Arrays expect(string).toMatch(/pattern/) expect(array).toContain(item) // Objects expect(object).toHaveProperty('key') expect(object).toMatchObject({ a: 1 }) // Exceptions expect(() => throwError()).toThrow('message') // Promises await expect(promise).resolves.toBe(value) await expect(promise).rejects.toThrow()
Mocking
Function Mocks
import { vi } from 'vitest' const mockFn = vi.fn() mockFn.mockReturnValue(42) mockFn.mockResolvedValue('async result') mockFn.mockImplementation((x) => x * 2) expect(mockFn).toHaveBeenCalled() expect(mockFn).toHaveBeenCalledWith('arg')
Module Mocking
vi.mock('./api', () => ({ fetchUser: vi.fn(() => ({ id: 1, name: 'Test User' })), })) import { fetchUser } from './api' beforeEach(() => { vi.clearAllMocks() })
Timers
beforeEach(() => vi.useFakeTimers()) afterEach(() => vi.restoreAllMocks()) it('advances timers', () => { const callback = vi.fn() setTimeout(callback, 1000) vi.advanceTimersByTime(1000) expect(callback).toHaveBeenCalledOnce() }) it('mocks dates', () => { const date = new Date('2024-01-01') vi.setSystemTime(date) expect(Date.now()).toBe(date.getTime()) })
Coverage
# Generate coverage report bun test --coverage # HTML report bun test --coverage --coverage.reporter=html open coverage/index.html # Check against thresholds bun test --coverage --coverage.thresholds.lines=90
Integration Testing
import request from 'supertest' import { app } from './app' describe('API endpoints', () => { it('creates a user', async () => { const response = await request(app) .post('/api/users') .send({ name: 'John' }) .expect(201) expect(response.body).toMatchObject({ id: expect.any(Number), name: 'John', }) }) })
Best Practices
- One test file per source file:
→math.tsmath.test.ts - Group related tests with
blocksdescribe() - Use descriptive test names
- Mock only external dependencies
- Use
tests for independent async testsconcurrent - Share expensive fixtures with
beforeAll() - Aim for 80%+ coverage but don't chase 100%
See Also
- Detecting test smellstest-quality-analysis
- E2E testingplaywright-testing
- Validate test effectivenessmutation-testing