feat: v0.1.0 — scaffold + MapLibre map with EU airports

This commit is contained in:
2026-09-16 18:24:27 +00:00
parent fd2a887524
commit 30e33a08cf
23 changed files with 10813 additions and 5 deletions
+56
View File
@@ -0,0 +1,56 @@
import { test, expect, type Page } from '@playwright/test';
// Terrain is disabled in e2e (?terrain=0) for deterministic headless rendering;
// the terrain code path stays toggleable on by default in the app.
const APP_URL = '/?terrain=0';
async function waitForAirportCount(page: Page): Promise<number> {
const countEl = page.getByTestId('airport-count');
await expect.poll(async () => {
const text = (await countEl.textContent()) ?? '';
const m = text.match(/(\d+)/);
return m ? parseInt(m[1], 10) : -1;
}).toBeGreaterThan(0);
const text = (await countEl.textContent()) ?? '';
return parseInt(text.match(/(\d+)/)?.[1] ?? '0', 10);
}
test('page loads with the map and EU airport count', async ({ page }) => {
await page.goto(APP_URL);
await expect(page.getByTestId('map')).toBeVisible();
const count = await waitForAirportCount(page);
expect(count).toBeGreaterThan(0);
});
test('clicking an airport marker opens a popup with name and ICAO', async ({ page }) => {
await page.goto(APP_URL);
await waitForAirportCount(page);
// Wait until the map instance exists and airport circles are actually rendered
// (the GeoJSON source is parsed in a worker, so features arrive after addSource).
await expect.poll(async () =>
page.evaluate(
() =>
(window as any).__flightMap?.queryRenderedFeatures(undefined, {
layers: ['airports-circles'],
})?.length ?? 0,
),
{ timeout: 15_000 },
).toBeGreaterThan(0);
// Project EKRN (Bornholm) to screen space via the dev hook, then click it.
// Bornholm is used because its nearest other airport is ~0.8° away (~19 px at the
// initial zoom), so its marker cannot be overlapped by a neighbouring circle.
const pt = await page.evaluate(() => {
const map = (window as any).__flightMap;
const p = map.project([14.7596, 55.063301]);
const rect = map.getContainer().getBoundingClientRect();
return { x: rect.left + p.x, y: rect.top + p.y };
});
await page.mouse.click(pt.x, pt.y);
const popup = page.getByTestId('airport-popup');
await expect(popup).toBeVisible();
await expect(popup).toContainText('Bornholm Airport');
await expect(popup).toContainText('EKRN');
});