Для начала работы с React Router необходимо установить
соответствующий пакет. На текущий момент актуальной версией является
react-router-dom, предназначенная для веб-приложений на
React. Установка выполняется через npm или yarn:
npm install react-router-dom
# или
yarn add react-router-dom
После установки важно убедиться, что версия React совместима с React
Router. Последние версии требуют React 18 и выше, что обеспечивает
поддержку новых возможностей, таких как Suspense и
Concurrent Mode.
Основные компоненты библиотеки:
BrowserRouter — оборачивает приложение и обеспечивает
работу с историей браузера.Routes — контейнер для всех маршрутов приложения.Route — отдельный маршрут, связывающий путь с
компонентом.Link и NavLink — элементы для навигации
без перезагрузки страницы.useNavigate — хук для программной навигации.useParams — хук для получения параметров маршрута.Пример базового импорта:
import {
BrowserRouter,
Routes,
Route,
Link,
NavLink,
useNavigate,
useParams
} from 'react-router-dom';
Для тестирования маршрутов рекомендуется использовать
Jest и React Testing Library. Они позволяют
эмулировать поведение пользователя и проверять корректность
навигации.
npm install --save-dev @testing-library/react @testing-library/jest-dom 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(/главная страница/i)).toBeInTheDocument();
});
Ключевой момент — initialEntries позволяет задать
начальный путь, по которому будет выполнен рендеринг компонента. Это
особенно полезно для проверки маршрутов с параметрами и редиректов.
React Router поддерживает динамические сегменты в URL, например
/users/:id. Для тестов это выглядит так:
import UserPage from './UserPage';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
test('рендерит страницу пользователя по id', () => {
render(
<MemoryRouter initialEntries={['/users/42']}>
<Routes>
<Route path="/users/:id" element={<UserPage />} />
</Routes>
</MemoryRouter>
);
expect(screen.getByText(/пользователь 42/i)).toBeInTheDocument();
});
Здесь MemoryRouter и initialEntries создают
виртуальный URL /users/42, а компонент
UserPage использует useParams для получения
id.
Для тестирования переходов между маршрутами используется хук
useNavigate или компонент Link. В тестах можно
симулировать клики и проверять обновление URL:
import { fireEvent } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import App from './App';
test('переход на страницу About', () => {
render(
<MemoryRouter initialEntries={['/']}>
<App />
</MemoryRouter>
);
fireEvent.click(screen.getByText(/о нас/i));
expect(screen.getByText(/страница о нас/i)).toBeInTheDocument();
});
Важно, чтобы все маршруты, которые могут использоваться в тестах,
были явно объявлены внутри Routes. Это предотвращает ошибки
рендеринга и исключает ситуации, когда тест пытается перейти на
несуществующий маршрут.
Современные приложения часто используют ленивую загрузку компонентов
с помощью React.lazy и Suspense. Для
тестирования таких маршрутов необходимо оборачивать компоненты в
Suspense:
import { Suspense } from 'react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
const LazyPage = React.lazy(() => import('./LazyPage'));
test('рендер ленивой страницы', async () => {
render(
<MemoryRouter initialEntries={['/lazy']}>
<Suspense fallback={<div>Загрузка...</div>}>
<Routes>
<Route path="/lazy" element={<LazyPage />} />
</Routes>
</Suspense>
</MemoryRouter>
);
expect(await screen.findByText(/ленивая страница/i)).toBeInTheDocument();
});
Использование findByText вместо getByText
важно для асинхронных компонентов, так как оно возвращает промис и
корректно ждёт рендеринга.
Для полноценного тестирования маршрутов часто необходимо
предоставлять контексты, например AuthContext или
ThemeContext. Они оборачиваются вокруг
MemoryRouter:
import { AuthProvider } from './AuthContext';
render(
<AuthProvider value={{ user: { name: 'Иван' } }}>
<MemoryRouter initialEntries={['/dashboard']}>
<App />
</MemoryRouter>
</AuthProvider>
);
Это обеспечивает корректное функционирование компонентов, зависящих от контекста, в тестовой среде.
Тщательная настройка тестового окружения с использованием
MemoryRouter, моков контекста и асинхронной поддержки
позволяет создавать стабильные и воспроизводимые тесты для приложений на
React с React Router. Использование initialEntries, обёртки
в Suspense и правильной структуры маршрутов гарантирует
точное тестирование логики навигации, параметров URL и редиректов.