testing · git:20250301.62fad3c · 2025-03-01 · sha256 b8856a5274b6ac8d
testing git:20250301.62fad3cA
Immutable. This exact content is served forever at /api/v1/blob/b8856a5274b6ac8d.
---
description: Rules for writing Jest tests in TypeScript
globs: *.test.ts, *.test.tsx, **/__tests__/*.ts, **/__tests__/*.tsx
alwaysApply: true
---
# Jest Testing Guidelines
## File Organization
- Place tests next to the file being tested with `.test.ts(x)` extension
- Or use `__tests__` directory in the same folder as the tested file
- Match the folder structure of the source code
## Test Setup
### Custom Test Renderer
Always use the custom test renderer to ensure consistent provider wrapping and test utilities located in test/test-utils.tsx
```
// Re-export everything
export * from '@testing-library/react'
export { render }
```
Usage in tests:
```typescript
import { render, screen } from '@/test/test-utils'
describe('Component', () => {
it('should render correctly', () => {
render(<Component />)
// ... rest of test
})
})
```
## Test Structure
Follow this structure for all tests:
```typescript
describe('ComponentName or FunctionName', () => {
describe('specific functionality or scenario', () => {
it('should describe expected behavior', () => {
// Arrange
// Act
// Assert
})
})
})
```
### Example of Good Test Structure
```typescript
// Good: Clear structure and naming
describe('useAuth', () => {
describe('when user logs in', () => {
it('should update authentication state', () => {
// Arrange
const credentials = {
email: 'test@example.com',
password: 'password123'
}
// Act
const result = login(credentials)
// Assert
expect(result.isAuthenticated).toBe(true)
})
})
})
```
## React Testing Library Best Practices
### Component Testing
```typescript
import { render, screen } from '@/test/test-utils'
import userEvent from '@testing-library/user-event'
describe('Component', () => {
it('should interact correctly', async () => {
// Arrange
render(<Component />)
// Act
await userEvent.click(screen.getByRole('button'))
// Assert
expect(screen.getByText('Expected Result')).toBeInTheDocument()
})
})
```
### Query Priority
Always use queries in this order:
1. getByRole
2. getByLabelText
3. getByPlaceholderText
4. getByText
5. getByDisplayValue
6. getByAltText
7. getByTitle
8. getByTestId
## Mocking
### Module Mocking
```typescript
// Mock modules
jest.mock('./path/to/module', () => ({
someFunction: jest.fn()
}))
// Mock API calls
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve(mockData)
})
) as jest.Mock
```
## Next.js Specific Testing
### Server Components
```typescript
import { render } from '@/test/test-utils'
describe('ServerComponent', () => {
it('should render server content', async () => {
const props = await getServerSideProps()
render(<ServerComponent {...props} />)
// Assert rendered content
})
})
```
### API Routes
```typescript
import { createMocks } from 'node-mocks-http'
describe('API Route', () => {
it('should handle requests correctly', async () => {
const { req, res } = createMocks({
method: 'POST',
body: { data: 'test' }
})
await handler(req, res)
expect(res._getStatusCode()).toBe(200)
})
})
```
### Custom Hooks
```typescript
import { renderHook, act } from '@testing-library/react'
describe('useCustomHook', () => {
it('should manage state correctly', () => {
const { result } = renderHook(() => useCustomHook())
act(() => {
result.current.someFunction()
})
expect(result.current.value).toBe('expected')
})
})
```
## Error Handling
Always test both success and error cases:
```typescript
describe('Form submission', () => {
it('handles successful submission', async () => {
render(<Form />)
await userEvent.click(screen.getByRole('button'))
expect(screen.getByText('Success')).toBeInTheDocument()
})
it('handles submission errors', async () => {
server.use(
rest.post('/api/submit', (req, res, ctx) =>
res(ctx.status(500))
)
)
render(<Form />)
await userEvent.click(screen.getByRole('button'))
expect(screen.getByText('Error')).toBeInTheDocument()
})
})
```
## Coverage Requirements
- Aim for minimum 80% coverage
- Focus on business logic and user interactions
- Test error states and edge cases
- Run coverage reports regularly: `jest --coverage`
## Best Practices Summary
1. Use the custom render function from test-utils.tsx
2. Follow AAA pattern (Arrange, Act, Assert)
3. Test both success and error cases
4. Use meaningful test descriptions
5. Keep tests focused and isolated
6. Mock external dependencies
7. Use proper cleanup in afterEach when needed
8. Prefer userEvent over fireEvent for user interactions
9. Use proper async/await for asynchronous tests
10. Maintain test structure that mirrors component structure