import { expect, test } from "@playwright/test"; import { mockAgentApi } from "./support/mock-agent-api"; import { mockWorkbenchContext } from "./support/mock-workbench-context"; for (const kind of ["peripheral", "dev"] as const) { test(`${kind} panel keeps outside clicks, dragging and wheel navigation available`, async ({ page }) => { await mockWorkbenchContext(page); await mockAgentApi(page); await page.route("**/runtime-config.js", (route) => route.fulfill({ contentType: "application/javascript", body: `globalThis.__TJWATER_CONFIG__ = ${JSON.stringify({ TJWATER_AUTH_MODE: "disabled", TJWATER_ENABLE_DEV_PANEL: "true", TJWATER_SERVER_API_BASE_URL: "https://tjwater-api.invalid", TJWATER_AGENT_URL: "http://127.0.0.1:8787", TJWATER_MAP_URL: "https://workbench-map.invalid/geoserver", TJWATER_GEOSERVER_WORKSPACE: "tjwater_next", TJWATER_MAPBOX_ACCESS_TOKEN: "", TJWATER_TIANDITU_TOKEN: "", TJWATER_ENABLE_MSW: "false" })};` })); await page.emulateMedia({ reducedMotion: "reduce" }); await page.goto("/", { waitUntil: "domcontentloaded" }); await page.waitForFunction(() => Boolean(window.__waterNetworkMap)); const trigger = page.getByRole("button", { name: kind === "peripheral" ? "外围系统" : "切换地图 Dev Panel", exact: true }); await trigger.click(); const panel = page.getByRole("complementary", { name: kind === "peripheral" ? "外围系统" : "地图开发面板", exact: true }); await expect(panel).toBeVisible(); await page.locator(".maplibregl-canvas-container").evaluate((element) => { element.setAttribute("data-pointer-probe", "0"); for (const type of ["pointerdown", "wheel"]) element.addEventListener(type, () => { element.setAttribute("data-pointer-probe", String(Number(element.getAttribute("data-pointer-probe")) + 1)); }, true); }); // Controls inside a floating panel consume their own pointer input. const heading = panel.getByRole("heading", { level: 2 }); await heading.click(); await page.mouse.wheel(0, 100); await expect(page.locator(".maplibregl-canvas-container")).toHaveAttribute("data-pointer-probe", "0"); const canvas = page.locator(".maplibregl-canvas"); const bounds = (await canvas.boundingBox())!; const point = { x: bounds.x + 150, y: bounds.y + 340 }; await expect.poll(() => page.evaluate(({ x, y }) => document.elementFromPoint(x, y)?.classList.contains("maplibregl-canvas") ?? false, point)).toBe(true); await page.mouse.click(point.x, point.y); await expect(page.locator(".maplibregl-canvas-container")).toHaveAttribute("data-pointer-probe", "1"); const center = await page.evaluate(() => window.__waterNetworkMap!.getCenter().toArray()); await page.mouse.move(point.x, point.y); await page.mouse.down(); await page.mouse.move(point.x + 100, point.y + 30, { steps: 8 }); await page.mouse.up(); await expect.poll(() => page.evaluate(() => window.__waterNetworkMap!.getCenter().toArray())).not.toEqual(center); const zoom = await page.evaluate(() => window.__waterNetworkMap!.getZoom()); await page.mouse.wheel(0, -200); await expect.poll(() => page.evaluate(() => window.__waterNetworkMap!.getZoom())).toBeGreaterThan(zoom); await expect(panel).toBeVisible(); await expect(trigger).toHaveAttribute("aria-pressed", "true"); // Opening and closing the other panel must not leave an invisible input shield. if (kind === "dev") { await page.getByRole("button", { name: "外围系统", exact: true }).click(); await expect.poll(() => page.evaluate(({ x, y }) => document.elementFromPoint(x, y)?.classList.contains("maplibregl-canvas") ?? false, point)).toBe(true); await page.getByRole("button", { name: "关闭外围系统", exact: true }).click(); await panel.getByRole("tab", { name: "地图调试", exact: true }).click(); await expect(panel.getByRole("button", { name: "定位并高亮", exact: true })).toBeEnabled(); } await panel.getByRole("button", { name: kind === "peripheral" ? "关闭外围系统" : "关闭 Dev Panel", exact: true }).click(); await expect(panel).toBeHidden(); await expect.poll(() => page.evaluate(({ x, y }) => document.elementFromPoint(x, y)?.classList.contains("maplibregl-canvas") ?? false, point)).toBe(true); }); }