Особенности
тестирования интерактивных картографических сценариев
Взаимодействия в OpenLayers основаны на событийной модели и тесно
связаны с DOM, canvas-рендерингом и внутренним состоянием карты. Это
создаёт специфические требования к тестированию: необходимо проверять не
только чистую логику, но и поведение при пользовательских событиях,
корректность обновления слоёв, а также синхронизацию состояния объектов
карты.
Ключевая сложность заключается в том, что взаимодействия
(interaction) работают поверх Map-инстанса и
зависят от:
- событий мыши и клавиатуры;
- текущего состояния представления (
View);
- слоёв и источников данных (
Source);
- геометрии объектов;
- внутренних механизмов обработки пиксельных координат.
Поэтому тестирование делится на три уровня:
- модульное (unit);
- интеграционное;
- e2e (end-to-end).
Подготовка тестовой среды
Тестирование взаимодействий требует имитации DOM-окружения. Чаще
всего используются:
- Jest + jsdom
- Vitest + jsdom
- Mocha + jsdom
- Playwright / Cypress (для e2e)
jsdom не реализует canvas полностью, поэтому OpenLayers часто
тестируется с частичной или полной мок-реализацией canvas API.
Минимальная настройка тестовой среды включает:
- создание виртуального DOM;
- мока
HTMLCanvasElement;
- стабилизацию
requestAnimationFrame;
- фиксацию размеров контейнера карты.
Инициализация карты в тестах
Создание карты в тестовой среде требует детерминированного
контейнера:
- фиксированные размеры
width/height;
- ручное управление рендерингом;
- отключение анимаций.
Типовой подход:
- создаётся
div контейнер;
- задаются размеры через
style;
- инициализируется
Map;
- добавляется
View с фиксированным центром и zoom.
Важный аспект — синхронный рендеринг:
- используется
map.renderSync() для принудительного
обновления;
- события ожидания заменяются на прямой вызов обновления.
Тестирование базовых
взаимодействий
Select interaction
Взаимодействие выбора объектов (Select) зависит от
попадания курсора в feature.
Основные проверяемые аспекты:
- добавление feature в коллекцию
selected;
- корректная обработка клика;
- снятие выделения при повторном клике;
- работа фильтров
condition.
При тестировании имитируются события:
singleclick;
pointerdown;
pointerup.
Важно учитывать преобразование координат:
- экранные координаты → координаты карты;
- учитывается
pixelRatio.
Draw interaction
Интеракция рисования (Draw) одна из наиболее сложных для
тестирования.
Проверяются сценарии:
- начало рисования (
drawstart);
- добавление вершин;
- завершение (
drawend);
- формирование геометрии.
Типовой сценарий теста:
- создаётся
VectorSource;
- активируется
Draw с типом геометрии;
- эмулируются клики по карте;
- проверяется итоговая геометрия.
Особое внимание:
- порядок координат;
- замыкание полигонов;
- минимальное количество точек.
Modify interaction
Modify изменяет существующие геометрии.
Ключевые аспекты тестирования:
- корректность выбора вершины;
- обновление геометрии при drag;
- сохранение структуры feature;
- корректная работа
insertVertexCondition.
В тестах проверяются:
- изменение координат массива geometry;
- события
modifystart и modifyend;
- отсутствие побочных изменений других features.
Snap interaction
Snap-интеракция автоматически “прилипает” к ближайшим вершинам.
Тестирование включает:
- корректность поиска ближайшей точки;
- применение snap при добавлении координат;
- приоритет snap над свободным вводом.
Типовые проверки:
- расстояние до ближайшей вершины;
- изменение координат при pointermove;
- взаимодействие с Draw и Modify одновременно.
Тестирование событийной
модели
OpenLayers активно использует систему событий:
on('click')
on('pointermove')
on('change')
on('addfeature')
При тестировании важно проверять:
- порядок вызова обработчиков;
- корректную передачу
event объекта;
- отмену событий (
preventDefault /
stopPropagation);
- подписку и отписку от событий.
Особое внимание уделяется:
- утечкам обработчиков;
- дублированию подписок при повторной инициализации
взаимодействий.
Интеграционные тесты
взаимодействий
Интеграционные тесты проверяют связку:
Map + Layer + Source + Interaction
Типовые сценарии:
- добавление feature через Draw → проверка появления на
VectorLayer;
- изменение геометрии через Modify → проверка обновления
источника;
- Select + Style изменение → проверка визуального состояния;
- Snap + Draw → проверка корректности координат.
Интеграционные тесты часто требуют:
- синхронного рендера карты;
- фиксации таймеров (
fake timers);
- контроля состояния источников данных.
Мокирование
внутренних компонентов OpenLayers
Для ускорения unit-тестов часто мокируются:
ol/Map
ol/View
ol/render/canvas
requestAnimationFrame
Цели мокирования:
- исключить canvas-рендеринг;
- контролировать события вручную;
- ускорить выполнение тестов.
Пример подхода:
Map заменяется заглушкой с событиями;
getPixelFromCoordinate возвращает фиксированное
значение;
forEachFeatureAtPixel эмулирует попадание по
feature.
Тестирование
пользовательских сценариев взаимодействий
Сложные сценарии включают комбинации взаимодействий:
- Draw + Snap + Modify;
- Select + Translate;
- Rotate + Modify geometry;
- DragPan конфликт с Select.
Проверяется:
- приоритет взаимодействий (
active состояния);
- корректное отключение конфликтующих interaction;
- стабильность состояния карты при переключении режимов.
Особенно важно тестировать:
- переключение режимов редактирования;
- очистку interaction stack;
- предотвращение двойной обработки событий.
E2E тестирование
взаимодействий
End-to-end тесты выполняются в реальном браузере (Playwright,
Cypress).
Проверяются:
- реальное движение мыши;
- клики по canvas;
- визуальный результат;
- реакция интерфейса.
Сценарии:
- рисование полигона мышью;
- перетаскивание вершины;
- выделение объектов;
- масштабирование и панорамирование.
Особенности:
- требуется стабильная тайминг-модель;
- важно учитывать анимации view;
- возможны расхождения между браузерами.
Тестирование
производительности взаимодействий
Взаимодействия могут вызывать нагрузку:
- частые pointermove события;
- перерасчёт геометрии;
- rerender canvas.
Метрики:
- количество рендеров карты;
- время реакции на pointer events;
- задержка обновления feature;
- нагрузка при большом количестве объектов.
Проверяется:
- debounce/throttle поведения;
- отсутствие лишних перерисовок;
- оптимизация spatial index.
Ошибки и нестабильности
тестирования
Типичные проблемы:
- нестабильные координаты из-за pixel ratio;
- асинхронные события render cycle;
- различия jsdom и реального браузера;
- некорректная эмуляция pointer events;
- race conditions между interaction.
Причины нестабильности:
- отсутствие фиксации времени;
- параллельные обновления источников;
- неконтролируемые requestAnimationFrame.
Стратегии повышения
надёжности тестов
Используются следующие подходы:
- фиксация размеров карты;
- отключение анимаций View;
- использование fake timers;
- синхронный render;
- минимизация DOM-зависимости;
- изоляция interaction в отдельных тестах.
Дополнительно:
- разделение unit и integration тестов;
- использование тестовых фикстур геометрий;
- повторяемые сценарии pointer events.
Проверка
корректности геометрических изменений
При тестировании взаимодействий с геометрией важно проверять:
- сохранение топологии полигона;
- отсутствие самопересечений (если не допускаются);
- корректность порядка координат;
- обновление bounding extent.
Особенно критично для:
- Modify interaction;
- Draw interaction;
- Translate interaction.
Тестирование кастомных
interaction
Кастомные взаимодействия часто реализуются через наследование
ol/interaction/Interaction.
Проверяются:
- подписка на
handleEvent;
- корректная обработка
mapBrowserEvent;
- изменение состояния interaction;
- взаимодействие с другими слоями.
Типовые сценарии:
- обработка pointerdown → старт режима;
- pointermove → изменение состояния;
- pointerup → завершение действия.