React Router предоставляет мощный механизм маршрутизации для одностраничных приложений (SPA) на React, позволяя управлять переходами между страницами без полной перезагрузки браузера. Интеграционное тестирование навигации в таких приложениях требует внимания к нескольким ключевым аспектам: правильной конфигурации маршрутов, корректной работе компонентов при изменении URL и корректной обработке переходов между маршрутами.
Для интеграционного тестирования React Router обычно используется
комбинация React Testing Library и
Jest. Важный элемент — обертка тестируемого компонента
в <MemoryRouter> или
<BrowserRouter> для имитации поведения маршрутизатора
в среде тестов:
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import App from './App';
test('рендерит домашнюю страницу по умолчанию', () => {
render(
<MemoryRouter initialEntries={['/']}>
<App />
</MemoryRouter>
);
expect(screen.getByText('Главная')).toBeInTheDocument();
});
Ключевой момент: initialEntries
позволяет задать начальный путь для маршрутизатора в тестах, что
критично для проверки поведения навигации на разных страницах.
Навигация в React Router может осуществляться через компонент
<Link> или через хук useNavigate. Тесты
должны учитывать оба способа:
import { fireEvent } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import App from './App';
test('переход на страницу о приложении', () => {
render(
<MemoryRouter initialEntries={['/']}>
<App />
</MemoryRouter>
);
const aboutLink = screen.getByText('О приложении');
fireEvent.click(aboutLink);
expect(screen.getByText('Информация о приложении')).toBeInTheDocument();
});
Выделение ключевого момента: использование
fireEvent.click или userEvent.click имитирует
реальное поведение пользователя, проверяя корректность рендеринга
целевой страницы после навигации.
React Router позволяет использовать динамические сегменты пути
(:id, :slug), которые необходимо проверять на
корректность обработки в компонентах:
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import UserPage from './UserPage';
test('рендерит страницу пользователя с динамическим ID', () => {
render(
<MemoryRouter initialEntries={['/user/42']}>
<Routes>
<Route path="/user/:id" element={<UserPage />} />
</Routes>
</MemoryRouter>
);
expect(screen.getByText('Пользователь 42')).toBeInTheDocument();
});
Ключевой момент: использование
initialEntries в сочетании с маршрутом, включающим
параметры, позволяет тестировать правильную интерпретацию URL и передачу
параметров в компонент.
Интеграционные тесты часто проверяют корректность перенаправлений при условных маршрутах, например для страниц, требующих авторизации:
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
import App from './App';
test('незалогиненный пользователь перенаправляется на страницу входа', () => {
render(
<MemoryRouter initialEntries={['/profile']}>
<App />
</MemoryRouter>
);
expect(screen.getByText('Вход')).toBeInTheDocument();
});
Выделение ключевого момента: тест должен проверять не только рендер целевого компонента, но и корректное изменение URL при редиректе.
useNavigateХуки React Router требуют отдельного подхода при тестировании:
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import ComponentWithNavigate from './ComponentWithNavigate';
import userEvent from '@testing-library/user-event';
test('навигация через useNavigate работает корректно', async () => {
render(
<MemoryRouter initialEntries={['/start']}>
<ComponentWithNavigate />
</MemoryRouter>
);
const button = screen.getByText('Перейти далее');
await userEvent.click(button);
expect(screen.getByText('Следующая страница')).toBeInTheDocument();
});
Ключевой момент: использование
userEvent вместо fireEvent более точно
имитирует реальные действия пользователя, включая асинхронные
переходы.
MemoryRouter для изоляции
тестов: это предотвращает влияние браузера на результаты и
обеспечивает предсказуемое поведение тестов.initialEntries при изменении
структуры маршрутов, чтобы интеграционные тесты оставались
актуальными.Эффективное интеграционное тестирование навигации обеспечивает надёжность SPA и предотвращает ошибки, связанные с динамическими маршрутами, редиректами и пользовательскими переходами между страницами.