| name | frontend/typescript-testing |
| description | Designs tests with React Testing Library and MSW. Applies component testing patterns. |
TypeScript Testing Rules (Frontend)
Test Framework
- Vitest: This project uses Vitest
- React Testing Library: For component testing
- MSW (Mock Service Worker): For API mocking
- Test imports:
import { describe, it, expect, beforeEach, vi } from 'vitest' - Component test imports:
import { render, screen, fireEvent } from '@testing-library/react' - Mock creation: Use
vi.mock()
Basic Testing Policy
Quality Requirements
- Coverage: Unit test coverage must be 60% or higher (Frontend standard 2025)
- Independence: Each test can run independently without depending on other tests
- Reproducibility: Tests are environment-independent and always return the same results
- Readability: Test code maintains the same quality as production code
Coverage Requirements (ADR-0002 Compliant)
Mandatory: Unit test coverage must be 60% or higher Component-specific targets:
- Atoms (Button, Text, etc.): 70% or higher
- Molecules (FormField, etc.): 65% or higher
- Organisms (Header, Footer, etc.): 60% or higher
- Custom Hooks: 65% or higher
- Utils: 70% or higher
Metrics: Statements, Branches, Functions, Lines
Test Types and Scope
Unit Tests (React Testing Library)
- Verify behavior of individual components or functions
- Mock all external dependencies
- Most numerous, implemented with fine granularity
- Focus on user-observable behavior
Integration Tests (React Testing Library + MSW)
- Verify coordination between multiple components
- Mock APIs with MSW (Mock Service Worker)
- No actual DB connections (backend manages DB)
- Verify major functional flows
Cross-functional Verification in E2E Tests
- Mandatory verification of impact on existing features when adding new features
- Cover integration points with "High" and "Medium" impact levels from Design Doc's "Integration Point Map"
- Verification pattern: Existing feature operation -> Enable new feature -> Verify continuity of existing features
- Success criteria: No change in displayed content, rendering time within 5 seconds
- Designed for automatic execution in CI/CD pipelines
Test Implementation Conventions
Directory Structure (Co-location Principle)
src/
└── components/
└── Button/
├── Button.tsx
├── Button.test.tsx # Co-located with component
└── index.ts
Rationale:
- React Testing Library best practice
- ADR-0002 Co-location principle
- Easy to find and maintain tests alongside implementation
Naming Conventions
- Test files:
{ComponentName}.test.tsx - Integration test files:
{FeatureName}.integration.test.tsx - Test suites: Names describing target components or features
- Test cases: Names describing expected behavior from user perspective
Test Code Quality Rules
Recommended: Keep all tests always active
- Merit: Guarantees test suite completeness
- Practice: Fix problematic tests and activate them
Avoid: test.skip() or commenting out
- Reason: Creates test gaps and incomplete quality checks
- Solution: Completely delete unnecessary tests
Mock Type Safety Enforcement
MSW (Mock Service Worker) Setup
// Type-safe MSW handler
import { rest } from 'msw'
const handlers = [
rest.get('/api/users/:id', (req, res, ctx) => {
return res(ctx.json({ id: '1', name: 'John' } satisfies User))
})
]
Component Mock Type Safety
// Only required parts
type TestProps = Pick<ButtonProps, 'label' | 'onClick'>
const mockProps: TestProps = { label: 'Click', onClick: vi.fn() }
// Only when absolutely necessary, with clear justification
const mockRouter = {
push: vi.fn()
} as unknown as Router // Complex router type structure
Basic React Testing Library Example
import { describe, it, expect, vi } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import { Button } from './Button'
describe('Button', () => {
it('should call onClick when clicked', () => {
const onClick = vi.fn()
render(<Button label="Click me" onClick={onClick} />)
fireEvent.click(screen.getByRole('button', { name: 'Click me' }))
expect(onClick).toHaveBeenCalledOnce()
})
})