Обёртывание в BrowserRouter

Enzyme является популярной библиотекой для тестирования компонентов React. Одной из основных задач при тестировании является проверка компонентов, которые зависят от контекста маршрутизации. В таких случаях важно обеспечить корректную работу маршрутизации в тестах, и именно для этого используется обёртывание компонентов в BrowserRouter или другие контейнеры маршрутизации.

Когда приложение React использует маршрутизацию с помощью библиотеки React Router, каждый компонент может иметь доступ к контексту маршрутизации через хук useHistory, useLocation или через компоненты типа Route. Тестирование таких компонентов без маршрутизации приведёт к ошибкам, поскольку эти хуки и компоненты будут ожидать наличие контекста маршрутизации.

В связи с этим, для корректного тестирования таких компонентов необходимо обёртывать их в компонент маршрутизации, такой как BrowserRouter. Это обеспечит контекст маршрутов и позволит тестировать логику, связанную с навигацией.

Как оборачивать компоненты в BrowserRouter?

Для использования BrowserRouter в тестах с Enzyme, нужно просто обернуть тестируемый компонент в BrowserRouter в момент его рендеринга. В Enzyme это можно сделать с помощью метода shallow или mount, в зависимости от того, как глубоко нужно тестировать компонент.

Пример обёртывания с использованием mount:

import { mount } from 'enzyme';
import { BrowserRouter } from 'react-router-dom';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('должен правильно рендериться внутри BrowserRouter', () => {
    const wrapper = mount(
      <BrowserRouter>
        <MyComponent />
      </BrowserRouter>
    );

    expect(wrapper.find(MyComponent).length).toBe(1);
  });
});

В данном примере компонент MyComponent будет обёрнут в BrowserRouter для того, чтобы иметь доступ к контексту маршрутизации. Использование mount здесь позволяет рендерить компонент с полным жизненным циклом, что необходимо для работы с маршрутами.

Пример использования shallow с BrowserRouter

Метод shallow используется для поверхностного рендеринга компонента, при этом дочерние компоненты не рендерятся в полном объёме. Для того чтобы протестировать компонент с маршрутизацией в этом случае, можно использовать shallow вместе с обёртыванием в BrowserRouter.

import { shallow } from 'enzyme';
import { BrowserRouter } from 'react-router-dom';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
  it('должен правильно рендериться в shallow', () => {
    const wrapper = shallow(
      <BrowserRouter>
        <MyComponent />
      </BrowserRouter>
    );

    expect(wrapper.find(MyComponent).length).toBe(1);
  });
});

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

Особенности тестирования с маршрутизацией

  1. Использование MemoryRouter вместо BrowserRouter В некоторых случаях вместо BrowserRouter может быть полезен компонент MemoryRouter, который не зависит от реального URL-адреса. Это может быть удобно, если вам нужно настроить маршрутизацию на основе искусственного состояния, не меняя URL в браузере.

    Пример:

    import { mount } from 'enzyme';
    import { MemoryRouter } from 'react-router-dom';
    import MyComponent from './MyComponent';
    
    describe('MyComponent', () => {
      it('должен работать с MemoryRouter', () => {
        const wrapper = mount(
          <MemoryRouter initialEntries={['/test']}>
            <MyComponent />
          </MemoryRouter>
        );
    
        expect(wrapper.find(MyComponent).length).toBe(1);
      });
    });

    В этом примере initialEntries позволяет задать начальный маршрут, что полезно для тестов, где нужно проверить поведение компонентов на основе определённых маршрутов.

  2. Тестирование компонентов с Route и Link Если компонент использует такие элементы, как Route или Link, то важно тестировать их взаимодействие с другими частями приложения. Например, можно проверить, правильно ли работает переход по маршруту, и вызывает ли Link нужный переход.

    Пример тестирования Link:

    import { mount } from 'enzyme';
    import { BrowserRouter, Link } from 'react-router-dom';
    
    describe('Тестирование Link', () => {
      it('должен корректно переходить по маршруту', () => {
        const wrapper = mount(
          <BrowserRouter>
            <Link to="/home">Home</Link>
          </BrowserRouter>
        );
    
        expect(wrapper.find(Link).props().to).toBe('/home');
      });
    });
  3. Проверка работы хуков маршрутизации Если компонент использует хук useHistory, useLocation или другие хуки маршрутизации, то необходимо проверять их работу в контексте BrowserRouter. Это позволяет убедиться, что ваш компонент правильно использует информацию о текущем маршруте и выполняет необходимые действия при изменении маршрута.

    Пример тестирования хука useHistory:

    import { mount } from 'enzyme';
    import { BrowserRouter, useHistory } from 'react-router-dom';
    
    const MyComponent = () => {
      const history = useHistory();
    
      const navigate = () => {
        history.push('/new-route');
      };
    
      return (
        <button onCl ick={navigate}>Go</button>
      );
    };
    
    describe('MyComponent', () => {
      it('должен вызывать history.push при клике', () => {
        const wrapper = mount(
          <BrowserRouter>
            <MyComponent />
          </BrowserRouter>
        );
    
        wrapper.find('button').simulate('click');
        // Проверка вызова push или изменения состояния маршрута
      });
    });

Особенности тестирования в различных режимах

  • Тестирование с серверным рендерингом (SSR): В случае использования серверного рендеринга для React-приложений, возможно, потребуется использовать другие типы маршрутизаторов, такие как StaticRouter, вместо BrowserRouter, так как последний зависит от работы с реальным браузером и URL-адресом.

  • Тестирование с динамическими маршрутами: В случае использования динамических маршрутов, например, с параметрами в URL (/user/:id), важно учесть правильное переданное состояние в MemoryRouter или BrowserRouter, чтобы тесты проходили корректно при различных вариантах маршрутов.

Заключение

Тестирование компонентов, использующих маршрутизацию в React, требует использования соответствующего контейнера маршрутизации, такого как BrowserRouter. В Enzyme для этого достаточно обёрнуть компоненты в нужный маршрутизатор при рендеринге, используя mount или shallow. В зависимости от ситуации, можно использовать как BrowserRouter, так и MemoryRouter для тестов с искусственным состоянием маршрутов.