Update application ports to 3050 and enhance Playwright tests with WebGL mock
Tests / backend-test (pull_request) Successful in 10s
Tests / frontend-test (pull_request) Successful in 9m25s
Tests / e2e-test (pull_request) Has been cancelled

This commit is contained in:
(jenkins)
2026-04-01 11:04:16 +01:00
parent cac76a2f69
commit 228032c913
11 changed files with 278 additions and 19 deletions
+69 -5
View File
@@ -1,14 +1,80 @@
import { test, expect } from '@playwright/test';
// MapLibre GL requires WebGL which isn't available in headless Chromium.
// Intercept the module request and return a lightweight mock so React can render.
const MAPLIBRE_MOCK = `
class Map {
constructor(opts) {
this._listeners = {};
Promise.resolve().then(() => this._emit('style.load'));
}
_emit(event) {
(this._listeners[event] || []).forEach(fn => fn());
}
on(event, fn) {
if (!this._listeners[event]) this._listeners[event] = [];
this._listeners[event].push(fn);
return this;
}
off(event, fn) {
this._listeners[event] = (this._listeners[event] || []).filter(l => l !== fn);
return this;
}
remove() {}
getSource() { return null; }
getLayer() { return null; }
addSource() {}
addLayer() {}
removeLayer() {}
removeSource() {}
setSky() {}
setTerrain() {}
setLayoutProperty() {}
flyTo() {}
jumpTo() {}
setStyle() { Promise.resolve().then(() => this._emit('style.load')); }
getCanvas() { return document.createElement('canvas'); }
project() { return { x: 0, y: 0 }; }
unproject() { return { lng: 0, lat: 0 }; }
}
class Marker {
constructor(opts) {
this._el = (opts && opts.element) || document.createElement('div');
}
setLngLat() { return this; }
addTo() { return this; }
remove() {}
getLngLat() { return { lng: 0, lat: 0 }; }
getElement() { return this._el; }
}
class Popup {
setLngLat() { return this; }
setDOMContent() { return this; }
addTo() { return this; }
remove() {}
}
class LngLatBounds {
extend() { return this; }
}
export default { Map, Marker, Popup, LngLatBounds };
`;
test.beforeEach(async ({ page }) => {
await page.route('**maplibre-gl.js*', async route => {
await route.fulfill({ contentType: 'application/javascript', body: MAPLIBRE_MOCK });
});
});
test.describe('Line of Sight Application', () => {
test('should load the home page and show settings', async ({ page }) => {
await page.goto('/');
await expect(page.locator('text=Line of Sight Settings')).toBeVisible();
await expect(page.locator('text=Direction')).toBeVisible();
await expect(page.locator('label:has-text("Direction")')).toBeVisible();
});
test('should be able to toggle map style', async ({ page }) => {
await page.goto('/');
await page.waitForSelector('h3:text("Line of Sight Settings")', { timeout: 10000 });
const darkButton = page.locator('button:text("Dark")');
await darkButton.click();
await expect(darkButton).toHaveClass(/active-style/);
@@ -16,10 +82,8 @@ test.describe('Line of Sight Application', () => {
test('should show results when clicking the search button', async ({ page }) => {
await page.goto('/');
// Mock the API response to avoid dependency on backend for E2E if desired,
// but here we let it hit the real backend if it's up.
// For a robust E2E in CI, we usually mock.
await page.waitForSelector('h3:text("Line of Sight Settings")', { timeout: 10000 });
await page.route('**/api/line-of-sight*', async route => {
const json = {
success: true,