What to Test
What to Test
Integration tests verify multiple units work together.
Integration vs Unit
| Aspect | Unit | Integration |
|---|---|---|
| Scope | Single function | Multiple components |
| Speed | Fast | Slower |
| Isolation | Fully isolated | Some dependencies |
| Confidence | Low | High |
What to Cover
- Component interactions
- API calls
- State management flows
- Form submissions
- Navigation
Testing Components Together
// Test components that work together
describe('ShoppingCart', () => {
it('should add item and update total', async () => {
render(
<CartProvider>
<ProductList />
<CartSummary />
</CartProvider>
);
// Add item
fireEvent.click(screen.getByText('Add to Cart'));
// Verify cart updates
expect(screen.getByText('1 item')).toBeInTheDocument();
expect(screen.getByText('$29.99')).toBeInTheDocument();
});
});
Testing Forms
describe('LoginForm', () => {
it('should submit form with valid data', async () => {
const onSubmit = jest.fn();
render(<LoginForm onSubmit={onSubmit} />);
fireEvent.change(screen.getByLabelText('Email'), {
target: { value: 'test@example.com' },
});
fireEvent.change(screen.getByLabelText('Password'), {
target: { value: 'password123' },
});
fireEvent.click(screen.getByText('Sign In'));
await waitFor(() => {
expect(onSubmit).toHaveBeenCalledWith({
email: 'test@example.com',
password: 'password123',
});
});
});
});
Testing API Calls
Testing API Calls
Mock API responses for reliable tests.
MSW (Mock Service Worker)
// src/mocks/handlers.js
import { rest } from 'msw';
export const handlers = [
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.json([
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
])
);
}),
rest.post('/api/users', async (req, res, ctx) => {
const body = await req.json();
return res(ctx.json({ id: 3, ...body }));
}),
];
// src/mocks/server.js
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
Test Setup
// src/test/setup.js
import { server } from '../mocks/server';
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
Component Test
describe('UserList', () => {
it('should display users', async () => {
render(<UserList />);
// Wait for data to load
await waitFor(() => {
expect(screen.getByText('John')).toBeInTheDocument();
expect(screen.getByText('Jane')).toBeInTheDocument();
});
});
it('should handle API error', async () => {
server.use(
rest.get('/api/users', (req, res, ctx) => {
return res(ctx.status(500));
})
);
render(<UserList />);
await waitFor(() => {
expect(screen.getByText('Error loading users')).toBeInTheDocument();
});
});
});
Fetch Mock
// Simple fetch mock
beforeEach(() => {
global.fetch = jest.fn();
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should fetch data', async () => {
global.fetch.mockResolvedValueOnce({
ok: true,
json: async () => ({ data: 'test' }),
});
const data = await fetchData();
expect(data).toEqual({ data: 'test' });
expect(global.fetch).toHaveBeenCalledWith('/api/data');
});
Testing User Flows
Testing User Flows
Test complete user journeys through the application.
Multi-Step Form
describe('Checkout Flow', () => {
it('should complete checkout', async () => {
render(<CheckoutPage />);
// Step 1: Shipping
fireEvent.change(screen.getByLabelText('Name'), {
target: { value: 'John Doe' },
});
fireEvent.change(screen.getByLabelText('Address'), {
target: { value: '123 Main St' },
});
fireEvent.click(screen.getByText('Continue'));
// Step 2: Payment
await waitFor(() => {
expect(screen.getByText('Payment')).toBeInTheDocument();
});
fireEvent.change(screen.getByLabelText('Card Number'), {
target: { value: '4242424242424242' },
});
fireEvent.click(screen.getByText('Place Order'));
// Step 3: Confirmation
await waitFor(() => {
expect(screen.getByText('Order Confirmed')).toBeInTheDocument();
});
});
});
Navigation Flow
describe('Navigation', () => {
it('should navigate through pages', async () => {
render(
<MemoryRouter>
<App />
</MemoryRouter>
);
// Start at home
expect(screen.getByText('Home')).toBeInTheDocument();
// Navigate to products
fireEvent.click(screen.getByText('Products'));
await waitFor(() => {
expect(screen.getByText('Product List')).toBeInTheDocument();
});
// Navigate to product detail
fireEvent.click(screen.getByText('Product 1'));
await waitFor(() => {
expect(screen.getByText('Product 1 Details')).toBeInTheDocument();
});
});
});
Search Flow
describe('Search', () => {
it('should search and filter results', async () => {
render(<SearchPage />);
// Type search query
fireEvent.change(screen.getByLabelText('Search'), {
target: { value: 'laptop' },
});
// Wait for results
await waitFor(() => {
expect(screen.getByText('Laptop Pro')).toBeInTheDocument();
});
// Apply filter
fireEvent.click(screen.getByText('Price: Low to High'));
// Verify sorted results
await waitFor(() => {
const prices = screen.getAllByText(/\\$\\d+/);
const priceValues = prices.map(el =>
parseInt(el.textContent.replace('$', ''))
);
expect(priceValues).toEqual([...priceValues].sort((a, b) => a - b));
});
});
});
Quiz
1. What is the difference between unit and integration tests?
2. What is MSW?
3. What is a common mistake when implementing Integration Testing in frontend applications?
Flashcards
Question
What is integration testing?
Click to reveal answer
Answer
Testing multiple components working together, including API calls and user interactions.
Question
What is MSW?
Click to reveal answer
Answer
Mock Service Worker - intercepts API requests for realistic testing.
Question
What should integration tests cover?
Click to reveal answer
Answer
Component interactions, API calls, form submissions, and user flows.
Question
How do you test async operations?
Click to reveal answer
Answer
Use waitFor() to wait for async operations to complete.
Revision Notes
Key Takeaways
- 1. Integration tests verify multiple components working together
- 2. MSW provides realistic API mocking
- 3. Test complete user flows through the application
- 4. Use waitFor for async operations
- 5. Integration tests give higher confidence than unit tests
Interview Tips
- • Explain the difference between unit and integration tests
- • Discuss how to mock API calls for testing
- • Know how to test user flows
Cheat Sheet
Integration Testing Cheat Sheet
What to Test
- Component interactions
- API calls
- Form submissions
- User flows
- Navigation
MSW Setup
const server = setupServer(...handlers);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
Common Patterns
- waitFor() for async
- fireEvent for events
- screen queries for elements