Unit тесты для карт

Базовая структура тестового окружения

Unit-тестирование картографических приложений требует воспроизведения части браузерной среды в изолированном окружении. Основная сложность заключается в том, что карта зависит от DOM, Canvas, событий мыши и асинхронной загрузки ресурсов.

Чаще всего используется связка:

  • Jest или Vitest как тестовый раннер
  • jsdom как DOM-эмуляция
  • мокирование Canvas API
  • заглушки сетевых запросов (fetch, XHR)

Ключевая задача — отделить бизнес-логику карты от реального рендеринга тайлов и графики.


Инициализация карты в тестовой среде

Создание экземпляра Map в unit-тестах требует минимального DOM-контейнера:

  • наличие элемента div
  • фиксированная ширина и высота
  • отключение реального рендеринга при необходимости

Типовая проблема — отсутствие размеров контейнера, из-за чего View не может корректно вычислить разрешение и центр.

В тестовой среде часто используется явная фиксация размеров через Object.defineProperty для offsetWidth и offsetHeight.


Тестирование состояния Map и View

Основная логика карты сосредоточена в:

  • состоянии центра
  • масштабе (zoom)
  • проекции
  • ограничениях (extent)

Проверка обычно сводится к валидации состояния объекта View:

  • корректность установки центра через setCenter
  • изменение масштаба через setZoom
  • синхронизация состояния при программных изменениях

Особое внимание уделяется реактивности: изменения View должны отражаться в состоянии карты без прямого вмешательства в DOM.


Проверка слоёв и источников данных

В OpenLayers слои являются основным механизмом композиции карты.

Тестируемые элементы:

  • TileLayer
  • VectorLayer
  • ImageLayer

Источники данных:

  • XYZ/OSM тайлы
  • WMS/WMTS
  • VectorSource

Проверка добавления слоёв

Проверяется:

  • факт добавления слоя в коллекцию map.getLayers()
  • порядок слоёв
  • корректность zIndex

Проверка источников

Для VectorSource важны:

  • добавление фич (addFeature)
  • очистка источника (clear)
  • фильтрация по атрибутам

Мокирование сетевых запросов

Тайловые и векторные источники часто выполняют HTTP-запросы.

В unit-тестах применяются:

  • jest-fetch-mock
  • msw (Mock Service Worker)
  • ручные заглушки global.fetch

Проверяется:

  • корректность формирования URL тайлов
  • обработка ошибок сети
  • retry-механизмы
  • кеширование запросов

Особенно важно тестировать шаблоны URL:

/{z}/{x}/{y}.png

Тестирование взаимодействий (Interactions)

Взаимодействия в OpenLayers:

  • Select
  • Draw
  • Modify
  • Translate

Тестирование строится без реальных событий мыши, через программную эмуляцию:

  • создание фейковых PointerEvent
  • вызов обработчиков вручную
  • проверка состояния коллекции фич

Select interaction

Проверяется:

  • добавление выбранных объектов
  • снятие выделения
  • работа фильтров layers, condition

Draw interaction

Проверяется:

  • создание геометрии
  • завершение рисования
  • корректность типа (Point, LineString, Polygon)

Проверка кастомных контролов

Контролы представляют UI-слой над картой.

Тестируются:

  • добавление через map.addControl
  • корректное создание DOM-элементов
  • реакция на события (click, input)

Особое внимание уделяется:

  • очистке ресурсов при dispose
  • отсутствию утечек DOM-узлов

Событийная модель карты

Система событий включает:

  • moveend
  • pointermove
  • click
  • postrender

Unit-тесты проверяют:

  • корректность подписки через on
  • удаление слушателей через un
  • порядок вызова обработчиков

Проблемная зона — асинхронные события рендера, которые требуют ожидания через промисы или таймеры.


Тестирование координатных преобразований

Географическая логика базируется на преобразованиях:

  • EPSG:3857 ↔︎ EPSG:4326
  • pixel ↔︎ coordinate
  • resolution ↔︎ zoom

Проверяются функции:

  • fromLonLat
  • toLonLat
  • getCoordinateFromPixel

Ключевой аспект — допустимая погрешность вычислений, особенно при работе с проекциями.


Асинхронный рендеринг и тайлы

Tile-based рендеринг создаёт основную сложность тестирования.

Проверяется:

  • начало загрузки тайла
  • завершение загрузки
  • обработка ошибок (404, timeout)

Часто используется фиктивный тайловый источник, который возвращает синтетические изображения.


Canvas и snapshot-тестирование

Рендеринг карты в Canvas может тестироваться через:

  • мок HTMLCanvasElement
  • фиктивный getContext('2d')
  • сравнение snapshot состояния буфера

Проверяется:

  • вызовы drawImage
  • последовательность операций рендеринга
  • очистка контекста (clearRect)

Snapshot-тестирование применяется ограниченно из-за нестабильности пиксельных данных.


Работа с векторными фичами

VectorLayer и VectorSource требуют проверки:

  • добавление/удаление геометрий
  • обновление стилей
  • фильтрация через feature.setStyle

Тесты часто оперируют минимальными GeoJSON-структурами.


Типичные проблемные зоны

Основные источники нестабильности unit-тестов:

  • асинхронная загрузка тайлов
  • отсутствие реального layout в jsdom
  • различия Canvas API между средами
  • тайминги рендера (requestAnimationFrame)
  • глобальное состояние WebGL/Canvas контекста

Для стабилизации применяются:

  • фиксация таймеров (fake timers)
  • отключение анимаций
  • изоляция экземпляров карты
  • явное завершение рендера через map.renderSync()