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

Unpoly — это JavaScript-библиотека, предназначенная для улучшения UX веб-приложений за счёт динамической подгрузки фрагментов страниц без полной перезагрузки. Она строится на принципах прогрессивного улучшения: если JavaScript отключён, приложение продолжает работать как обычное многостраничное.

В основе работы лежит концепция фрагментов (fragments) и целевых элементов (targets). Фрагменты — это части HTML, которые могут быть динамически обновлены. Целевой элемент — это контейнер, куда будет вставлен новый контент.

up.target('main').render('/posts/42');

В этом примере /posts/42 подгружается в элемент с атрибутом up-target="main".


Навигация и замена контента

Unpoly автоматически обрабатывает ссылки и формы, если они помечены атрибутом up-target или находятся внутри контейнера с этим атрибутом.

Пример ссылки с динамической подгрузкой:

<a href="/posts/42" up-target="main">Читать пост</a>

При клике содержимое <main up-target="main"> будет заменено без полной перезагрузки страницы.

Пример формы с AJAX-подгрузкой:

<form action="/posts" method="post" up-target="main">
  <input type="text" name="title">
  <button type="submit">Создать</button>
</form>

Unpoly перехватывает отправку формы, отправляет данные через AJAX и обновляет указанный фрагмент страницы.


Настройка эффектов анимации

Unpoly поддерживает плавные переходы при подгрузке контента. Для этого используются CSS-классы и опции анимации:

up.render('/posts/42', { fade: true });

Можно определить собственные классы анимации через CSS:

.up-fade-in {
  animation: fadeIn 0.3s ease-out;
}

.up-fade-out {
  animation: fadeOut 0.3s ease-in;
}

Unpoly автоматически применяет их при замене содержимого целевого элемента.


Работа с событиями

Unpoly предоставляет богатый набор событий, которые позволяют интегрировать динамическое поведение:

  • up:fragment:loaded — вызывается после подгрузки нового фрагмента.
  • up:fragment:replaced — вызывается после замены содержимого целевого элемента.
  • up:request:error — вызывается при ошибке AJAX-запроса.
document.addEventListener('up:fragment:loaded', function(event) {
  console.log('Фрагмент загружен:', event.fragment);
});

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


Кэширование и управление историей

Unpoly автоматически управляет историей браузера. При подгрузке фрагмента URL изменяется с помощью pushState, а нажатие кнопки “Назад” восстанавливает предыдущий контент.

Можно контролировать кэширование с помощью опций cache и stale:

up.render('/posts', { cache: 'reload' });
  • cache: 'reload' — всегда запрашивать свежие данные.
  • cache: 'prefer' — использовать кэш, если фрагмент уже загружен.

Интеграция с Rails и другими фреймворками

Unpoly легко интегрируется с серверными фреймворками, поддерживая стандартные маршруты и форматы ответа.

Пример ответа сервера:

<div up-target="main">
  <h1><%= @post.title %></h1>
  <p><%= @post.body %></p>
</div>

Важно возвращать HTML-фрагмент, соответствующий указанному up-target. Если фреймворк возвращает JSON, необходимо использовать up.render с обработкой ответа.


Расширенные возможности

Фрагменты с приоритетом

Unpoly позволяет загружать несколько фрагментов одновременно и управлять их приоритетом:

up.render({
  '#sidebar': '/sidebar',
  '#content': '/posts/42'
});

Это удобно для сложных страниц с несколькими зонами обновления.

Обработка ошибок

При ошибках можно показать специальный фрагмент или выполнить перенаправление:

up.on('up:request:error', function(event) {
  up.render('/errors/500', { target: '#main' });
});

Интеграция с формами и валидацией

Unpoly поддерживает серверную и клиентскую валидацию форм. Ошибки можно отображать в виде отдельных фрагментов:

<div id="form-errors" up-target="errors"></div>
<form action="/posts" method="post" up-target="main" up-error-target="#form-errors">
  ...
</form>

При ошибке сервер возвращает HTML для #form-errors, а Unpoly автоматически вставляет его на страницу.


Практические рекомендации

  • Всегда использовать up-target для указания контейнера, чтобы избежать непреднамеренного обновления всей страницы.
  • Использовать события up:fragment:loaded и up:fragment:replaced для инициализации динамических элементов после подгрузки.
  • Планировать структуру фрагментов так, чтобы каждый из них был независимым и содержал минимально необходимый HTML.
  • Контролировать кэширование при частых изменениях данных, чтобы избежать отображения устаревшей информации.
  • При работе с формами использовать up-error-target для аккуратного отображения ошибок, не перегружая основной контент.

Unpoly объединяет преимущества классического многостраничного приложения и современных SPA, обеспечивая быструю, плавную работу интерфейса при минимальной сложности интеграции с серверной логикой.