В Popper.js управление положением всплывающих элементов (popper) тесно связано с использованием моков (mocks) и стабов (stubs) при тестировании. Эти инструменты позволяют изолировать поведение элементов, проверить алгоритмы вычисления позиций и обеспечить корректное взаимодействие popper с reference-элементом без необходимости реально рендерить DOM.
Мок — это объект, имитирующий поведение реального элемента или функции. В контексте Popper.js моки часто применяются для:
reference или
popper) при юнит-тестах.resize или
scroll.placement и
offset.Пример создания мока reference-элемента:
const referenceMock = {
getBoundingClientRect: jest.fn(() => ({
width: 100,
height: 50,
top: 200,
left: 300,
right: 400,
bottom: 250,
})),
clientWidth: 100,
clientHeight: 50,
};
Здесь метод getBoundingClientRect возвращает заранее
определённые размеры и координаты. Это позволяет тестировать функции
Popper.js, которые зависят от положения reference, не создавая реальный
DOM.
Моки также полезны при проверке модификаторов (modifiers). Например,
offset можно протестировать без фактического изменения
позиции в браузере:
const popperInstance = createPopper(referenceMock, popperMock, {
placement: 'top',
modifiers: [
{
name: 'offset',
options: {
offset: [0, 10],
},
},
],
});
popperInstance.update();
expect(popperInstance.state.modifiersData.offset).toEqual({ x: 0, y: 10 });
Стаб — это объект или функция, заменяющая часть кода с целью контролировать её поведение. В отличие от моков, стабы чаще используют для контроля внутренних зависимостей Popper.js, а не имитации внешнего API.
Пример стаба модификатора:
const flipStub = jest.fn(({ state, options }) => {
state.placement = 'bottom';
return state;
});
const popperInstance = createPopper(referenceMock, popperMock, {
placement: 'top',
modifiers: [
{
name: 'flip',
enabled: true,
phase: 'main',
fn: flipStub,
},
],
});
popperInstance.update();
expect(flipStub).toHaveBeenCalled();
expect(popperInstance.state.placement).toBe('bottom');
Стабы позволяют:
flip,
preventOverflow, arrow).| Характеристика | Мок | Стаб |
|---|---|---|
| Назначение | Имитировать внешний объект или API | Подменять внутреннюю функцию или модуль |
| Контроль поведения | Возвращает заранее заданные значения | Управляет тем, как функция себя ведёт |
| Использование | Юнит-тестирование элементов DOM | Юнит-тестирование модификаторов и логики Popper |
| Примеры в Popper.js | reference, popper, events | flip, offset, preventOverflow |
Использовать моки для reference и popper Это позволяет полностью контролировать их размеры и позицию без рендеринга страницы.
Стабы для модификаторов Если нужно проверить корректность вызова или изменения состояния, стабы обеспечивают точный контроль.
Комбинировать моки и стабы Для комплексного тестирования можно одновременно использовать моки для DOM и стабы для модификаторов. Это позволяет проверять полное поведение Popper.js в изоляции.
Проверка фаз модификаторов Popper.js выполняет
модификаторы в фазах read, main,
write. Стабы позволяют проверить, что модификатор
срабатывает именно в нужной фазе:
expect(flipStub.mock.calls[0][0].phase).toBe('main');
const stateBefore = popperInstance.state.placement;
popperInstance.update();
const stateAfter = popperInstance.state.placement;
expect(stateBefore).not.toBe(stateAfter);
Моки и стабы позволяют строить надёжные тесты Popper.js без зависимости от визуального рендеринга, делая процесс проверки быстрым и предсказуемым.
window.dispatchEvent(new Event('scroll'));
const computeStylesStub = jest.spyOn(popperInstance.modifiersData, 'computeStyles').mockImplementation(() => {
return { x: 10, y: 20 };
});
popperInstance.update();
expect(popperInstance.state.placement).toBe('bottom');
expect(popperInstance.state.modifiersData.offset).toEqual({ x: 0, y: 10 });
Эти подходы позволяют тестировать как отдельные части Popper.js, так и их взаимодействие, создавая полное покрытие поведения popper без необходимости работы с реальным DOM.