import type { Page } from "@playwright/test"; /** * Canned enriched route for 3 nearby Berlin waypoints: * [52.520, 13.405] → [52.516, 13.377] → [52.510, 13.390] * * ~3.2km total, 6 track points with elevation. */ const MOCK_ROUTE_3WP = { geojson: { type: "FeatureCollection", features: [{ type: "Feature", geometry: { type: "LineString", coordinates: [ [13.405, 52.520, 34], [13.398, 52.519, 36], [13.391, 52.518, 38], [13.384, 52.517, 40], [13.377, 52.516, 42], [13.379, 52.514, 40], [13.382, 52.513, 38], [13.385, 52.512, 36], [13.388, 52.511, 35], [13.390, 52.510, 34], ], }, properties: {}, }], }, coordinates: [ [13.405, 52.520, 34], [13.398, 52.519, 36], [13.391, 52.518, 38], [13.384, 52.517, 40], [13.377, 52.516, 42], [13.379, 52.514, 40], [13.382, 52.513, 38], [13.385, 52.512, 36], [13.388, 52.511, 35], [13.390, 52.510, 34], ], segmentBoundaries: [0, 4], totalLength: 3200, totalAscend: 8, surfaces: [ "asphalt", "asphalt", "cobblestone", "cobblestone", "gravel", "gravel", "asphalt", "asphalt", "asphalt", "asphalt", ], highways: [ "residential", "residential", "cycleway", "cycleway", "path", "path", "tertiary", "tertiary", "residential", "residential", ], maxspeeds: [ "30", "30", "unknown", "unknown", "unknown", "unknown", "50", "50", "30", "30", ], smoothnesses: [ "good", "good", "intermediate", "intermediate", "bad", "bad", "good", "good", "excellent", "excellent", ], tracktypes: [ "unknown", "unknown", "unknown", "unknown", "grade3", "grade3", "unknown", "unknown", "unknown", "unknown", ], cycleways: [ "lane", "lane", "track", "track", "unknown", "unknown", "shared_lane", "shared_lane", "lane", "lane", ], bikeroutes: [ "rcn", "rcn", "lcn", "lcn", "none", "none", "ncn", "ncn", "rcn", "rcn", ], }; /** * Canned enriched route for 2 nearby Berlin waypoints: * [52.520, 13.405] → [52.515, 13.351] * * ~3.8km total, 6 track points with elevation. */ const MOCK_ROUTE_2WP = { geojson: { type: "FeatureCollection", features: [{ type: "Feature", geometry: { type: "LineString", coordinates: [ [13.405, 52.520, 34], [13.394, 52.519, 36], [13.383, 52.518, 40], [13.372, 52.517, 38], [13.361, 52.516, 36], [13.351, 52.515, 35], ], }, properties: {}, }], }, coordinates: [ [13.405, 52.520, 34], [13.394, 52.519, 36], [13.383, 52.518, 40], [13.372, 52.517, 38], [13.361, 52.516, 36], [13.351, 52.515, 35], ], segmentBoundaries: [0], totalLength: 3800, totalAscend: 6, surfaces: [ "asphalt", "asphalt", "gravel", "gravel", "asphalt", "asphalt", ], highways: [ "secondary", "secondary", "cycleway", "cycleway", "residential", "residential", ], maxspeeds: [ "50", "50", "unknown", "unknown", "30", "30", ], smoothnesses: [ "good", "good", "intermediate", "bad", "good", "good", ], tracktypes: [ "unknown", "unknown", "grade2", "grade4", "unknown", "unknown", ], cycleways: [ "lane", "lane", "track", "no", "shared_lane", "shared_lane", ], bikeroutes: [ "ncn", "ncn", "rcn", "none", "lcn", "lcn", ], }; /** * Mock the BRouter route API to return instant, deterministic responses. * Selects the appropriate canned response based on waypoint count. */ export async function mockBRouter(page: Page) { await page.route("**/api/route", async (route) => { const body = route.request().postDataJSON(); const wpCount = body?.waypoints?.length ?? 0; const mock = wpCount >= 3 ? MOCK_ROUTE_3WP : MOCK_ROUTE_2WP; await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(mock), }); }); } /** * Convert a lat/lon to pixel coordinates on the Leaflet map. * Requires MapExposer to have set window.__leafletMap. */ export async function latLngToPixel(page: Page, lat: number, lon: number): Promise<{ x: number; y: number }> { return page.evaluate(([la, ln]) => { const map = (window as any).__leafletMap; if (!map) throw new Error("__leafletMap not available"); const point = map.latLngToContainerPoint([la, ln]); return { x: point.x, y: point.y }; }, [lat, lon]); }