Open WC Testing

Haunted — это библиотека для создания веб-компонентов на основе функционального подхода в JavaScript, вдохновлённая React-хуками. Она позволяет описывать поведение компонентов с помощью функций и легко управлять состоянием и эффектами. Для обеспечения качества кода и корректной работы компонентов важно использовать автоматизированное тестирование. Open WC Testing предоставляет набор инструментов для тестирования веб-компонентов, включая поддержку Haunted.


Настройка окружения

Для начала необходимо установить базовые пакеты:

npm install haunted lit @open-wc/testing mocha chai
  • haunted — библиотека функциональных веб-компонентов.
  • lit — необходима для рендеринга шаблонов (Lit-html используется Haunted для работы с шаблонами).
  • @open-wc/testing — набор утилит для тестирования веб-компонентов.
  • mocha и chai — фреймворк для запуска тестов и библиотека для ассертов.

Настройка package.json для тестирования:

"scripts": {
  "test": "mocha --require @babel/register 'test/**/*.test.js'"
}

При использовании современных синтаксисов ES6/ESM важно настроить транспиляцию через Babel.


Структура теста Haunted-компонента

Простейший тест компонента включает:

  1. Импорт функций Haunted и утилит Open WC Testing.
  2. Определение компонента.
  3. Рендеринг компонента в тестовую среду.
  4. Проверку состояния или DOM.

Пример:

import { html, render } from 'haunted';
import { fixture, expect } from '@open-wc/testing';
import { component } from 'haunted';

function counter({ initial = 0 } = {}) {
  const [count, setCount] = useState(initial);
  return html`
    <div>
      <span>${count}</span>
      <button @click=${() => setCount(count + 1)}>Increment</button>
    </div>
  `;
}

customElements.define('my-counter', component(counter));

describe('my-counter', () => {
  it('отображает начальное значение', async () => {
    const el = await fixture(html`<my-counter></my-counter>`);
    const span = el.shadowRoot.querySelector('span');
    expect(span.textContent).to.equal('0');
  });

  it('увеличивает значение по клику', async () => {
    const el = await fixture(html`<my-counter></my-counter>`);
    const button = el.shadowRoot.querySelector('button');
    button.click();
    await el.updateComplete;
    const span = el.shadowRoot.querySelector('span');
    expect(span.textContent).to.equal('1');
  });
});

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

  • fixture создаёт компонент в DOM и возвращает его для тестирования.
  • expect позволяет писать читаемые проверки состояния.
  • Для Haunted-компонентов важно учитывать асинхронное обновление DOM, поэтому часто используют await el.updateComplete или аналогичные методы.

Работа с хуками в тестах

Haunted активно использует хуки (useState, useEffect, useReducer). При тестировании хуков следует учитывать следующие особенности:

  • useState требует перерендеринга компонента для проверки нового состояния.
  • useEffect выполняется после рендера, поэтому тесты должны ожидать асинхронного завершения.

Пример проверки эффекта:

function messageUpdater() {
  const [msg, setMsg] = useState('Hello');
  useEffect(() => {
    const timer = setTimeout(() => setMsg('Updated'), 100);
    return () => clearTimeout(timer);
  }, []);
  return html`<span>${msg}</span>`;
}

customElements.define('message-updater', component(messageUpdater));

it('обновляет сообщение после таймера', async () => {
  const el = await fixture(html`<message-updater></message-updater>`);
  await new Promise(r => setTimeout(r, 120));
  const span = el.shadowRoot.querySelector('span');
  expect(span.textContent).to.equal('Updated');
});

Моки и слежение за событиями

Haunted-компоненты часто генерируют кастомные события. Open WC Testing позволяет легко отслеживать их:

it('вызывает событие при клике', async () => {
  const el = await fixture(html`<my-counter></my-counter>`);
  const spy = sinon.spy();
  el.addEventListener('increment', spy);
  const button = el.shadowRoot.querySelector('button');
  button.click();
  expect(spy).to.have.been.calledOnce;
});
  • Использование sinon для создания шпионов упрощает проверку событий.
  • События можно кастомизировать через dispatchEvent внутри Haunted-компонента.

Тестирование стилей и рендеринга

Open WC Testing поддерживает проверку CSS и структуры DOM. Для Haunted важно:

  • Проверять shadow DOM через el.shadowRoot.
  • Использовать селекторы CSS для поиска элементов и проверки их стилей.

Пример:

it('имеет красный текст', async () => {
  const el = await fixture(html`<my-counter></my-counter>`);
  const span = el.shadowRoot.querySelector('span');
  const color = getComputedStyle(span).color;
  expect(color).to.equal('rgb(255, 0, 0)');
});

Интеграция с CI/CD

Для автоматизации тестов Haunted-компонентов:

  1. Настроить скрипт npm test для запуска тестов.
  2. Включить Mocha и Open WC Testing в pipeline.
  3. Использовать headless-браузеры (puppeteer или playwright) для эмуляции DOM в CI.

Пример конфигурации с Puppeteer:

import { setUpPage } from '@open-wc/testing-helpers';
import puppeteer from 'puppeteer';

before(async () => {
  global.page = await puppeteer.launch({ headless: true });
  global.document = await setUpPage(global.page);
});

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


Полезные рекомендации

  • Разделять тесты по функциональности компонентов и хукам.
  • Использовать асинхронные функции и await для стабильных тестов.
  • Shadow DOM требует точного доступа через shadowRoot.
  • Для событий и колбэков применять шпионы (sinon.spy).
  • Автоматизировать тесты с использованием headless-браузеров для CI/CD.

Тщательное тестирование с Open WC Testing обеспечивает корректную работу функциональных веб-компонентов Haunted и минимизирует баги при изменении логики.