Jest & React Testing Library Cheatsheet
Jest Core
Test Structure
describe('Component/Unit', () => {
beforeAll(() => {})
beforeEach(() => {})
afterEach(() => {})
afterAll(() => {})
it('should do something', () => {})
test('does something', () => {})
})
Matchers
// Common
expect(value).toBe(exact)
expect(value).toEqual(deepEqual)
expect(value).toBeTruthy()
expect(value).toBeFalsy()
expect(value).toBeNull()
expect(value).toBeUndefined()
expect(value).toBeDefined()
// Numbers
expect(value).toBeGreaterThan(3)
expect(value).toBeLessThan(5)
expect(value).toBeCloseTo(0.3)
// Strings
expect(str).toMatch(/regex/)
expect(str).toContain('substring')
expect(str).toHaveLength(6)
// Arrays/Objects
expect(arr).toContain(item)
expect(obj).toHaveProperty('key')
expect(arr).toHaveLength(n)
// Functions/Async
expect(fn).toThrow(error)
expect(promise).resolves.toBe(value)
expect(promise).rejects.toThrow(error)
Mocks
// Function Mocks
const mock = jest.fn()
mock.mockReturnValue(value)
mock.mockImplementation(() => value)
mock.mockResolvedValue(value)
mock.mockRejectedValue(error)
// Verifying Calls
expect(mock).toHaveBeenCalled()
expect(mock).toHaveBeenCalledWith(arg1, arg2)
expect(mock).toHaveBeenCalledTimes(n)
// Module Mocks
jest.mock('./module')
jest.spyOn(object, 'method')
React Testing Library
Rendering
import { render, screen } from '@testing-library/react'
// Basic Render
render(<Component />)
// With Providers
render(
<Provider>
<Component />
</Provider>
)
// With Router
render(
<MemoryRouter initialEntries={['/path']}>
<Component />
</MemoryRouter>
)
Queries
// Priority Order:
// 1. getByRole
// 2. getByLabelText
// 3. getByPlaceholderText
// 4. getByText
// 5. getByDisplayValue
// 6. getByAltText
// 7. getByTitle
// 8. getByTestId
// Variants:
// getBy: Expect element to be in DOM
// queryBy: Element might not be in DOM
// findBy: Async, element might appear in DOM
// Multiple elements:
// getAllBy, queryAllBy, findAllBy
// Examples
screen.getByRole('button', { name: /submit/i })
screen.getByLabelText('Username')
screen.getByPlaceholderText('Enter value')
screen.getByText(/hello/i)
screen.getByTestId('custom-id')
User Events
import userEvent from '@testing-library/user-event'
// Setup
const user = userEvent.setup()
// Events
await user.click(element)
await user.type(input, 'text')
await user.keyboard('{Enter}')
await user.selectOptions(select, ['option'])
await user.clear(input)
await user.tab()
Common Patterns
// Testing Form Submission
test('form submission', async () => {
const user = userEvent.setup()
const onSubmit = jest.fn()
render(<Form onSubmit={onSubmit} />)
await user.type(screen.getByLabelText('Email'), 'test@test.com')
await user.type(screen.getByLabelText('Password'), 'password')
await user.click(screen.getByRole('button', { name: /submit/i }))
expect(onSubmit).toHaveBeenCalled()
})
// Testing Async Actions
test('async data fetching', async () => {
render(<UserList />)
expect(screen.getByText('Loading...')).toBeInTheDocument()
await screen.findByRole('list')
expect(screen.getAllByRole('listitem')).toHaveLength(3)
})
// Testing Error States
test('error handling', async () => {
server.use(
rest.get('/api/users', (req, res, ctx) => {
return res(ctx.status(500))
})
)
render(<UserList />)
await screen.findByText('Error loading users')
})
Custom Hooks Testing
import { renderHook, act } from '@testing-library/react'
test('custom hook', () => {
const { result } = renderHook(() => useCustomHook())
act(() => {
result.current.update()
})
expect(result.current.value).toBe('updated')
})
Testing Best Practices
- Test behavior, not implementation
- Use accessible queries
- Avoid implementation details
- Test user interactions
- Test error scenarios
- Mock external dependencies
- Keep tests focused and simple
- Use meaningful test descriptions
- Follow Arrange-Act-Assert pattern
- Write maintainable tests