mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 01:01:39 -05:00
* fix: move foreman to global gems to fix startup crash (#1971) * Update exporting code to stream points data to file in batches to red… (#1980) * Update exporting code to stream points data to file in batches to reduce memory usage * Update changelog * Update changelog * Feature/maplibre frontend (#1953) * Add a plan to use MapLibre GL JS for the frontend map rendering, replacing Leaflet * Implement phase 1 * Phases 1-3 + part of 4 * Fix e2e tests * Phase 6 * Implement fog of war * Phase 7 * Next step: fix specs, phase 7 done * Use our own map tiles * Extract v2 map logic to separate manager classes * Update settings panel on v2 map * Update v2 e2e tests structure * Reimplement location search in maps v2 * Update speed routes * Implement visits and places creation in v2 * Fix last failing test * Implement visits merging * Fix a routes e2e test and simplify the routes layer styling. * Extract js to modules from maps_v2_controller.js * Implement area creation * Fix spec problem * Fix some e2e tests * Implement live mode in v2 map * Update icons and panel * Extract some styles * Remove unused file * Start adding dark theme to popups on MapLibre maps * Make popups respect dark theme * Move v2 maps to maplibre namespace * Update v2 references to maplibre * Put place, area and visit info into side panel * Update API to use safe settings config method * Fix specs * Fix method name to config in SafeSettings and update usages accordingly * Add missing public files * Add handling for real time points * Fix remembering enabled/disabled layers of the v2 map * Fix lots of e2e tests * Add settings to select map version * Use maps/v2 as main path for MapLibre maps * Update routing * Update live mode * Update maplibre controller * Update changelog * Remove some console.log statements --------- Co-authored-by: Robin Tuszik <mail@robin.gg>
232 lines
8.1 KiB
JavaScript
232 lines
8.1 KiB
JavaScript
import { test, expect } from '@playwright/test';
|
|
import { navigateToMap, closeOnboardingModal } from '../helpers/navigation.js';
|
|
import { waitForMap, enableLayer } from '../helpers/map.js';
|
|
|
|
test.describe('Map Layers', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await navigateToMap(page);
|
|
});
|
|
|
|
test('should enable Routes layer and display routes', async ({ page }) => {
|
|
// Wait for map to be ready
|
|
await page.waitForFunction(() => {
|
|
const container = document.querySelector('#map [data-maps-target="container"]');
|
|
return container && container._leaflet_id !== undefined;
|
|
}, { timeout: 10000 });
|
|
|
|
// Navigate to date with data
|
|
const toggleButton = page.locator('button[data-action*="map-controls#toggle"]');
|
|
const isPanelVisible = await page.locator('[data-map-controls-target="panel"]').isVisible();
|
|
|
|
if (!isPanelVisible) {
|
|
await toggleButton.click();
|
|
await page.waitForTimeout(300);
|
|
}
|
|
|
|
const startInput = page.locator('input[type="datetime-local"][name="start_at"]');
|
|
await startInput.clear();
|
|
await startInput.fill('2024-10-15T00:00');
|
|
|
|
const endInput = page.locator('input[type="datetime-local"][name="end_at"]');
|
|
await endInput.clear();
|
|
await endInput.fill('2024-10-15T23:59');
|
|
await page.click('input[type="submit"][value="Search"]');
|
|
await page.waitForLoadState('networkidle');
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Close onboarding modal if present
|
|
await closeOnboardingModal(page);
|
|
|
|
// Open layer control and enable Routes
|
|
await page.locator('.leaflet-control-layers').hover();
|
|
await page.waitForTimeout(300);
|
|
|
|
const routesCheckbox = page.locator('.leaflet-control-layers-overlays label:has-text("Routes") input[type="checkbox"]');
|
|
const isChecked = await routesCheckbox.isChecked();
|
|
|
|
if (!isChecked) {
|
|
await routesCheckbox.check();
|
|
await page.waitForTimeout(1000);
|
|
}
|
|
|
|
// Verify routes are visible
|
|
const hasRoutes = await page.evaluate(() => {
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
if (controller?.polylinesLayer && controller.polylinesLayer._layers) {
|
|
return Object.keys(controller.polylinesLayer._layers).length > 0;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
expect(hasRoutes).toBe(true);
|
|
});
|
|
|
|
test('should enable Heatmap layer and display heatmap', async ({ page }) => {
|
|
await waitForMap(page);
|
|
await enableLayer(page, 'Heatmap');
|
|
|
|
const hasHeatmap = await page.locator('.leaflet-heatmap-layer').isVisible();
|
|
expect(hasHeatmap).toBe(true);
|
|
});
|
|
|
|
test('should enable Fog of War layer and display fog', async ({ page }) => {
|
|
await waitForMap(page);
|
|
await enableLayer(page, 'Fog of War');
|
|
|
|
const hasFog = await page.evaluate(() => {
|
|
const fogCanvas = document.getElementById('fog');
|
|
return fogCanvas && fogCanvas instanceof HTMLCanvasElement;
|
|
});
|
|
|
|
expect(hasFog).toBe(true);
|
|
});
|
|
|
|
test('should enable Areas layer and display areas', async ({ page }) => {
|
|
await waitForMap(page);
|
|
|
|
// Check if there are any points in the map - areas need location data
|
|
const hasPoints = await page.evaluate(() => {
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
if (controller?.pointsLayer?._layers) {
|
|
return Object.keys(controller.pointsLayer._layers).length > 0;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
if (!hasPoints) {
|
|
console.log('No points found - skipping areas test');
|
|
return;
|
|
}
|
|
|
|
const hasAreasLayer = await page.evaluate(() => {
|
|
const mapElement = document.querySelector('#map');
|
|
const app = window.Stimulus;
|
|
const controller = app?.getControllerForElementAndIdentifier(mapElement, 'maps');
|
|
return controller?.areasLayer !== null && controller?.areasLayer !== undefined;
|
|
});
|
|
|
|
expect(hasAreasLayer).toBe(true);
|
|
});
|
|
|
|
test('should enable Suggested Visits layer', async ({ page }) => {
|
|
await waitForMap(page);
|
|
// Suggested Visits are now under Visits > Suggested in the tree
|
|
await enableLayer(page, 'Suggested');
|
|
|
|
const hasSuggestedVisits = await page.evaluate(() => {
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
return controller?.visitsManager?.visitCircles !== null &&
|
|
controller?.visitsManager?.visitCircles !== undefined;
|
|
});
|
|
|
|
expect(hasSuggestedVisits).toBe(true);
|
|
});
|
|
|
|
test('should enable Confirmed Visits layer', async ({ page }) => {
|
|
await waitForMap(page);
|
|
// Confirmed Visits are now under Visits > Confirmed in the tree
|
|
await enableLayer(page, 'Confirmed');
|
|
|
|
const hasConfirmedVisits = await page.evaluate(() => {
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
return controller?.visitsManager?.confirmedVisitCircles !== null &&
|
|
controller?.visitsManager?.confirmedVisitCircles !== undefined;
|
|
});
|
|
|
|
expect(hasConfirmedVisits).toBe(true);
|
|
});
|
|
|
|
test('should enable Scratch Map layer and display visited countries', async ({ page }) => {
|
|
await waitForMap(page);
|
|
|
|
// Check if there are any points - scratch map needs location data
|
|
const hasPoints = await page.evaluate(() => {
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
if (controller?.pointsLayer?._layers) {
|
|
return Object.keys(controller.pointsLayer._layers).length > 0;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
if (!hasPoints) {
|
|
console.log('No points found - skipping scratch map test');
|
|
return;
|
|
}
|
|
|
|
await enableLayer(page, 'Scratch Map');
|
|
|
|
// Wait a bit for the layer to load country borders
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Verify scratch layer exists and has been initialized
|
|
const hasScratchLayer = await page.evaluate(() => {
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
|
|
// Check if scratchLayerManager exists
|
|
if (!controller?.scratchLayerManager) return false;
|
|
|
|
// Check if scratch layer was created
|
|
const scratchLayer = controller.scratchLayerManager.getLayer();
|
|
return scratchLayer !== null && scratchLayer !== undefined;
|
|
});
|
|
|
|
expect(hasScratchLayer).toBe(true);
|
|
});
|
|
|
|
test('should remember enabled layers across page reloads', async ({ page }) => {
|
|
await waitForMap(page);
|
|
|
|
// Check if there are any points - needed for this test to be meaningful
|
|
const hasPoints = await page.evaluate(() => {
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
if (controller?.pointsLayer?._layers) {
|
|
return Object.keys(controller.pointsLayer._layers).length > 0;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
if (!hasPoints) {
|
|
console.log('No points found - skipping layer persistence test');
|
|
return;
|
|
}
|
|
|
|
// Enable multiple layers
|
|
await enableLayer(page, 'Points');
|
|
await enableLayer(page, 'Routes');
|
|
await enableLayer(page, 'Heatmap');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Get current layer states
|
|
const getLayerStates = () => page.evaluate(() => {
|
|
const layers = {};
|
|
// Use tree structure selectors
|
|
document.querySelectorAll('.leaflet-layerstree-header-label input[type="checkbox"]').forEach(checkbox => {
|
|
const nameSpan = checkbox.closest('.leaflet-layerstree-header').querySelector('.leaflet-layerstree-header-name');
|
|
if (nameSpan) {
|
|
const label = nameSpan.textContent.trim();
|
|
layers[label] = checkbox.checked;
|
|
}
|
|
});
|
|
return layers;
|
|
});
|
|
|
|
const layersBeforeReload = await getLayerStates();
|
|
|
|
// Reload the page
|
|
await page.reload();
|
|
await closeOnboardingModal(page);
|
|
await waitForMap(page);
|
|
await page.waitForTimeout(1000); // Wait for layers to restore
|
|
|
|
// Get layer states after reload
|
|
const layersAfterReload = await getLayerStates();
|
|
|
|
// Verify Points, Routes, and Heatmap are still enabled
|
|
expect(layersAfterReload['Points']).toBe(true);
|
|
expect(layersAfterReload['Routes']).toBe(true);
|
|
expect(layersAfterReload['Heatmap']).toBe(true);
|
|
|
|
// Verify layer states match before and after
|
|
expect(layersAfterReload).toEqual(layersBeforeReload);
|
|
});
|
|
});
|