useLocation hook тестирование

React Router является популярной библиотекой для управления маршрутизацией в React-приложениях. Одним из полезных хуков, предоставляемых этой библиотекой, является useLocation. Этот хук предоставляет информацию о текущем местоположении (адресе) в приложении, включая путь, параметры запроса и состояние. Тестирование этого хука важно для обеспечения корректной работы маршрутизации и взаимодействия компонентов с адресной строкой браузера.

Основные моменты

  1. Хук useLocation возвращает объект, содержащий информацию о текущем местоположении, который включает:

    • pathname: текущий путь URL.
    • search: строку запроса (например, ?page=2).
    • state: состояние, переданное через объект состояния в маршрутах (например, при навигации с использованием state).
  2. Тестирование хука 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.
  • Имитация параметров и состояния: Для полноценного тестирования компонентов, работающих с параметрами URL или состоянием, используйте соответствующие методы из библиотеки react-router-dom для передачи данных в маршруты.

Тестирование хука useLocation позволяет убедиться в том, что приложение корректно реагирует на изменения маршрутов, обновляет отображение компонентов и правильно обрабатывает параметры и состояние маршрутов.