Интеграционное тестирование в контексте веб-картографии охватывает проверку взаимодействия между компонентами приложения: слоем карты, тайловыми сервисами, маркерами, всплывающими окнами, геоданными и пользовательскими событиями. В отличие от модульных тестов, где проверяются отдельные функции или классы, интеграционные тесты фиксируют поведение системы в условиях, максимально приближенных к реальному браузерному окружению.
В приложениях на основе Leaflet ключевую роль играет DOM-рендеринг карты, асинхронная загрузка тайлов, обработка событий мыши и касаний, а также взаимодействие с внешними источниками данных (GeoJSON, WMS, кастомные API). Поэтому интеграционные тесты должны охватывать не только JavaScript-логику, но и визуально-событийную модель карты.
Интеграционные тесты для Leaflet-приложений обычно строятся вокруг следующих уровней:
1. Уровень инициализации карты
divL.map()2. Уровень слоёв
3. Уровень объектов
4. Событийный уровень
5. Интеграция с внешними сервисами
Интеграционные тесты для Leaflet могут выполняться в двух основных средах:
Браузерная среда (рекомендуемая):
Headless-окружение (ограниченное):
Проблема jsdom заключается в том, что он не реализует полноценный layout engine, а Leaflet активно зависит от размеров контейнера, координат пикселей и событий DOM.
Пример минимальной HTML-фикстуры:
<div id="map" style="width: 800px; height: 600px;"></div>
Инициализация карты:
import L from 'leaflet';
const map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19
}).addTo(map);
Интеграционный тест инициализации должен проверять:
Пример теста (Playwright):
test('карта инициализируется корректно', async ({ page }) => {
await page.goto('http://localhost:3000/map');
const mapExists = await page.evaluate(() => {
return !!window.map && window.map.getZoom() === 13;
});
expect(mapExists).toBe(true);
});
Особое внимание уделяется асинхронной загрузке тайлов. Даже если
карта создана, тайлы могут подгружаться позже, что требует ожиданий
(waitForSelector, network idle).
TileLayer является одним из самых чувствительных компонентов. Он зависит от сети, кэширования и правильной генерации URL.
L.tileLayer('https://a.tile.server/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
Интеграционные проверки:
a, b,
c)Пример проверки сетевых запросов:
page.on('request', request => {
if (request.url().includes('.png')) {
console.log('Tile requested:', request.url());
}
});
Маркерный слой — одна из самых часто тестируемых частей.
const marker = L.marker([51.5, -0.09]).addTo(map);
marker.bindPopup('Hello').openPopup();
Интеграционные тесты проверяют:
Пример теста клика по маркеру:
test('popup открывается по клику', async ({ page }) => {
await page.goto('/map');
await page.click('.leaflet-marker-icon');
const popupText = await page.textContent('.leaflet-popup-content');
expect(popupText).toContain('Hello');
});
Событийная модель Leaflet критична для интерактивных приложений.
Основные события:
clickzoomendmoveenddragendПример:
map.on('click', (e) => {
console.log(e.latlng);
});
Интеграционный тест:
test('обработка клика по карте', async ({ page }) => {
await page.goto('/map');
await page.click('#map', { position: { x: 400, y: 300 } });
const latlng = await page.evaluate(() => window.lastClick);
expect(latlng).toBeDefined();
});
Работа с GeoJSON требует проверки корректности рендеринга и стилизации.
L.geoJSON(geoData, {
style: {
color: 'blue'
}
}).addTo(map);
Интеграционные тесты включают:
Пример проверки количества объектов:
const layerCount = await page.evaluate(() => {
return Object.keys(window.vectorLayer._layers).length;
});
expect(layerCount).toBe(5);
Многие приложения загружают данные через fetch:
fetch('/api/geojson')
.then(res => res.json())
.then(data => {
L.geoJSON(data).addTo(map);
});
Интеграционное тестирование требует:
Пример с Playwright:
await page.route('/api/geojson', route => {
route.fulfill({
contentType: 'application/json',
body: JSON.stringify({ type: 'FeatureCollection', features: [] })
});
});
Leaflet зависит от размеров контейнера для расчёта тайлов и координат. Поэтому критично проверять:
invalidateSize()map.invalidateSize();
map.setView([51.505, -0.09], 13);
Интеграционный тест:
await page.evaluate(() => {
document.getElementById('map').style.width = '400px';
window.map.invalidateSize();
});
Leaflet поддерживает touch-события:
Интеграционные тесты в мобильных профилях браузера проверяют:
Пример Playwright:
await page.touchscreen.tap(200, 200);
await page.touchscreen.tap(200, 200);
Контролы Leaflet часто реализуются как UI-компоненты:
L.control.custom = function () {
const control = L.control({ position: 'topright' });
control.on Add = function () {
const div = L.DomUtil.create('div', 'custom-control');
div.innerHTML = 'Button';
return div;
};
return control;
};
Интеграционные тесты проверяют:
Основная сложность интеграционного тестирования карт — внешние сервисы:
Подходы:
1. Мокирование HTTP
2. Локальный tile server
3. Snapshot сетевых запросов
Карты создают значительную нагрузку:
Контроль включает:
Экосистема плагинов расширяет функциональность:
Интеграционные тесты проверяют:
Пример:
const markers = L.markerClusterGroup();
markers.addLayer(L.marker([51.5, -0.09]));
map.addLayer(markers);
Интеграционные тесты картографических приложений выполняются в CI окружениях:
Особенности:
Пример конфигурации:
- name: Run e2e tests
run: npx playwright test
load и tileloadВ интеграционных тестах важно анализировать:
const popupVisible = await page.isVisible('.leaflet-popup');
Типовой сценарий включает:
Карты часто используют таймеры:
Интеграционные тесты требуют контроля времени:
moveend, zoomendСложные приложения комбинируют:
Тестируется:
При изменении маршрута SPA:
Интеграционные тесты для Leaflet строятся вокруг моделирования поведения реального пользователя и реальной среды браузера, с акцентом на асинхронные процессы, DOM-рендеринг и сетевые взаимодействия, что требует строгого контроля окружения, событий и визуального состояния карты.