E2E тестирование

Для начала необходимо подключить библиотеку Navigo. В современных проектах на основе модулей ES6 это делается через npm:

npm install navigo

Или с помощью подключения через CDN в браузере:

<script src="https://unpkg.com/navigo@8.11.1/lib/navigo.min.js"></script>

После подключения создаётся экземпляр роутера:

import Navigo from 'navigo';

const router = new Navigo('/', { hash: true });

Здесь первый аргумент указывает базовый путь, второй — конфигурацию. Опция hash: true позволяет использовать хеш-маршруты (#/home) вместо стандартного HTML5 History API.


Определение маршрутов

Маршруты задаются с помощью метода .on(). Navigo поддерживает статические маршруты, динамические сегменты и регулярные выражения.

router
  .on('/', () => {
    console.log('Главная страница');
  })
  .on('/about', () => {
    console.log('О проекте');
  })
  .on('/user/:id', (params) => {
    console.log(`Пользователь с ID: ${params.id}`);
  })
  .resolve();

Ключевые моменты:

  • :id — динамический сегмент, доступный через объект params.
  • .resolve() — запускает роутер и проверяет текущий URL.

Навигация между маршрутами

Для программной навигации используется метод router.navigate():

router.navigate('/about');

При этом вызывается соответствующий обработчик маршрута. Это позволяет реализовать SPA без перезагрузки страницы.


Поддержка перехвата несуществующих маршрутов

Navigo предоставляет метод .notFound() для обработки неизвестных URL:

router.notFound(() => {
  console.log('Страница не найдена');
});

Использование хуков перед маршрутизацией

Методы .before() и .hooks() позволяют выполнять действия до и после срабатывания маршрута:

router.before((done, params, route) => {
  console.log(`Переход на маршрут: ${route.url}`);
  done(); // необходимо вызвать для продолжения навигации
});
  • done() обязателен для продолжения навигации.
  • Можно использовать для проверки авторизации, подгрузки данных или логирования.

Динамическая генерация маршрутов

Маршруты могут создаваться динамически на основе данных:

const pages = ['home', 'about', 'contact'];

pages.forEach(page => {
  router.on(`/${page}`, () => {
    console.log(`Открыта страница: ${page}`);
  });
});

Это упрощает поддержку большого количества однотипных маршрутов.


E2E тестирование с Navigo

При тестировании SPA важно проверять правильность маршрутов без реальной перезагрузки страницы. Для этого в E2E тестах можно использовать:

  • Cypress
  • Playwright
  • Puppeteer

Проверка переходов по маршрутам

В Cypress пример проверки маршрутов с Navigo может выглядеть так:

describe('Тестирование маршрутов', () => {
  beforeEach(() => {
    cy.visit('/');
  });

  it('Переход на About', () => {
    cy.window().then(win => {
      win.router.navigate('/about');
    });
    cy.contains('О проекте').should('be.visible');
  });

  it('Проверка динамического маршрута', () => {
    cy.window().then(win => {
      win.router.navigate('/user/42');
    });
    cy.contains('Пользователь с ID: 42').should('be.visible');
  });
});
  • cy.window() позволяет получить доступ к объекту router.
  • Проверяются как статические, так и динамические маршруты.
  • Метод .should('be.visible') проверяет корректный рендер контента после навигации.

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

it('Несуществующий маршрут', () => {
  cy.window().then(win => {
    win.router.navigate('/nonexistent');
  });
  cy.contains('Страница не найдена').should('be.visible');
});

Проверка хуков

Для тестирования хуков можно использовать заглушки (spy) для функции before:

it('Вызывается before хук', () => {
  cy.window().then(win => {
    const spy = cy.spy();
    win.router.before(spy);
    win.router.navigate('/about');
    expect(spy).to.have.been.called;
  });
});

Особенности тестирования SPA с Navigo

  1. Изоляция маршрутов: Для E2E тестов важно, чтобы каждый тест начинался с определённого состояния приложения (cy.visit('/')).
  2. Контроль асинхронных операций: Если в хуках происходит асинхронная загрузка данных, необходимо использовать done() или промисы.
  3. Доступ к внутреннему роутеру: Для интеграции с тестами удобно экспортировать объект router из модуля приложения.

Работа с HTML5 History API

Navigo может использовать pushState без хеша:

const router = new Navigo('/', { hash: false });
  • В этом случае сервер должен быть настроен на отдачу одного HTML файла для всех маршрутов SPA.
  • Позволяет корректно тестировать URL в браузере без хешей, что ближе к реальному поведению продакшн-приложения.

Рекомендации по структуре кода

  • Разделять объявление маршрутов и логику рендеринга.
  • Для больших приложений динамически импортировать модули по маршрутам (import()).
  • Использовать хуки для авторизации, логирования и загрузки данных, что упрощает тестирование и покрытие E2E.

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