Vitest: Faster Unit Testing for TypeScript Projects
Jest requires Babel or ts-jest for TypeScript. Vitest runs TypeScript natively, shares your Vite config, and starts 10x faster with HMR for tests.
Install
npm install --save-dev vitest @vitest/coverage-v8 @testing-library/react @testing-library/jest-dom
Config
// vitest.config.ts
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',
coverage: {
provider: 'v8',
reporter: ['text', 'lcov'],
exclude: ['node_modules', 'src/test'],
},
},
});
// src/test/setup.ts
import '@testing-library/jest-dom';
Unit Tests
import { describe, it, expect, vi } from 'vitest';
import { formatCurrency, calculateDiscount } from './utils';
describe('formatCurrency', () => {
it('formats USD correctly', () => {
expect(formatCurrency(2999, 'USD')).toBe('$29.99');
});
it('handles zero', () => {
expect(formatCurrency(0, 'USD')).toBe('$0.00');
});
});
describe('calculateDiscount', () => {
it('applies percentage discount', () => {
expect(calculateDiscount(100, 20)).toBe(80);
});
it('throws for discount > 100', () => {
expect(() => calculateDiscount(100, 110)).toThrow('Invalid discount');
});
});
Component Tests
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button';
describe('Button', () => {
it('calls onClick when clicked', async () => {
const user = userEvent.setup();
const onClick = vi.fn();
render(<Button onClick={onClick}>Click me</Button>);
await user.click(screen.getByRole('button', { name: 'Click me' }));
expect(onClick).toHaveBeenCalledOnce();
});
it('is disabled when loading', () => {
render(<Button loading>Save</Button>);
expect(screen.getByRole('button')).toBeDisabled();
});
});
Mocking
import { vi, beforeEach } from 'vitest';
// Mock a module
vi.mock('@/lib/stripe', () => ({
stripe: {
paymentIntents: {
create: vi.fn().mockResolvedValue({ id: 'pi_test', status: 'succeeded' }),
},
},
}));
// Mock environment variables
beforeEach(() => {
vi.stubEnv('STRIPE_SECRET_KEY', 'sk_test_123');
});
Watch Mode
npx vitest # Watch mode — reruns on file change
npx vitest run # Single run (CI)
npx vitest --coverage # With coverage report
npx vitest ui # Visual browser UI for tests
Snapshot Testing
it('renders correctly', () => {
const { container } = render(<ProductCard product={mockProduct} />);
expect(container).toMatchSnapshot();
});
Vitest ships pre-configured in the Ship Fast Skill Pack — /test skill generates comprehensive test suites for any function or component. $49 at whoffagents.com.
Top comments (0)