Юнит-тестирование waypoints

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

Установка и настройка среды тестирования

Для тестирования Waypoints чаще всего используют сочетание следующих инструментов:

  • Jest — современный фреймворк для юнит-тестов в JavaScript.
  • jsdom — виртуальное DOM-окружение, необходимое для симуляции браузерного поведения.

Пример установки через npm:

npm install --save-dev jest jsdom

Waypoints напрямую зависит от наличия DOM-элементов, поэтому тестовая среда должна имитировать поведение окна и документа браузера. Настройка jsdom обычно происходит автоматически через Jest, но при необходимости можно явно указать окружение в конфигурации:

{
  "testEnvironment": "jsdom"
}

Создание тестируемой структуры DOM

Для корректного юнит-тестирования необходимо подготовить эмуляцию HTML, которая включает элементы, на которые будут навешиваться Waypoints:

document.body.innerHTML = `
  <div style="height: 2000px;">
    <div id="target" style="margin-top: 500px; height: 100px;">Waypoint Target</div>
  </div>
`;

Важные моменты:

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

Инициализация Waypoints в тестах

Waypoints создаются через конструктор Waypoint и требует объект с конфигурацией:

const waypoint = new Waypoint({
  element: document.getElementById('target'),
  handler: jest.fn(), // используем jest.fn() для отслеживания вызовов
  offset: '50%' // срабатывание в середине окна
});

Ключевые свойства:

  • element — целевой DOM-элемент.
  • handler — функция, вызываемая при срабатывании.
  • offset — смещение, при котором происходит активация.

Использование jest.fn() позволяет проверять, был ли вызван обработчик, сколько раз и с какими аргументами.

Симуляция прокрутки и событий

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

window.scrollTo(0, 600); // прокрутка страницы
window.dispatchEvent(new Event('scroll')); // имитация события scroll

После этого можно проверить вызов обработчика:

expect(waypoint.handler).toHaveBeenCalled();

Если требуется протестировать многоступенчатые события (например, активация при входе и выходе элемента), следует учитывать направление прокрутки:

const handler = jest.fn();
const waypoint = new Waypoint({
  element: document.getElementById('target'),
  handler: handler,
  offset: '50%'
});

window.scrollTo(0, 600);
window.dispatchEvent(new Event('scroll'));
expect(handler).toHaveBeenCalledTimes(1);

window.scrollTo(0, 400);
window.dispatchEvent(new Event('scroll'));
expect(handler).toHaveBeenCalledTimes(2);

Тестирование динамических элементов

Если элементы добавляются на страницу динамически после инициализации, Waypoints необходимо реинициализировать. В тестах это проверяется через манипуляции DOM:

const container = document.createElement('div');
container.id = 'dynamic-container';
document.body.appendChild(container);

const newElement = document.createElement('div');
newElement.id = 'new-target';
newElement.style.height = '100px';
container.appendChild(newElement);

const waypoint = new Waypoint({
  element: newElement,
  handler: jest.fn(),
  offset: '50%'
});

window.scrollTo(0, 500);
window.dispatchEvent(new Event('scroll'));
expect(waypoint.handler).toHaveBeenCalled();

Проверка свойств Waypoints

Waypoints предоставляет доступ к ряду внутренних свойств, которые можно использовать для валидации в тестах:

  • waypoint.element — проверка корректности привязанного элемента.
  • waypoint.offset — проверка смещения активации.
  • waypoint.enabled — состояние точки (включена/выключена).

Пример проверки состояния:

expect(waypoint.element.id).toBe('new-target');
expect(waypoint.offset).toBe('50%');
expect(waypoint.enabled).toBe(true);

Организация тестов

Для поддерживаемости рекомендуется:

  1. Изолировать каждый тест — создавать новый DOM и новый Waypoint для каждого сценария.
  2. Использовать мок-функции для проверки вызова обработчиков.
  3. Тестировать разные комбинации offset и направления прокрутки, чтобы убедиться в корректной работе.
  4. Проверять очистку и удаление Waypoints, если элементы удаляются из DOM.

Пример полного тестового сценария

describe('Waypoints Unit Tests', () => {
  let handler;
  let waypoint;

  beforeEach(() => {
    document.body.innerHTML = `
      <div style="height: 2000px;">
        <div id="target" style="margin-top: 500px; height: 100px;"></div>
      </div>
    `;
    handler = jest.fn();
    waypoint = new Waypoint({
      element: document.getElementById('target'),
      handler: handler,
      offset: '50%'
    });
  });

  test('Handler is called on scroll past waypoint', () => {
    window.scrollTo(0, 600);
    window.dispatchEvent(new Event('scroll'));
    expect(handler).toHaveBeenCalled();
  });

  test('Handler is not called before reaching waypoint', () => {
    window.scrollTo(0, 400);
    window.dispatchEvent(new Event('scroll'));
    expect(handler).not.toHaveBeenCalled();
  });
});

Такой подход обеспечивает полное покрытие юнит-тестами поведения Waypoints, проверку корректного срабатывания, динамических изменений DOM и управления состоянием точек.