Тестирование после миграции

После миграции на MapLibre GL JS критически важным этапом становится проверка корректности работы всех слоёв карты, источников данных и пользовательских взаимодействий. Даже при формальной совместимости API с Mapbox GL JS различия в рендерере, обработке стилей и шрифтовых ресурсах могут приводить к визуальным и функциональным расхождениям, которые невозможно обнаружить без системного тестирования.

Первым уровнем тестирования выступает проверка создания экземпляра карты и корректной загрузки базового стиля. Важно убедиться, что карта не только инициализируется без ошибок, но и полностью завершает загрузку всех ресурсов.

Типовой сценарий проверки:

import maplibregl from "maplibre-gl";

const map = new maplibregl.Map({
  container: "map",
  style: "https://demotiles.maplibre.org/style.json",
  center: [37.6173, 55.7558],
  zoom: 10
});

map.on("load", () => {
  console.assert(map.isStyleLoaded(), "Стиль должен быть полностью загружен");
});

Ключевым индикатором корректной работы выступает событие load и метод isStyleLoaded(). В тестовой среде важно учитывать асинхронность загрузки тайлов и ресурсов шрифтов.

Тестирование источников данных (sources)

После миграции часто возникают расхождения в обработке источников GeoJSON, Vector Tiles и Raster Tiles. Особое внимание уделяется структуре sources, так как MapLibre GL JS более строго обрабатывает некоторые поля спецификации стиля.

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

map.on("load", () => {
  map.addSource("cities", {
    type: "geojson",
    data: {
      type: "FeatureCollection",
      features: []
    }
  });

  const source = map.getSource("cities");
  console.assert(source, "Источник cities должен существовать");
});

Тестирование должно включать:

  • корректность загрузки удалённых URL-источников
  • обработку пустых FeatureCollection
  • обновление данных через setData
  • поведение при ошибках сети

Особое внимание уделяется setData, так как при миграции могут проявляться различия в обновлении кэша рендера.

Проверка слоёв (layers) и порядка отрисовки

Слои являются центральным элементом визуального тестирования. После миграции возможны изменения в порядке отрисовки, особенно при использовании fill, line, symbol и custom layers.

map.addLayer({
  id: "cities-layer",
  type: "circle",
  source: "cities",
  paint: {
    "circle-radius": 6,
    "circle-color": "#ff0000"
  }
});

Проверка должна включать:

  • наличие слоя через map.getLayer
  • корректный порядок beforeId
  • соответствие стилей ожиданиям дизайна
  • проверку visibility (layout.visibility)

Отдельное внимание требуется символическим слоям (symbol), так как различия в шрифтах (glyphs) после миграции могут приводить к пустым подписям.

Тестирование стилей (style specification)

MapLibre GL JS строго следует спецификации Mapbox Style Spec, однако некоторые edge-case поведения отличаются. Проверка стиля включает:

  • корректность JSON структуры style.json
  • доступность sprite и glyphs
  • загрузку источников через HTTPS
  • отсутствие deprecated полей

Пример валидации загрузки стиля:

map.on("styledata", () => {
  const style = map.getStyle();
  console.assert(style.sources, "sources должны быть определены");
  console.assert(style.layers.length > 0, "layers должны присутствовать");
});

Важно тестировать динамическую смену стилей:

map.setStyle("https://example.com/new-style.json");
map.once("style.load", () => {
  console.assert(map.isStyleLoaded(), "Новый стиль должен загрузиться полностью");
});

Проверка событийной модели

После миграции необходимо убедиться, что все пользовательские события продолжают работать корректно. MapLibre GL JS сохраняет API событий Mapbox GL JS, но порядок их срабатывания может отличаться в зависимости от версии WebGL контекста.

Основные события для тестирования:

  • load
  • idle
  • render
  • move
  • zoom
  • click, mouseenter, mouseleave

Пример проверки клика по слою:

map.on("click", "cities-layer", (e) => {
  console.assert(e.features.length > 0, "Должен быть хотя бы один feature");
});

Особое внимание уделяется событию idle, так как оно используется в тестах визуальной стабилизации карты.

Визуальное регрессионное тестирование

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

Типовой подход включает:

  • фиксированные координаты центра и zoom
  • отключение анимаций
  • ожидание idle перед снимком
await map.once("idle");
const canvas = map.getCanvas();

В CI обычно применяется сравнение скриншотов с эталонными изображениями. Важно учитывать:

  • различия GPU между окружениями
  • headless WebGL поведение
  • платформенные отличия рендеринга шрифтов

Тестирование производительности

После миграции возможно изменение производительности из-за различий в оптимизациях WebGL слоя. Основные метрики:

  • время первого рендера
  • FPS при панорамировании
  • время загрузки тайлов
  • потребление памяти

Пример измерения времени загрузки:

const start = performance.now();

map.on("idle", () => {
  const duration = performance.now() - start;
  console.log("Время до idle:", duration);
});

Также проверяется поведение при большом количестве слоёв и источников:

  • деградация FPS при >1000 features
  • стабильность при частых setData
  • отсутствие утечек при повторном создании карты

Кроссбраузерное тестирование

MapLibre GL JS опирается на WebGL, поэтому различия между браузерами напрямую влияют на результат. Тестирование должно охватывать:

  • Chromium-based браузеры
  • Firefox
  • Safari (особенно ограничения WebGL2)

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

  • инициализация WebGL context
  • fallback при отсутствии поддержки
  • корректность работы preserveDrawingBuffer
  • поведение при low-power GPU
if (!maplibregl.supported()) {
  throw new Error("WebGL не поддерживается");
}

Тестирование мобильных устройств

На мобильных устройствах ключевыми становятся ограничения памяти и GPU. После миграции часто проявляются:

  • вылеты при сложных стилях
  • задержки при pinch-zoom
  • некорректное позиционирование touch events

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

  • обработка touch events (touchstart, touchmove)
  • inertia scrolling
  • корректность жестов вращения (bearing)

Интеграционные тесты с данными

После миграции важно протестировать взаимодействие карты с backend-данными:

  • обновление GeoJSON через API
  • потоковые обновления (WebSocket)
  • кластеризация данных

Пример динамического обновления:

setInterval(() => {
  fetch("/api/geojson")
    .then(res => res.json())
    .then(data => {
      const source = map.getSource("cities");
      source.setData(data);
    });
}, 5000);

Проверка должна учитывать:

  • отсутствие мерцания слоёв
  • корректное обновление кластеров
  • синхронизацию состояния карты и данных

Тестирование устойчивости к ошибкам

После миграции важно убедиться, что библиотека корректно обрабатывает ошибки:

  • недоступные tiles
  • битые style.json
  • некорректный GeoJSON
  • таймауты сети

Проверка поведения:

map.on("error", (e) => {
  console.error("Map error:", e.error);
});

Цель тестирования — отсутствие полного падения рендера при частичных ошибках источников.

Проверка совместимости кастомных расширений

Если в старой версии использовались кастомные слои или расширения WebGL, после миграции требуется проверка:

  • инициализации custom layer lifecycle
  • корректности render(gl, matrix)
  • взаимодействия с depth buffer
  • очистки ресурсов

Особенно критично при использовании анимаций и shader-based визуализаций.

Автоматизация тестирования в CI

После миграции тестирование должно выполняться автоматически. Типовой pipeline включает:

  • unit-тесты API-обёрток
  • integration-тесты загрузки стилей
  • headless WebGL рендеринг
  • визуальные диффы

Пример структуры:

/tests
  /unit
  /integration
  /visual
  /performance

В headless-режиме важно фиксировать окружение:

  • версия WebGL
  • разрешение canvas
  • seed для данных
  • отключение анимаций

Тестирование после миграции на MapLibre GL JS становится многоуровневым процессом, охватывающим рендеринг, данные, взаимодействия и производительность, где каждый слой системы требует отдельной валидации и повторяемости результатов в разных средах исполнения.