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

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

Архитектура Hyperapp и её влияние на тестирование

Hyperapp строится вокруг централизованного состояния (state) и действий (actions). Все изменения UI проходят через эти структуры, что упрощает создание интеграционных тестов. Основные элементы, на которые ориентируются при интеграционном тестировании:

  • State — глобальное состояние приложения.
  • Actions — функции, изменяющие состояние.
  • View — чистая функция, отображающая состояние.
  • Effects — побочные эффекты, такие как HTTP-запросы или локальное хранилище.

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

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

Для интеграционных тестов Hyperapp используют следующие библиотеки:

  • Jest — тестовый раннер и фреймворк с возможностью мокирования функций.
  • Testing Library / DOM Testing Library — проверка взаимодействий с DOM.
  • jsdom — имитация браузерного DOM в Node.js.

Комбинация этих инструментов позволяет создавать тесты, охватывающие как внутреннюю логику приложения, так и отображение UI.

Структура интеграционного теста

  1. Инициализация состояния Перед тестом создаётся стартовое состояние приложения. Например:
import { app } from "hyperapp";

const initState = {
  counter: 0
};

const increment = state => ({ counter: state.counter + 1 });
  1. Рендеринг приложения Используется виртуальный DOM Hyperapp:
const view = state => (
  <div>
    <p id="count">{state.counter}</p>
    <button oncl ick={increment}>+</button>
  </div>
);

const mainApp = app({ init: initState, view, node: document.body, actions: { increment } });
  1. Выполнение действий и проверка состояния Тест проверяет, что определённые действия корректно изменяют состояние и UI:
test("increment button increases counter", () => {
  const button = document.querySelector("button");
  const countDisplay = document.getElementById("count");

  button.click();

  expect(countDisplay.textContent).toBe("1");
});

Тестирование эффектов

Эффекты в Hyperapp — это асинхронные операции, такие как API-запросы. Их интеграционные тесты включают мокирование:

const fetchData = () => async (state, actions) => {
  const response = await fetch("/data");
  const data = await response.json();
  return { ...state, data };
};

// Тест с мокированием fetch
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ items: [1, 2, 3] })
  })
);

test("fetchData effect updates state", async () => {
  let state = { data: [] };
  const actions = { fetchData };

  state = await actions.fetchData()(state, actions);

  expect(state.data.items.length).toBe(3);
});

Организация комплексных сценариев

Интеграционное тестирование в Hyperapp часто требует проверки цепочек действий:

  1. Пользователь кликает кнопку → изменяется состояние.
  2. Состояние вызывает эффект → обновляется UI.
  3. UI отображает корректные данные.

Пример цепочки:

const addItem = (state, actions, item) => ({ items: [...state.items, item] });

const view = state => (
  <div>
    <ul>
      {state.items.map(i => <li>{i}</li>)}
    </ul>
    <button oncl ick={() => addItem(state, null, "Task 1")}>Add</button>
  </div>
);

Тест проверяет добавление элемента в список и рендер нового <li>:

test("adding item updates list", () => {
  const button = document.querySelector("button");
  button.click();
  const listItems = document.querySelectorAll("li");
  expect(listItems.length).toBe(1);
  expect(listItems[0].textContent).toBe("Task 1");
});

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

  • Изолировать состояние между тестами, создавая новый экземпляр приложения для каждого сценария.
  • Мокировать эффекты, чтобы избежать зависимости от внешних сервисов.
  • Тестировать пользовательские сценарии, а не отдельные функции.
  • Использовать селекторы по id или data-атрибутам для стабильного поиска элементов в DOM.

Преимущества подхода

  • Все изменения состояния проходят через действия, что обеспечивает единый источник правды.
  • Виртуальный DOM Hyperapp позволяет проверять отображение без запуска полноценного браузера.
  • Модульность компонентов облегчает создание повторно используемых тестовых сценариев.

Интеграционное тестирование в Hyperapp становится мощным инструментом для проверки сложных взаимодействий компонентов, асинхронных эффектов и корректного рендера пользовательского интерфейса. Оно обеспечивает уверенность в том, что приложение работает целостно, а не только по отдельным блокам кода.