Vitest
Vitest - Modern TypeScript testing framework with Vite-native performance, ESM support, and TypeScript-first design
- Skill ID
- bobmatnyc/claude-mpm-skills/vitest
- Publisher
- bobmatnyc
- Repository
- claude-mpm-skills
- Installs
- 0
- Files
- 4
- License
- MIT
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
bobmatnyc/claude-mpm-skills/vitestInstalls these files- CODE_EXAMPLES_INDEX.md
- IMPLEMENTATION_SUMMARY.md
- SKILL.md
- metadata.json
What this skill tells the agent
Vitest - Modern TypeScript Testing
Overview
Vitest is a next-generation test framework powered by Vite, designed for modern TypeScript/JavaScript projects. It provides blazing-fast test execution through HMR-based test running, native ESM support, and first-class TypeScript integration.
Key Features:
- ⚡ Vite-native: Instant HMR-based test execution (10-100x faster than Jest)
- 🎯 TypeScript-first: Built-in TypeScript support, no configuration needed
- 🔄 ESM-native: Native ES modules, async/await, top-level await
- 🧪 Jest-compatible: Compatible API for easy migration
- 📸 Snapshot testing: Built-in snapshot support
- 🎨 Component testing: React Testing Library, Vue Test Utils integration
- 📊 Coverage: Built-in v8/c8 coverage (faster than Istanbul)
- 🌐 UI mode: Beautiful web UI for test debugging
Installation:
npm install -D vitest
# TypeScript types (usually auto-detected)
npm install -D @vitest/ui # Optional: UI modeBasic Setup
1. Configure Vitest
vitest.config.ts:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true, // Use describe/it/expect globally
environment: 'node', // or 'jsdom' for DOM testing
coverage: {
provider: 'v8', // or 'istanbul'
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/',
'dist/',
'**/*.test.ts',
'**/*.spec.ts',
],
},
include: ['**/*.{test,spec}.{ts,tsx}'],
exclude: ['node_modules', 'dist', '.idea', '.git', '.cache'],
},
});2. TypeScript Configuration
tsconfig.json:
{
"compilerOptions": {
"types": ["vitest/globals"] // For global describe/it/expect
}
}Alternative (without globals):
import { describe, it, expect } from 'vitest';3. Package.json Scripts
{
"scripts": {
"test": "vitest run", // CI mode (single run)
"test:watch": "vitest", // Watch mode (default)
"test:ui": "vitest --ui", // UI mode
"test:coverage": "vitest run --coverage"
}
}Core Testing Patterns
Basic Test Structure
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
describe('Calculator', () => {
let calculator: Calculator;
beforeEach(() => {
calculator = new Calculator();
});
it('adds two numbers correctly', () => {
const result = calculator.add(2, 3);
expect(result).toBe(5);
});
it('handles negative numbers', () => {
expect(calculator.add(-5, 3)).toBe(-2);
});
});TypeScript Type Testing
import { describe, it, expectTypeOf, assertType } from 'vitest';
interface User {
id: number;
name: string;
email: string;
}
describe('Type Safety', () => {
it('ensures correct types', () => {
const user: User = {
id: 1,
name: 'Alice',
email: 'alice@example.com',
};
// Type assertions
expectTypeOf(user.id).toBeNumber();
expectTypeOf(user.name).toBeString();
expectTypeOf(user).toMatchTypeOf<User>();
// Assert type at compile time
assertType<User>(user);
});
it('checks function return types', () => {
function getUser(): User {
return { id: 1, name: 'Bob', email: 'bob@example.com' };
}
expectTypeOf(getUser).returns.toMatchTypeOf<User>();
});
});Mocking and Spies
vi.mock for Module Mocking
import { describe, it, expect, vi } from 'vitest';
import { fetchUser } from './api';
import { UserService } from './UserService';
// Mock entire module
vi.mock('./api', () => ({
fetchUser: vi.fn(),
}));
describe('UserService', () => {
it('fetches user data', async () => {
const mockUser = { id: 1, name: 'Alice' };
vi.mocked(fetchUser).mockResolvedValue(mockUser);
const service = new UserService();
const user = await service.getUser(1);
expect(fetchUser).toHaveBeenCalledWith(1);
expect(user).toEqual(mockUser);
});
});vi.spyOn for Method Spying
import { describe, it, expect, vi } from 'vitest';
class Logger {
log(message: string) {
console.log(message);
}
}
describe('Logger Spy', () => {
it('tracks method calls', () => {
const logger = new Logger();
const spy = vi.spyOn(logger, 'log');
logger.log('Hello');
logger.log('World');
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledWith('Hello');
expect(spy).toHaveBeenLastCalledWith('World');
spy.mockRestore(); // Restore original implementation
});
});Mock Implementation
import { describe, it, expect, vi } from 'vitest';
describe('Mock Implementation', () => {
it('provides custom mock implementation', () => {
const mockFn = vi.fn((x: number) => x * 2);
expect(mockFn(5)).toBe(10);
expect(mockFn).toHaveBeenCalledWith(5);
// Change implementation
mockFn.mockImplementation((x: number) => x + 10);
expect(mockFn(5)).toBe(15);
// One-time implementation
mockFn.mockImplementationOnce((x: number) => 100);
expect(mockFn(5)).toBe(100);
expect(mockFn(5)).toBe(15); // Back to default
});
});Mocking Timers
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
describe('Timer Mocking', () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.restoreAllMocks();
});
it('fast-forwards time', () => {
const callback = vi.fn();
setTimeout(callback, 1000);
vi.advanceTimersByTime(500);
expect(callback).not.toHaveBeenCalled();
vi.advanceTimersByTime(500);
expect(callback).toHaveBeenCalledTimes(1);
});
it('runs all timers', async () => {
const callback = vi.fn();
setTimeout(callback, 1000);
setTimeout(callback, 2000);
await vi.runAllTimersAsync();
expect(callback).toHaveBeenCalledTimes(2);
});
});React Testing Integration
Setup React Testing Library
npm install -D @testing-library/react @testing-library/jest-dom @testing-library/user-event
npm install -D jsdom # For DOM environmentvitest.config.ts (React):
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
},
});src/test/setup.ts:
import '@testing-library/jest-dom';
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();
});React Component Testing
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Counter } from './Counter';
describe('Counter Component', () => {
it('renders initial count', () => {
render(<Counter initialCount={0} />);
expect(screen.getByText('Count: 0')).toBeInTheDocument();
});
it('increments counter on button click', async () => {
const user = userEvent.setup();
render(<Counter initialCount={0} />);
const button = screen.getByRole('button', { name: /increment/i });
await user.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
it('calls onChange callback', async () => {
const onChange = vi.fn();
const user = userEvent.setup();
render(<Counter initialCount={0} onChange={onChange} />);
await user.click(screen.getByRole('button', { name: /increment/i }));
expect(onChange).toHaveBeenCalledWith(1);
});
});Testing Hooks
import { describe, it, expect } from 'vitest';
import { renderHook, act } from '@testing-library/react';More from bobmatnyc
Use this skill in a project
Open any RiverX project, search the Skills panel for bobmatnyc/claude-mpm-skills/vitest, and install it in one click.
