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

Unpoly — это библиотека для создания динамических веб-интерфейсов без полного перезагрузки страниц. Она предоставляет удобные методы для обновления части страницы через AJAX, поддерживает навигацию по истории браузера и управление формами. При написании E2E (End-to-End) тестов важно учитывать, как Unpoly управляет DOM и событиями, чтобы тесты корректно имитировали поведение реального пользователя.

Навигация и асинхронные обновления

Unpoly использует AJAX для подгрузки содержимого. Любой клик по элементу с атрибутом up-target или up-link инициирует асинхронный запрос. В E2E тестах необходимо дожидаться завершения этих обновлений перед проверкой состояния DOM. Например, при использовании Cypress или Playwright следует использовать команды ожидания (wait, expect(...).to.exist) для элементов, которые появляются после обновления:

cy.get('a[up-link]').click();
cy.get('#content').should('contain', 'Новый текст');

up-target указывает, какую часть страницы обновлять. При тестировании важно проверять не весь DOM, а именно тот контейнер, который ожидается. Это ускоряет тесты и делает их более стабильными.

Обработка форм

Unpoly предоставляет расширенные возможности работы с формами через атрибуты up-submit и up-target. Формы отправляются асинхронно, и сервер может вернуть как новый HTML, так и JSON. В E2E тестах нужно учитывать следующее:

  • После up-submit форма может быть заменена новым контентом.
  • Ошибки валидации чаще всего возвращаются в HTML с добавлением классов up-error или up-invalid.
  • Для проверки успешной отправки следует дожидаться обновления целевого контейнера:
cy.get('form[up-submit]').submit();
cy.get('#messages').should('contain', 'Форма успешно отправлена');

Использование up-on позволяет отслеживать события, такие как up:success, up:fail и up:layer:opened. В тестах можно подписываться на эти события и проверять правильность их срабатывания:

cy.window().then(win => {
  win.document.addEventListener('up:success', () => {
    cy.get('#status').should('contain', 'Успешно');
  });
});

Работа с слоями и модальными окнами

Unpoly поддерживает слои (up-layer) и модальные окна. Для E2E тестирования это требует контроля появления и исчезновения элементов:

  • Открытие слоя через up-target или up-layer создаёт отдельный DOM-контейнер. Проверки нужно делать именно в этом контейнере.
  • Закрытие слоя можно отслеживать через события up:layer:closed.
  • В тестах важно дожидаться анимации открытия или закрытия, иначе проверки могут выполняться преждевременно.

Пример проверки модального окна:

cy.get('button[up-layer]').click();
cy.get('.up-layer').should('be.visible');
cy.get('.up-layer button.close').click();
cy.get('.up-layer').should('not.exist');

Навигация по истории

Unpoly интегрируется с историей браузера. При E2E тестировании следует учитывать, что window.history.back() и window.history.forward() корректно восстанавливают состояние слоёв и контейнеров. Это особенно важно при многоуровневой навигации и использовании up-history.

Пример теста возврата назад:

cy.get('a[up-link]').click();
cy.get('#content').should('contain', 'Страница 2');
cy.go('back');
cy.get('#content').should('contain', 'Страница 1');

Синхронизация тестов с Unpoly

Проблемой при E2E тестировании может стать асинхронность обновлений. Unpoly предоставляет глобальные события up:framework:ready, up:framework:idle, которые сигнализируют о завершении всех обновлений на странице. Их использование позволяет писать стабильные тесты без искусственных таймаутов:

cy.window().then(win => {
  return new Cypress.Promise(resolve => {
    win.document.addEventListener('up:framework:idle', resolve, { once: true });
  });
});
cy.get('#content').should('contain', 'Обновление завершено');

Рекомендации по написанию E2E тестов

  • Всегда использовать селекторы для целевых контейнеров (up-target), а не для глобального DOM.
  • Проверять асинхронные обновления через события Unpoly, а не через setTimeout.
  • Тестировать обработку ошибок форм и модальных окон отдельно.
  • При работе с историями браузера убедиться в правильном восстановлении состояния контейнеров.

Заключение по подходу

E2E тестирование с Unpoly требует внимания к асинхронной природе обновлений и особенностям слоёв, форм и навигации. События фреймворка и таргетированные проверки позволяют создавать стабильные и детальные тесты, полностью покрывающие пользовательские сценарии.