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" }); });