feat(workbench): expand SCADA monitoring and investigation presentation
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { mockAgentApi } from "./support/mock-agent-api";
|
||||
import { mockWorkbenchContext } from "./support/mock-workbench-context";
|
||||
import { responsesFixture } from "./support/responses-fixture";
|
||||
|
||||
test.use({ timezoneId: "UTC" });
|
||||
|
||||
const times = Array.from({ length: 13 }, (_, index) => `${String(9 + Math.floor(index / 4)).padStart(2, "0")}:${String(index % 4 * 15).padStart(2, "0")}`);
|
||||
const block = {
|
||||
version: "answer-ui@1", block_id: "scada-week", phase: "final", fallback_text: "合成 SCADA 七日对照",
|
||||
spec: { root: "chart", elements: { chart: { type: "Chart", children: [], props: {
|
||||
title: "压力与前七天同时刻对照(m)", chart_type: "line", y_axis_name: "压力(m)", x_axis_name: "时间(UTC0)",
|
||||
x_data: times.map((time) => new Date(`2026-06-14T${time}:00+08:00`).toISOString().slice(11, 16)),
|
||||
series: [{ name: "当日三小时", type: "line", data: [34, 34.2, 33.8, 34, 33.5, 33, 32.5, 32, 31, 30, 29, 27, 25],
|
||||
sample_times: times.map((time) => new Date(`2026-06-14T${time}:00+08:00`).toISOString().replace(".000Z", "Z")) },
|
||||
...Array.from({ length: 7 }, (_, index) => ({ name: `6月${13 - index}日`, type: "scatter",
|
||||
data: [...Array(10).fill(null), 34 + index * 0.4, 34.3 + index * 0.4, 34.6 + index * 0.4],
|
||||
sample_times: [...Array(10).fill(null), ...times.slice(10).map((time) => index % 2
|
||||
? `2026-06-${String(13 - index).padStart(2, "0")}T${time}:00+08:00`
|
||||
: new Date(`2026-06-${String(13 - index).padStart(2, "0")}T${time}:00+08:00`).toISOString().replace(".000Z", "Z"))] }))],
|
||||
source: "浏览器合成样例,非现场监测数据"
|
||||
} } } }
|
||||
};
|
||||
|
||||
for (const width of [1440, 375, 320]) {
|
||||
test(`SCADA comparison preserves seven daily point sets, timestamps and axis range at ${width}px`, async ({ page }, testInfo) => {
|
||||
await page.setViewportSize({ width, height: 1000 });
|
||||
await page.emulateMedia({ reducedMotion: "reduce" });
|
||||
await mockWorkbenchContext(page, undefined, undefined, {}, [], { runtimeMode: "backend" });
|
||||
await mockAgentApi(page);
|
||||
await page.route("**/api/v1/responses", async (route) => {
|
||||
if (route.request().method() === "OPTIONS") return route.fallback();
|
||||
await route.fulfill({ headers: { "Access-Control-Allow-Origin": "*", "Content-Type": "text/event-stream" },
|
||||
body: responsesFixture([
|
||||
{ type: "start", messageId: "scada-week-answer" },
|
||||
{ type: "data-answer_ui", id: block.block_id, data: block },
|
||||
{ type: "data-final_answer", data: { content: "合成 SCADA 对照,待现场核验。", ui_block_ids: [block.block_id] } },
|
||||
{ type: "finish", finishReason: "stop" }
|
||||
]) });
|
||||
});
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
await page.getByRole("button", { name: width < 1024 ? "打开 Agent 面板" : /展开 Agent 助手面板/ }).click();
|
||||
const panel = page.getByRole("complementary", { name: "Agent 命令面板" });
|
||||
await panel.locator("textarea").fill("查看合成 SCADA 七日对照");
|
||||
await panel.getByRole("button", { name: "发送 Agent 指令" }).click();
|
||||
const ui = panel.locator(".answer-ui-chart");
|
||||
await expect(ui).toBeVisible();
|
||||
await expect(ui).toContainText("时间(UTC+8)");
|
||||
await expect(ui.getByRole("tab", { name: "复合", exact: true })).toBeVisible();
|
||||
await expect(ui.getByLabel("显示的数据序列").getByRole("button")).toHaveCount(8);
|
||||
// Each historical day has exactly three unconnected SVG scatter symbols.
|
||||
for (const color of ["#059669", "#d97706", "#7c3aed", "#0891b2", "#e11d48", "#475569", "#a16207"]) {
|
||||
await expect(ui.locator(`svg path[fill="${color}"]`)).toHaveCount(3);
|
||||
}
|
||||
const axisValues = () => ui.locator("svg text").allTextContents().then((labels) => labels.filter((label) => /^-?\d+(\.\d+)?$/.test(label)).map(Number));
|
||||
expect((await axisValues()).every((value) => value > 0)).toBe(true);
|
||||
await page.evaluate(() => document.fonts.ready);
|
||||
await testInfo.attach(`scada-week-${width}`, { body: await ui.screenshot({ path: testInfo.outputPath(`scada-week-${width}.png`) }), contentType: "image/png" });
|
||||
await ui.locator('svg path[fill="#059669"]').last().hover({ position: { x: 4, y: 6 } });
|
||||
await expect(ui).toContainText("采样时间 2026-06-13 12:00:00+08:00");
|
||||
await page.evaluate(() => document.fonts.ready);
|
||||
await testInfo.attach(`scada-week-tooltip-${width}`, { body: await ui.screenshot({ path: testInfo.outputPath(`scada-week-tooltip-${width}.png`) }), contentType: "image/png" });
|
||||
const plot = ui.getByRole("group", { name: /按回车查看数据点/ });
|
||||
await plot.focus();
|
||||
await page.keyboard.press("End");
|
||||
const details = ui.getByRole("region", { name: "数据点详情" });
|
||||
await expect(details).toContainText("2026-06-14 12:00:00+08:00");
|
||||
await expect(details).toContainText("2026-06-13 12:00:00+08:00");
|
||||
await page.keyboard.press("Home");
|
||||
await expect(details).toContainText("缺测");
|
||||
await ui.getByRole("button", { name: "关闭数据点详情" }).click();
|
||||
await ui.getByRole("tab", { name: "柱状", exact: true }).click();
|
||||
expect(await axisValues()).toContain(0);
|
||||
await ui.getByRole("tab", { name: "数据", exact: true }).click();
|
||||
await expect(ui).toContainText("缺测");
|
||||
await expect(ui).toContainText("2026-06-13 12:00:00+08:00");
|
||||
expect(await ui.evaluate((element) => element.scrollWidth - element.clientWidth)).toBeLessThanOrEqual(1);
|
||||
|
||||
// Use the product buttons to inspect both the floating and maximized layouts.
|
||||
await page.setViewportSize({ width, height: width < 640 ? 640 : 1000 });
|
||||
const search = ui.getByRole("textbox", { name: /搜索压力与前七天/ });
|
||||
await search.fill("2026-06-13");
|
||||
const expand = ui.getByRole("button", { name: "放大查看 压力与前七天同时刻对照(m)", exact: true });
|
||||
await expand.click();
|
||||
const floating = page.getByRole("dialog", { name: "压力与前七天同时刻对照(m)", exact: true });
|
||||
await expect(floating.getByRole("tab", { name: "数据", exact: true })).toHaveAttribute("aria-selected", "true");
|
||||
await expect(floating.getByRole("textbox", { name: /搜索压力与前七天/ })).toHaveValue("2026-06-13");
|
||||
await floating.getByRole("tab", { name: "复合", exact: true }).click();
|
||||
const drawing = floating.getByRole("img", { name: "压力与前七天同时刻对照(m)", exact: true });
|
||||
const instance = await drawing.locator(".echarts-for-react").getAttribute("_echarts_instance_");
|
||||
const restored = (await floating.boundingBox())!;
|
||||
await floating.getByRole("button", { name: "最大化窗口", exact: true }).click();
|
||||
await expect.poll(async () => (await floating.boundingBox())!.width).toBe(width - 16);
|
||||
await expect.poll(async () => (await floating.boundingBox())!.height).toBe((width < 640 ? 640 : 1000) - 16);
|
||||
await expect.poll(async () => Math.abs(Number(await drawing.locator("svg").getAttribute("width")) - (await drawing.boundingBox())!.width)).toBeLessThan(1);
|
||||
await expect.poll(async () => Math.abs(Number(await drawing.locator("svg").getAttribute("height")) - (await drawing.boundingBox())!.height)).toBeLessThan(1);
|
||||
await expect(drawing.locator(".echarts-for-react")).toHaveAttribute("_echarts_instance_", instance!);
|
||||
const content = floating.locator("[data-floating-window-content]");
|
||||
expect(await content.evaluate((element) => element.scrollWidth - element.clientWidth)).toBeLessThanOrEqual(1);
|
||||
const plotBox = (await drawing.boundingBox())!;
|
||||
const sidebar = (await floating.locator("aside").boundingBox())!;
|
||||
if (width < 640) expect(sidebar.y).toBeGreaterThanOrEqual(plotBox.y + plotBox.height);
|
||||
else expect(sidebar.x).toBeGreaterThanOrEqual(plotBox.x + plotBox.width);
|
||||
expect(plotBox.height).toBeGreaterThanOrEqual(220);
|
||||
await floating.getByLabel("显示的数据序列").getByRole("button", { name: "6月12日", exact: true }).click();
|
||||
await expect(ui.getByLabel("显示的数据序列").getByRole("button", { name: "6月12日", exact: true })).toHaveAttribute("aria-pressed", "false");
|
||||
await floating.getByLabel("显示的数据序列").getByRole("button", { name: "6月12日", exact: true }).click();
|
||||
await floating.locator('svg path[fill="#059669"]').last().hover({ position: { x: 4, y: 6 } });
|
||||
await expect(floating).toContainText("采样时间 2026-06-13 12:00:00+08:00");
|
||||
await floating.locator(".floating-window-heading").hover();
|
||||
await page.evaluate(() => document.fonts.ready);
|
||||
await testInfo.attach(`scada-week-fullscreen-${width}`, { body: await floating.screenshot({ path: testInfo.outputPath(`scada-week-fullscreen-${width}.png`) }), contentType: "image/png" });
|
||||
await floating.getByRole("button", { name: "还原窗口", exact: true }).click();
|
||||
await expect.poll(async () => (await floating.boundingBox())!.width).toBe(restored.width);
|
||||
await expect.poll(async () => (await floating.boundingBox())!.height).toBe(restored.height);
|
||||
await floating.getByRole("tab", { name: "数据", exact: true }).click();
|
||||
await expect(floating.getByRole("textbox", { name: /搜索压力与前七天/ })).toHaveValue("2026-06-13");
|
||||
await floating.getByRole("button", { name: "关闭窗口", exact: true }).click();
|
||||
await expect(floating).toHaveCount(0);
|
||||
await expect(expand).toBeFocused();
|
||||
await expect(search).toHaveValue("2026-06-13");
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user