| name | create-unit-test |
| description | Create Vitest unit tests following project patterns. Use when writing tests for functions, components, models, or route loaders/actions. |
Create Unit Test
When to Use
- Writing tests for any code
- User asks to "add tests" or "test this function"
- After implementing new features
Test File Location
Tests are co-located with source files:
app/components/Button.tsx
app/components/Button.test.tsx # Component test
app/models/user.server.ts
app/models/user.server.test.ts # Model test
Test Template
import { describe, it, expect, vi, beforeEach } from 'vitest';
describe('Feature Name', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('does something specific', () => {
// Arrange
const input = 'test';
// Act
const result = functionUnderTest(input);
// Assert
expect(result).toBe('expected');
});
});
Component Testing
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '~/test/utils';
import { Button } from './Button';
describe('Button', () => {
it('renders and handles clicks', () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click</Button>);
screen.getByRole('button').click();
expect(handleClick).toHaveBeenCalled();
});
});
Query by role, label, text - NOT class or test IDs.
Model Testing (Mock Prisma)
// Mock BEFORE importing
vi.mock('~/db.server', () => ({
prisma: { user: { findUnique: vi.fn() } },
}));
import { prisma } from '~/db.server';
import { getUserProfile } from './user.server';
describe('User Model', () => {
it('fetches user', async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValue({ id: '123' } as any);
const result = await getUserProfile('123');
expect(prisma.user.findUnique).toHaveBeenCalledWith({
where: { id: '123' },
select: expect.any(Object),
});
});
});
Critical: Mock ~/db.server BEFORE importing it.
Mocking Patterns
// Return value
mockFn.mockReturnValue('value');
mockFn.mockResolvedValue({ data: 'async' });
// Suppress console
vi.spyOn(console, 'error').mockImplementation(() => {});
Running Tests
npm test # Watch mode
npm run test:run # Single run
npm run test:coverage # Coverage
Checklist
- Create
*.test.ts(x)co-located with source - Mock dependencies BEFORE importing them
- Call
vi.clearAllMocks()inbeforeEach - Use semantic queries (role, label, text)
Templates
Full Reference
See .github/instructions/unit-testing.instructions.md for:
- Route loader/action testing
- Async module mocking
- Test utilities reference
- What to test vs. what not to test