React Router является популярной библиотекой для управления
маршрутизацией в React-приложениях. Одним из полезных хуков,
предоставляемых этой библиотекой, является useLocation.
Этот хук предоставляет информацию о текущем местоположении (адресе) в
приложении, включая путь, параметры запроса и состояние. Тестирование
этого хука важно для обеспечения корректной работы маршрутизации и
взаимодействия компонентов с адресной строкой браузера.
Хук useLocation возвращает объект, содержащий
информацию о текущем местоположении, который включает:
pathname: текущий путь URL.search: строку запроса (например,
?page=2).state: состояние, переданное через объект состояния в
маршрутах (например, при навигации с использованием
state).Тестирование хука useLocation может быть немного
сложным, поскольку он зависит от контекста маршрутизатора. Для успешного
тестирования важно убедиться, что компонент, использующий хук, находится
внутри компонента маршрутизатора (BrowserRouter или
MemoryRouter).
Для тестирования компонентов, использующих useLocation,
нужно настроить тестовое окружение, которое будет эмулировать работу
маршрутизатора. Для этого используется компонент
BrowserRouter или MemoryRouter,
предоставляемый React Router. MemoryRouter — это особая
версия маршрутизатора, предназначенная для тестирования, так как она не
зависит от реального браузера и позволяет гибко управлять состоянием
маршрутов.
Пример обертки компонента в MemoryRouter для
тестирования:
import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import MyComponent from './MyComponent';
const renderWithRouter = (ui, { route = '/' } = {}) => {
return render(
<MemoryRouter initialEntries={[route]}>
{ui}
</MemoryRouter>
);
};
Этот вспомогательный метод позволяет тестировать компонент с разными маршрутами.
useLocationПредположим, что есть компонент, который отображает текущий путь URL:
import { useLocation } from 'react-router-dom';
const CurrentPath = () => {
const location = useLocation();
return <div>Current path is {location.pathname}</div>;
};
Компонент CurrentPath использует хук
useLocation для получения текущего пути и отображает
его.
useLocationДля тестирования этого компонента необходимо имитировать разные маршруты и проверять, что компонент корректно отображает информацию о пути.
Пример теста с использованием React Testing Library:
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import CurrentPath from './CurrentPath';
test('отображает текущий путь', () => {
render(
<MemoryRouter initialEntries={['/home']}>
<CurrentPath />
</MemoryRouter>
);
expect(screen.getByText('Current path is /home')).toBeInTheDocument();
});
test('обновление пути при изменении маршрута', () => {
const { rerender } = render(
<MemoryRouter initialEntries={['/home']}>
<CurrentPath />
</MemoryRouter>
);
expect(screen.getByText('Current path is /home')).toBeInTheDocument();
rerender(
<MemoryRouter initialEntries={['/about']}>
<CurrentPath />
</MemoryRouter>
);
expect(screen.getByText('Current path is /about')).toBeInTheDocument();
});
В этом примере:
/home./home на /about.useLocation также может использоваться в комбинации с
параметрами URL или состоянием, переданным через state в
маршрутах. В случае с параметрами, вы можете получить их через хук
useParams, а состояние доступно через
useLocation.
Пример компонента с параметрами и состоянием:
import { useLocation, useParams } from 'react-router-dom';
const UserDetails = () => {
const { userId } = useParams();
const location = useLocation();
return (
<div>
<h1>User {userId}</h1>
<p>Current path is {location.pathname}</p>
{location.state && <p>From: {location.state.from}</p>}
</div>
);
};
В этом компоненте используется как параметр маршрута
(userId), так и состояние
(location.state).
Пример теста для компонента, который использует параметры и состояние:
import { render, screen } from '@testing-library/react';
import { MemoryRouter, Route } from 'react-router-dom';
import UserDetails from './UserDetails';
test('отображает параметры и состояние', () => {
render(
<MemoryRouter initialEntries={['/user/123']} initialIndex={0}>
<Route path="/user/:userId" element={<UserDetails />} />
</MemoryRouter>
);
expect(screen.getByText('User 123')).toBeInTheDocument();
expect(screen.getByText('Current path is /user/123')).toBeInTheDocument();
});
test('отображает состояние', () => {
render(
<MemoryRouter initialEntries={['/user/123']} initialIndex={0}>
<Route
path="/user/:userId"
element={<UserDetails />}
state={{ from: 'home' }}
/>
</MemoryRouter>
);
expect(screen.getByText('User 123')).toBeInTheDocument();
expect(screen.getByText('From: home')).toBeInTheDocument();
});
В этом примере:
userId).location.state.useLocation, не сможет работать. Использование
MemoryRouter или BrowserRouter в тестах —
обязательное условие.rerender или обновление
initialEntries в MemoryRouter.react-router-dom для передачи данных в маршруты.Тестирование хука useLocation позволяет убедиться в том,
что приложение корректно реагирует на изменения маршрутов, обновляет
отображение компонентов и правильно обрабатывает параметры и состояние
маршрутов.