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

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


Основные концепции

Моки (mock) — это объекты или функции, имитирующие поведение реальных компонентов. В контексте DOM это могут быть:

  • Элементы, созданные в памяти, на которые можно навешивать обработчики событий;
  • Функции, имитирующие методы DOM-элементов, такие как click(), val(), html().

Стабы (stub) — более узкая концепция: это заранее определённые заглушки для методов, которые всегда возвращают фиксированные значения. Например, метод .val() может всегда возвращать "тест" для проверки логики функции.

Использование моков и стабов особенно актуально при юнит-тестировании функций, где требуется:

  • Проверка манипуляций с классами и атрибутами элементов;
  • Проверка событийной логики;
  • Тестирование методов выборки элементов.

Создание и использование DOM-моков

Cash работает с обычными HTML-элементами, поэтому можно создавать элементы в памяти:

// Создание элемента для теста
const div = document.createElement('div');
div.id = 'test-div';
div.className = 'box';
div.textContent = 'Пример';

// Превращение в объект Cash
const $div = cash(div);

// Проверка добавления класса
$div.addClass('active');
console.log(div.className); // 'box active'

Важная особенность: Cash методы возвращают объекты Cash, что позволяет строить цепочки методов, как в jQuery.


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

События можно имитировать с помощью функций-заглушек. Cash предоставляет метод .trigger():

const $button = cash('<button>Click me</button>');

// Создание мока обработчика
let clicked = false;
function mockHandler() {
    clicked = true;
}

$button.on('click', mockHandler);

// Триггер события
$button.trigger('click');

console.log(clicked); // true

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


Стабы методов Cash

Методы Cash можно заменять на стабы для тестирования:

const $input = cash('<input value=""/>');

// Создание стаба для val()
$input.val = () => 'заглушка';

console.log($input.val()); // 'заглушка'

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


Комбинация моков и стабов

Часто используется сочетание для комплексного тестирования:

const $div = cash('<div></div>');

// Стаб метода html
$div.html = () => '<span>Стаб</span>';

// Мок события
let triggered = false;
$div.on('custom', () => triggered = true);

// Проверка работы
console.log($div.html()); // '<span>Стаб</span>'
$div.trigger('custom');
console.log(triggered); // true

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


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

  1. Создавать элементы в памяти вместо модификации реального DOM.
  2. Навешивать обработчики на объекты Cash, а не напрямую на DOM, чтобы проверять цепочки методов.
  3. Использовать стабы для методов, возвращающих данные с внешних источников, таких как val(), html(), attr().
  4. Использовать .trigger() для имитации событий, что позволяет тестировать как стандартные события (click, input), так и кастомные.
  5. Изолировать тесты: каждый тест должен создавать свои объекты Cash, чтобы состояние одного теста не влияло на другой.

Особенности работы с Cash

  • Методы, изменяющие DOM, возвращают объект Cash, что облегчает цепочные вызовы.
  • Cash поддерживает стандартные селекторы CSS, поэтому моки можно комбинировать с выборкой элементов:
const $list = cash('<ul><li>1</li><li>2</li></ul>');
const $item = $list.find('li').eq(1); // второй элемент
console.log($item.text()); // '2'
  • События в Cash имеют поддержку делегирования, что позволяет тестировать сложные сценарии с потомками и родительскими элементами.

Примеры типовых тестов

Проверка добавления класса по событию:

const $div = cash('<div></div>');

$div.on('mouseover', () => $div.addClass('hovered'));
$div.trigger('mouseover');

console.log($div.hasClass('hovered')); // true

Проверка изменения значения input через стабы:

const $input = cash('<input value=""/>');

$input.val = () => 'тест';
console.log($input.val()); // 'тест'

Тестирование цепочки методов:

const $div = cash('<div></div>');

$div.addClass('a').addClass('b').attr('data-test', 'ok');
console.log($div[0].className); // 'a b'
console.log($div.attr('data-test')); // 'ok'

Заключение по практике моков и стабов

Использование моков и стабов с Cash позволяет создавать чистые, изолированные тесты, минимизируя влияние реального DOM. Это особенно важно при проверке функций с цепочками вызовов, событийной логикой и манипуляциями с атрибутами, классами и значениями элементов. Такой подход делает тесты надёжными, повторяемыми и независимыми от браузерной среды.