import { expect, test } from "@playwright/test"; import { basename, resolve } from "node:path"; import { investigationFixture, mockInvestigationPresentation, selectInvestigation } from "./support/mock-investigation-presentation"; const ids = ["486033", "542017", "541061", "524529"]; const times = Array.from({ length: 13 }, (_, index) => `${String(5 + Math.floor(index / 4)).padStart(2, "0")}:${String(index % 4 * 15).padStart(2, "0")}`); const series = (id: string, day: number, missing = false) => ({ name: `${id} ${day ? `07-${String(16 - day).padStart(2, "0")}` : "当日"}`, device_id: id, day_offset: day, type: day ? "scatter" : "line", data: times.map((_, index) => missing || day > 0 && index < 10 ? null : 200 + index * 10), sample_times: times.map((time, index) => missing || day > 0 && index < 10 ? null : `2026-07-${String(16 - day).padStart(2, "0")}T${time}:00+08:00`) }); test("keeps four SCADA comparison objects and explains verified missing history", async ({ page }, testInfo) => { test.setTimeout(60_000); await page.route("**/@fs/**/noto-sans-sc-*.woff2", (route) => route.fulfill({ path: resolve("node_modules/@fontsource-variable/noto-sans-sc/files", basename(new URL(route.request().url()).pathname)), contentType: "font/woff2" })); const task = investigationFixture(1, "SCADA展示覆盖核查"); const mock = await mockInvestigationPresentation(page, [task]); await selectInvestigation(page, task.title); const context = { metric: "flow", unit: "m3/h", window_start: "2026-07-16T05:00:00+08:00", window_end: "2026-07-16T08:00:00+08:00" }; await mock.emit(task, { action: "open_chart", chart_id: "flow-current", evidence_refs: ["synthetic:flow"], chart: { title: "流量当前三小时趋势", chart_type: "line", x_data: times, scada: { ...context, role: "current" }, series: ids.map((id) => series(id, 0)) } }); for (const id of ids) { await mock.emit(task, { action: "open_chart", chart_id: `flow-${id}`, evidence_refs: ["synthetic:flow"], chart: { title: `${id} 流量同期对比`, chart_type: "time_comparison", x_data: times, scada: { ...context, role: "comparison", gaps: id === "524529" ? Array.from({ length: 7 }, (_, day) => ({ device_id: id, day_offset: day + 1, missing_count: 3, reason: day < 3 ? "no_readings" : "outside_frozen_window" })) : [] }, series: Array.from({ length: 8 }, (_, day) => series(id, day, id === "524529" && day > 0)) } }); await expect(page.locator(`[data-presentation-scope="investigation"] [data-investigation-chart="flow-${id}"]`)).toHaveCount(1); } await page.getByRole("dialog", { name: "图表管理", exact: true }).getByRole("button", { name: "关闭窗口", exact: true }).click(); const panel = page.getByLabel("调查实时展示", { exact: true }); await panel.getByRole("button", { name: /放大查看 流量当前曲线与前七天同期对比/ }).click(); const dialog = page.getByRole("dialog", { name: /流量当前曲线与前七天同期对比/ }); const objects = dialog.getByLabel("选择图表对象"); await expect(objects.getByRole("button")).toHaveCount(4); await expect(objects).toContainText("4 个"); await objects.getByRole("button", { name: "切换对象 524529", exact: true }).click(); await expect(dialog.getByLabel("监测数据缺口")).toContainText("历史缺测 21 点"); await expect(dialog.getByLabel("监测数据缺口")).toContainText("部分数据不在冻结范围内"); await expect(dialog.getByRole("img", { name: "524529 流量同期对比", exact: true })).toBeVisible(); expect(await dialog.evaluate((element) => element.scrollWidth - element.clientWidth)).toBeLessThanOrEqual(1); await page.evaluate(() => document.fonts.ready); await testInfo.attach("scada-four-objects-missing-history", { body: await dialog.screenshot({ path: testInfo.outputPath("scada-four-objects.png") }), contentType: "image/png" }); expect(mock.mutations).toEqual([]); });