Тестирование роутинга

Тестирование роутинга в Jest

Тестирование роутинга в JavaScript-приложениях играет важную роль в обеспечении правильной навигации между различными страницами и компонентами. При использовании React, Vue, Angular или других популярных библиотек для создания одностраничных приложений (SPA), правильная настройка и тестирование роутинга становятся важной частью процесса разработки.

Jest является одним из наиболее популярных инструментов для тестирования в экосистеме JavaScript. В этой статье рассмотрим, как эффективно тестировать маршруты и роутеры, используя Jest вместе с библиотеками для тестирования, такими как React Testing Library, и дополнительными библиотеками для маршрутизации.

Для тестирования роутинга необходимо понять, как маршрутизаторы взаимодействуют с компонентами, как работают переходы между страницами и как они могут влиять на состояние приложения. Рассмотрим пример на основе React и библиотеки React Router, которая предоставляет маршрутизатор для SPA.

Установка зависимостей

Перед тем как начать тестирование роутинга, необходимо установить несколько библиотек, включая сам Jest, React Router и React Testing Library.

npm install --save react-router-dom
npm install --save-dev @testing-library/react @testing-library/jest-dom

Тестирование простого маршрута

Для начала создадим простое приложение с двумя страницами. Допустим, у нас есть компонент Home и компонент About. В приложении используется React Router для маршрутизации.

// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from './Home';
import About from './About';

const App = () => (
  <Router>
    <Switch>
      <Route path="/" exact component={Home} />
      <Route path="/about" component={About} />
    </Switch>
  </Router>
);

export default App;

Теперь создадим два компонента:

// Home.js
import React from 'react';

const Home = () => <h1>Home Page</h1>;

export default Home;
// About.js
import React from 'react';

const About = () => <h1>About Page</h1>;

export default About;

Приложение настроено для маршрутизации между двумя страницами: Home и About. Теперь необходимо протестировать, что приложение корректно рендерит нужный компонент в зависимости от URL.

Тестирование навигации

Для тестирования маршрутов и переходов между страницами можно использовать React Testing Library. В этом примере мы протестируем, что компонент Home рендерится по пути / и компонент About — по пути /about.

// App.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';

test('renders home page by default', () => {
  render(
    <Router>
      <App />
    </Router>
  );
  expect(screen.getByText(/home page/i)).toBeInTheDocument();
});

test('renders about page when navigating to /about', () => {
  render(
    <Router>
      <App />
    </Router>
  );

  // Имитируем переход по маршруту
  fireEvent.click(screen.getByText(/about/i));

  expect(screen.getByText(/about page/i)).toBeInTheDocument();
});

В этих тестах мы проверяем два важных аспекта:

  1. Отображение начальной страницы. После рендера компонента App по умолчанию должен отображаться компонент Home.
  2. Переход по маршруту. При клике на ссылку, которая ведет на страницу /about, должен отображаться компонент About.

Тестирование с использованием моков

При тестировании маршрутизации бывает полезно использовать моки для компонентов, которые не зависят от текущего маршрута. Это позволяет изолировать тестируемые компоненты и избежать сложности с зависимостями.

Например, если компонент Home или About обращается к внешним API или сервисам, их можно замокать.

jest.mock('./Home', () => () => <h1>Mocked Home Page</h1>);
jest.mock('./About', () => () => <h1>Mocked About Page</h1>);

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

Тестирование динамических маршрутов

В некоторых случаях маршруты могут быть динамическими, что означает, что они могут принимать параметры, передаваемые через URL. Рассмотрим пример с динамическим маршрутом:

// Product.js
import React from 'react';
import { useParams } from 'react-router-dom';

const Product = () => {
  const { id } = useParams();
  return <h1>Product {id}</h1>;
};

export default Product;

Этот компонент отображает страницу с продуктом, используя параметр из URL. Чтобы протестировать динамический маршрут, мы можем использовать MemoryRouter, который позволяет нам симулировать различные URL.

// App.js
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import Product from './Product';

const App = () => (
  <Switch>
    <Route path="/product/:id" component={Product} />
  </Switch>
);

export default App;

Тестирование динамического маршрута:

// App.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import App from './App';

test('renders product page with dynamic ID', () => {
  render(
    <MemoryRouter initialEntries={['/product/123']}>
      <App />
    </MemoryRouter>
  );
  
  expect(screen.getByText(/Product 123/i)).toBeInTheDocument();
});

Здесь используется MemoryRouter, который позволяет нам указать начальный путь (/product/123). В результате теста мы проверяем, что компонент отображает правильный идентификатор продукта.

Тестирование защищенных маршрутов

В приложениях могут быть маршруты, которые требуют аутентификации. Для тестирования таких маршрутов можно замокать состояние авторизации или создать простой компонент защиты маршрута.

// ProtectedRoute.js
import React from 'react';
import { Route, Redirect } from 'react-router-dom';

const ProtectedRoute = ({ isAuthenticated, component: Component, ...rest }) => (
  <Route
    {...rest}
    render={(props) =>
      isAuthenticated ? <Component {...props} /> : <Redirect to="/login" />
    }
  />
);

export default ProtectedRoute;

В тестах можно замокать состояние isAuthenticated, чтобы проверить, как работает защита маршрута.

// App.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import App from './App';

test('redirects to login page for unauthenticated user', () => {
  render(
    <MemoryRouter initialEntries={['/protected']}>
      <App isAuthenticated={false} />
    </MemoryRouter>
  );

  expect(screen.getByText(/login page/i)).toBeInTheDocument();
});

В этом тесте мы проверяем, что если пользователь не авторизован, он будет перенаправлен на страницу логина.

Заключение

Тестирование роутинга является важной частью обеспечения стабильности и надежности веб-приложений. Jest и связанные с ним библиотеки, такие как React Testing Library, предоставляют мощные инструменты для проверки корректности маршрутов, динамических переходов и защиты страниц. Важно не только проверить, что маршруты работают корректно, но и протестировать сценарии, такие как неправильные маршруты или ошибки в навигации, чтобы предотвратить проблемы в реальных условиях использования.