47 lines
2.2 KiB
TypeScript
47 lines
2.2 KiB
TypeScript
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<string, Buffer>();
|
|
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": "*" } });
|
|
});
|
|
}
|