Моки и стабы для AOS

Библиотека AOS (Animate on Scroll) позволяет легко добавлять анимации при прокрутке страницы, но при разработке сложных интерфейсов и написании юнит-тестов возникает необходимость отделять визуальные эффекты от логики приложения. Для этого применяются моки и стабы, которые помогают имитировать поведение AOS без фактического запуска анимаций в браузере.

Моки – это объекты или функции, которые подменяют реальную функциональность библиотеки на упрощённую, контролируемую версию. Они используются для проверки того, что методы библиотеки вызываются корректно и в нужное время, без фактической анимации DOM-элементов.

Стабы – более простой вариант мока, представляющий собой заглушку, которая возвращает фиксированное значение или выполняет минимальную операцию вместо оригинальной функции. Стаб позволяет тесту выполняться быстро и предсказуемо, особенно если анимации создают побочные эффекты или зависят от состояния окна и прокрутки.

Инициализация моков и стабов

Для AOS стандартная инициализация выглядит так:

AOS.init({
  duration: 1200,
  once: true,
});

При использовании моков или стабов необходимо подменять метод AOS.init на тестовую версию:

// Стаб функции init
const initStub = jest.fn();
AOS.init = initStub;

// Вызов функции
AOS.init({ duration: 1000 });

// Проверка вызова
expect(initStub).toHaveBeenCalledWith({ duration: 1000 });

Здесь jest.fn() создаёт мок-функцию, которая фиксирует все вызовы, параметры и позволяет контролировать тестируемую логику.

Моки для событий и прокрутки

AOS реагирует на события прокрутки и изменения размера окна, что в обычных условиях сложно контролировать. Для тестирования таких сценариев применяют мокирование событий:

// Стаб для события scroll
window.addEventListener = jest.fn();

// Имитируем вызов обработчика
const scrollHandler = jest.fn();
window.addEventListener.mockImplementation((event, callback) => {
  if (event === 'scroll') {
    scrollHandler();
  }
});

// Генерация события scroll
window.dispatchEvent(new Event('scroll'));

// Проверка вызова
expect(scrollHandler).toHaveBeenCalled();

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

Подмена методов DOM-элементов

AOS активно работает с классами CSS и атрибутами data-aos. Для тестов создаются стабы методов classList.add и classList.remove, а также свойств dataset:

const element = document.createElement('div');
element.classList.add = jest.fn();
element.dataset.aos = 'fade-up';

// Вызов логики AOS
if (element.dataset.aos) {
  element.classList.add('aos-animate');
}

// Проверка вызова
expect(element.classList.add).toHaveBeenCalledWith('aos-animate');

Такой подход позволяет контролировать изменения классов без фактического рендеринга анимаций и обеспечивает стабильность тестов.

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

Для проектов на JavaScript обычно используются Jest, Mocha или Vitest. Моки и стабы AOS легко интегрируются с этими инструментами, обеспечивая контроль:

  • вызова методов AOS.init, AOS.refresh и AOS.refreshHard;
  • реакции на события scroll и resize;
  • добавления и удаления классов у элементов с data-aos.

Пример мокирования всего объекта AOS:

global.AOS = {
  init: jest.fn(),
  refresh: jest.fn(),
  refreshHard: jest.fn(),
};

После этого тесты могут проверять, что все методы вызваны с правильными параметрами и в нужной последовательности.

Тонкости использования моков и стабов

  1. Изоляция тестов – каждый тест должен подменять методы AOS локально, чтобы состояние одного теста не влияло на другой.
  2. Контроль состояния элементов – перед тестом желательно очищать DOM, чтобы атрибуты data-aos не накапливались.
  3. Использование фабрик моков – для больших проектов удобнее создавать функцию, которая возвращает заранее настроенный набор моков и стабов для AOS, минимизируя дублирование кода.
  4. Комбинация с визуальными тестами – моки позволяют проверять логику без анимации, но для проверки визуального эффекта анимации можно использовать скриншот-тестирование.

Практический пример фабрики моков

function createAOSMock() {
  return {
    init: jest.fn(),
    refresh: jest.fn(),
    refreshHard: jest.fn(),
    simulateScroll: function() {
      window.dispatchEvent(new Event('scroll'));
    }
  };
}

const AOSMock = createAOSMock();
global.AOS = AOSMock;

AOS.init({ duration: 500 });
AOSMock.simulateScroll();

expect(AOSMock.init).toHaveBeenCalledWith({ duration: 500 });

Такой подход упрощает повторное использование моков и делает тесты максимально предсказуемыми.

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