import { createRequire } from "node:module"; import type { Page } from "@playwright/test"; const requireFromMapLibre = createRequire(import.meta.resolve("maplibre-gl")); const { fromVectorTileJs } = requireFromMapLibre("@maplibre/vt-pbf") as { fromVectorTileJs(tile: unknown): Uint8Array; }; // Exercise the same MVT worker path as GeoServer, including a dense pipe inventory. export async function mockPipeVectorTiles(page: Page) { const tiles = new Map(); await page.route("**/tjwater_next:pipes/WebMercatorQuad/**", (route) => { const path = new URL(route.request().url()).pathname.split("/"); const [zoom, tileY, tileX] = path.slice(-3).map(Number); const key = `${zoom}/${tileY}/${tileX}`; let body = tiles.get(key); if (!body) { const project = (longitude: number, latitude: number) => { const sin = Math.sin(latitude * Math.PI / 180); return { x: Math.round(((longitude + 180) / 360 * 2 ** zoom - tileX) * 4096), y: Math.round(((0.5 - Math.log((1 + sin) / (1 - sin)) / (4 * Math.PI)) * 2 ** zoom - tileY) * 4096) }; }; const features = Array.from({ length: 2001 }, (_, index) => { const latitude = index === 0 ? 30.91 : 30.918 + Math.floor((index - 1) / 100) * 0.0004; const longitude = index === 0 ? 121.45 : 121.45 + (index - 1) % 100 * 0.0003; const geometry = [[project(longitude, latitude), project(index === 0 ? 121.48 : longitude + 0.00025, latitude)]]; const [start, end] = geometry[0]; if (start.y < -256 || start.y > 4352 || end.x < -256 || start.x > 4352) return []; return [{ type: 2, id: index + 1, extent: 4096, properties: { id: index + 1, diameter: index === 0 ? 800 : 100, status: index % 5 === 4 ? "closed" : "open" }, loadGeometry: () => geometry }]; }).flat(); body = Buffer.from(fromVectorTileJs({ layers: { pipes: { version: 2, name: "pipes", extent: 4096, length: features.length, feature: (index: number) => features[index] } } })); tiles.set(key, body); } return route.fulfill({ body, contentType: "application/vnd.mapbox-vector-tile", headers: { "Access-Control-Allow-Origin": "*" } }); }); }