Files
next-tjwater-frontend/tests/browser/city-scene.e2e.ts
T

120 lines
4.7 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { mockWorkbenchContext } from "./support/mock-workbench-context";
const EMPTY_RASTER_TILE = Buffer.from(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=",
"base64"
);
// Uses generated local building data, while unrelated backend services are isolated.
test("3D adds opaque buildings without enabling duplicate GIS layers", async ({ page }) => {
test.skip(
process.env.TJWATER_CITY_SCENE_TEST !== "1",
"Requires the generated local city-model scene"
);
test.setTimeout(60000);
await mockWorkbenchContext(page, undefined, undefined, {}, [], {
tiandituToken: "city-scene-tianditu-token"
});
await page.route("https://t0.tianditu.gov.cn/**", (route) =>
route.fulfill({ contentType: "image/png", body: EMPTY_RASTER_TILE })
);
await page.goto("/", { waitUntil: "domcontentloaded" });
const toggle = page
.getByRole("group", { name: "地图缩放", exact: true })
.locator("button[aria-pressed]");
await expect(toggle).toBeEnabled({ timeout: 15000 });
const businessLayers = await page.evaluate(() =>
window.__waterNetworkMap!.getStyle().layers.map((layer) => ({
id: layer.id,
visibility: window.__waterNetworkMap!.getLayoutProperty(layer.id, "visibility") ?? "visible"
}))
);
await toggle.click();
await expect(toggle).toHaveAttribute("aria-pressed", "true");
await page.evaluate(() =>
window.__waterNetworkMap?.jumpTo({ center: [121.464, 30.916], zoom: 16, pitch: 55 })
);
await expect
.poll(
() =>
page.evaluate(
() =>
window.__waterNetworkMap?.queryRenderedFeatures({ layers: ["fengxian-city-buildings"] })
.length ?? 0
),
{ timeout: 30000 }
)
.toBeGreaterThan(20);
const buildingPoint = await page.evaluate(() => {
const map = window.__waterNetworkMap!;
const canvas = map.getCanvas();
for (let y = 20; y < canvas.clientHeight; y += 20) {
for (let x = 20; x < canvas.clientWidth; x += 20) {
if (map.queryRenderedFeatures([x, y], { layers: ["fengxian-city-buildings"] }).length > 0) {
return { x, y };
}
}
}
return null;
});
expect(buildingPoint).not.toBeNull();
const mapCanvasBounds = await page.locator(".maplibregl-canvas").boundingBox();
expect(mapCanvasBounds).not.toBeNull();
await page.mouse.click(
mapCanvasBounds!.x + buildingPoint!.x,
mapCanvasBounds!.y + buildingPoint!.y
);
await expect(page.locator(".maplibregl-popup")).toHaveCount(0);
await expect(page.getByText("建筑参考模型", { exact: true })).toHaveCount(0);
const scene = await page.evaluate(() => ({
layers: window
.__waterNetworkMap!.getStyle()
.layers.filter((layer) => layer.id.startsWith("fengxian-city-"))
.map((layer) => layer.id),
sources: Object.keys(window.__waterNetworkMap!.getStyle().sources).filter((id) =>
id.startsWith("fengxian-city-")
),
opacity: window.__waterNetworkMap!.getPaintProperty(
"fengxian-city-buildings",
"fill-extrusion-opacity"
),
layerOrder: window.__waterNetworkMap!.getStyle().layers.map((layer) => layer.id)
}));
expect(scene.layers).toEqual(["fengxian-city-buildings"]);
expect(scene.sources).toEqual(["fengxian-city-buildings"]);
expect(scene.opacity).toBe(1);
const buildingIndex = scene.layerOrder.indexOf("fengxian-city-buildings");
expect(buildingIndex).toBeGreaterThan(scene.layerOrder.indexOf("tianditu-vector-annotation"));
expect(buildingIndex).toBeLessThan(
scene.layerOrder.findIndex((layerId) => layerId.startsWith("pipes-"))
);
for (const layer of businessLayers) {
expect(
await page.evaluate(
(id) => window.__waterNetworkMap!.getLayoutProperty(id, "visibility") ?? "visible",
layer.id
)
).toBe(layer.visibility);
}
await page.evaluate(() => window.__waterNetworkMap?.rotateTo(90, { duration: 0 }));
await expect(page.locator("[data-map-compass]")).toHaveAttribute("data-bearing", "90.0");
await page.evaluate(() => window.__waterNetworkMap?.rotateTo(0, { duration: 0 }));
await page.screenshot({ path: "../city-model-fengxian/reports/browser-nanqiao.png" });
await toggle.click();
await expect
.poll(() =>
page.evaluate(() =>
window.__waterNetworkMap?.getLayoutProperty("fengxian-city-buildings", "visibility")
)
)
.toBe("none");
await page.setViewportSize({ width: 390, height: 844 });
await toggle.click();
await expect(toggle).toHaveAttribute("aria-pressed", "true");
const box = await toggle.boundingBox();
expect(box?.width).toBe(40);
expect(box?.height).toBe(40);
await page.screenshot({ path: "../city-model-fengxian/reports/browser-mobile.png" });
});