import { expect, test } from "@playwright/test"; import { mockInvestigationPresentation } from "./support/mock-investigation-presentation"; test.beforeEach(async ({ page }) => { await mockInvestigationPresentation(page, []); await page.goto("/", { waitUntil: "domcontentloaded" }); await page.waitForFunction(() => Boolean(window.__waterNetworkMap?.getLayer("scada-pressure-hit"))); await page.getByRole("button", { name: "切换地图 Dev Panel" }).click(); await page.getByTestId("map-dev-panel").getByRole("tab", { name: "通知测试" }).click(); }); test("Dev previews all five tones, transient expiry and loading completion", async ({ page }, testInfo) => { const panel = page.getByTestId("map-dev-panel"); for (const label of ["信息", "成功", "警告", "错误", "加载"]) { await panel.getByRole("button", { name: `测试${label}通知` }).click(); } const loading = page.locator("[data-sonner-toast]").filter({ hasText: "正在加载管网 · 测试" }); await expect(loading).toBeVisible(); await expect(loading.getByRole("button", { name: "关闭通知" })).toHaveCount(0); await expect(loading).toHaveCSS("opacity", "1"); await testInfo.attach("notice-tones", { body: await page.screenshot({ path: testInfo.outputPath("tones.png") }), contentType: "image/png" }); await panel.getByRole("button", { name: "模拟加载完成" }).click(); await expect(page.locator("[data-sonner-toast]").filter({ hasText: "管网加载完成 · 测试" })).toBeVisible(); await page.mouse.move(5, 5); await expect(page.locator("[data-sonner-toast]").filter({ hasText: "管网加载完成 · 测试" })).toHaveCount(0, { timeout: 6000 }); await expect(page.locator("[data-sonner-toast]").filter({ hasText: "地图视图已更新 · 测试" })).toHaveCount(0); await expect(page.locator("[data-sonner-toast]").filter({ hasText: "部分监测数据延迟 · 测试" })).toBeVisible(); await panel.getByRole("button", { name: "清除测试通知" }).click(); await expect(page.locator("[data-sonner-toast]").filter({ hasText: "· 测试" })).toHaveCount(0); }); for (const width of [1280, 375, 320]) { test(`linked notices survive timeout and navigation, wrap and close independently at ${width}px`, async ({ page }, testInfo) => { const panel = page.getByTestId("map-dev-panel"); await panel.getByRole("button", { name: "测试报告通知" }).click(); await panel.getByRole("button", { name: "测试任务通知" }).click(); await panel.getByRole("button", { name: "测试长文本通知" }).click(); const notices = page.locator("[data-sonner-toast]").filter({ hasText: "保留至手动关闭" }); await expect(notices).toHaveCount(3); await notices.filter({ hasText: "新收到一项" }).getByRole("button", { name: "查看任务" }).click(); await expect(panel.getByRole("status")).toHaveText("已触发“查看任务”测试操作,通知仍保留。"); await notices.filter({ hasText: "城南片区" }).getByRole("button", { name: "查看报告" }).click(); await expect(panel.getByRole("status")).toHaveText("已触发“查看报告”测试操作,通知仍保留。"); await page.getByRole("button", { name: "关闭 Dev Panel" }).click(); await page.setViewportSize({ width, height: 900 }); await page.mouse.move(5, 5); await page.clock.install(); await page.clock.fastForward(15_000); await expect(notices).toHaveCount(3); for (const notice of await notices.all()) { await expect(notice).toBeInViewport(); expect(await notice.evaluate((element) => ({ overflow: element.scrollWidth > element.clientWidth, left: element.getBoundingClientRect().left, right: element.getBoundingClientRect().right <= innerWidth }))).toEqual({ overflow: false, left: expect.any(Number), right: true }); const close = notice.getByRole("button", { name: "关闭通知" }); await expect.poll(() => close.evaluate((element) => { const rect = element.getBoundingClientRect(); return element.contains(document.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2)); })).toBe(true); } await testInfo.attach(`linked-notices-${width}`, { body: await page.screenshot({ path: testInfo.outputPath("notices.png") }), contentType: "image/png" }); await notices.filter({ hasText: "新收到一项" }).getByRole("button", { name: "关闭通知" }).click(); await page.clock.runFor(250); await expect(notices).toHaveCount(2); await notices.filter({ hasText: "城南片区" }).getByRole("button", { name: "查看报告" }).click(); await expect(notices).toHaveCount(2); }); } test("closing retained notices reveals the remaining notices in the original stack", async ({ page }, testInfo) => { const panel = page.getByTestId("map-dev-panel"); await panel.getByRole("button", { name: "连续 6 条通知" }).click(); const notices = page.locator("[data-sonner-toast]").filter({ hasText: "保留至手动关闭" }); await expect(notices).toHaveCount(6); const oldest = notices.filter({ hasText: "第 1 条测试通知" }); await expect(oldest).toHaveAttribute("data-visible", "false"); await notices.first().getByRole("button", { name: "关闭通知" }).click(); await expect(notices).toHaveCount(5); await notices.first().getByRole("button", { name: "关闭通知" }).click(); await expect(notices).toHaveCount(4); await expect(oldest).toHaveAttribute("data-visible", "true"); await testInfo.attach("notice-original-stack", { body: await page.screenshot({ path: testInfo.outputPath("stack.png") }), contentType: "image/png" }); await panel.getByRole("button", { name: "清除测试通知" }).click(); await expect(notices).toHaveCount(0); });