Модульное тестирование роутов

Navigo — это лёгкий роутер для JavaScript, позволяющий организовать маршрутизацию в одностраничных приложениях (SPA). Модульное тестирование роутов в Navigo позволяет проверить корректность навигации, обработку параметров URL и вызовы соответствующих обработчиков, не запуская весь браузерный контекст.

Тестирование роутов состоит из нескольких ключевых элементов:

  1. Инициализация роутера Для тестирования создаётся экземпляр Navigo с указанием базового пути (root) и конфигурации:
import Navigo from 'navigo';

const router = new Navigo('/', { hash: false });
  • root — корневой путь приложения, относительно которого строятся все маршруты.
  • hash — если установлено в true, роутер использует хеш-навигацию (/#/home) вместо стандартного HTML5 history API.
  1. Определение маршрутов Навигационные маршруты должны быть определены через метод on:
router.on({
  '/home': () => console.log('Home page'),
  '/about': () => console.log('About page'),
  '/product/:id': (params) => console.log(`Product ID: ${params.id}`)
});
  • Параметры маршрута (:id) автоматически передаются в функцию-обработчик.
  • Для тестов важно убедиться, что все возможные пути корректно обрабатываются.
  1. Подмена обработчиков для тестирования В тестах рекомендуется не использовать реальную логику отображения, а заменять обработчики на mock-функции:
const homeHandler = jest.fn();
const aboutHandler = jest.fn();
const productHandler = jest.fn();

router.on({
  '/home': homeHandler,
  '/about': aboutHandler,
  '/product/:id': productHandler
});
  • Использование jest.fn() (или аналогов в других тестовых фреймворках) позволяет проверять вызовы обработчиков и передаваемые параметры.
  1. Имитирование навигации В модульных тестах можно программно вызвать метод navigate:
router.navigate('/home');
expect(homeHandler).toHaveBeenCalled();

router.navigate('/product/42');
expect(productHandler).toHaveBeenCalledWith({ id: '42' });
  • Метод navigate вызывает соответствующий маршрут так же, как если бы пользователь перешёл по URL.
  • Проверка параметров гарантирует корректную работу динамических маршрутов.
  1. Тестирование fallback-маршрутов Navigo поддерживает обработку неизвестных маршрутов через метод notFound:
const notFoundHandler = jest.fn();
router.notFound(notFoundHandler);

router.navigate('/unknown');
expect(notFoundHandler).toHaveBeenCalled();
  • Это позволяет гарантировать, что приложение не ломается при переходе на несуществующие URL.
  1. Проверка редиректов Роутер может выполнять редиректы через метод resolve:
router.on('/old', () => router.navigate('/new'));
const newHandler = jest.fn();
router.on('/new', newHandler);

router.navigate('/old');
expect(newHandler).toHaveBeenCalled();
  • Модульные тесты помогают убедиться, что логика перенаправления срабатывает корректно.
  1. Изоляция тестовой среды Для стабильности тестов желательно:
  • Использовать отдельный экземпляр Navigo для каждого теста.
  • Очищать mock-функции перед каждым запуском (jest.clearAllMocks()).
  • Избегать зависимости от window.location напрямую, использовать методы роутера.
  1. Комбинированные маршруты и группы Navigo позволяет группировать маршруты с общим префиксом:
router.on('/admin/*', () => console.log('Admin area'));
  • Тестирование таких маршрутов включает проверку wildcard-путей.
  • Можно проверять, что маршруты внутри группы вызывают правильные обработчики.
  1. Советы по организации тестов
  • Разделять тесты по сценариям: статические маршруты, динамические параметры, fallback, редиректы.
  • Использовать мок-объекты для компонентов, вызываемых внутри обработчиков.
  • Проверять корректность вызова обработчиков с правильными параметрами и контекстом (this при необходимости).
  1. Пример комплексного теста
describe('Router Navigo', () => {
  let router;
  let homeHandler, productHandler, notFoundHandler;

  beforeEach(() => {
    homeHandler = jest.fn();
    productHandler = jest.fn();
    notFoundHandler = jest.fn();
    router = new Navigo('/');
    router.on({
      '/home': homeHandler,
      '/product/:id': productHandler
    });
    router.notFound(notFoundHandler);
  });

  test('should call home handler', () => {
    router.navigate('/home');
    expect(homeHandler).toHaveBeenCalled();
  });

  test('should pass params to product handler', () => {
    router.navigate('/product/99');
    expect(productHandler).toHaveBeenCalledWith({ id: '99' });
  });

  test('should call notFound handler for unknown route', () => {
    router.navigate('/unknown');
    expect(notFoundHandler).toHaveBeenCalled();
  });
});
  • Такой подход позволяет полностью покрыть маршруты приложения модульными тестами без реального рендеринга страниц.
  • Обеспечивается высокая надёжность навигации и возможность безопасного рефакторинга роутов.

Модульное тестирование с Navigo минимизирует ошибки маршрутизации и гарантирует, что логика переходов работает в любых условиях, сохраняя динамику SPA и корректную обработку URL.