Files
next-tjwater-frontend/tests/browser/investigation-chart-manager.e2e.ts
T
jiang 0ae0a41e61
Generic Container CI/CD / test-build-publish (push) Successful in 2m7s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m8s
feat(charts): manage investigation charts in a scrolling workspace
2026-11-10 17:56:23 +08:00

119 lines
8.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { expect, test } from "@playwright/test";
import { basename, resolve } from "node:path";
import { investigationFixture, mockInvestigationPresentation, selectInvestigation } from "./support/mock-investigation-presentation";
const chart = (id: string, value = 28) => ({ action: "open_chart", chart_id: id, evidence_refs: ["synthetic:pressure"],
chart: { title: `合成监测 ${id}`, chart_type: "line", x_data: ["07:45", "08:00"], series: [{ name: "压力(m)", data: [32, value] }] } });
test.use({ reducedMotion: "reduce" });
test.setTimeout(60_000);
test.beforeEach(async ({ page }) => {
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"
}));
});
test("one manager receives live charts and keeps independent enlarged children", async ({ page }, testInfo) => {
const task = investigationFixture(1, "多图统一窗口验收");
const mock = await mockInvestigationPresentation(page, [task]);
await selectInvestigation(page, task.title);
await mock.emit(task, chart("P1"));
const manager = page.getByRole("dialog", { name: "图表管理", exact: true });
await expect(manager).toBeVisible();
await mock.emit(task, chart("P2"));
await expect(manager.getByRole("img", { name: "合成监测 P2", exact: true })).toBeVisible();
await expect(page.locator("[data-floating-window]")).toHaveCount(1);
await expect(manager).toContainText("2 张图表");
await manager.getByRole("button", { name: "放大查看 合成监测 P1", exact: true }).click();
const first = page.getByRole("dialog", { name: "合成监测 P1", exact: true });
await expect(first).toBeVisible();
await manager.locator(".floating-window-heading").focus();
await manager.getByRole("button", { name: "放大查看 合成监测 P2", exact: true }).click();
const second = page.getByRole("dialog", { name: "合成监测 P2", exact: true });
await expect(first).toBeVisible();
await expect(second).toBeVisible();
await expect(page.locator("[data-floating-window]")).toHaveCount(3);
const bounds = await second.boundingBox();
await mock.emit(task, chart("P2", 17));
await second.getByRole("tab", { name: "数据", exact: true }).click();
await expect(second.getByRole("table")).toContainText("17");
expect(await second.boundingBox()).toEqual(bounds);
await expect(page.locator("[data-floating-window]")).toHaveCount(3);
await second.getByRole("button", { name: "关闭窗口", exact: true }).click();
await first.locator(".floating-window-heading").focus();
await first.getByRole("button", { name: "最大化窗口", exact: true }).click();
expect((await first.boundingBox())!.width).toBe(1424);
await first.getByRole("button", { name: "关闭窗口", exact: true }).click();
await manager.locator(".floating-window-heading").focus();
await manager.getByRole("button", { name: "最大化窗口", exact: true }).click();
await page.evaluate(() => document.fonts.ready);
await testInfo.attach("chart-manager-desktop", { body: await manager.screenshot({ path: testInfo.outputPath("chart-manager-desktop.png") }), contentType: "image/png" });
for (const width of [375, 320]) {
await page.setViewportSize({ width, height: 720 });
const box = (await manager.boundingBox())!;
expect(box.x).toBeGreaterThanOrEqual(0);
expect(box.x + box.width).toBeLessThanOrEqual(width);
expect(await manager.evaluate((node) => node.scrollWidth - node.clientWidth)).toBeLessThanOrEqual(1);
await testInfo.attach(`chart-manager-${width}`, { body: await manager.screenshot({ path: testInfo.outputPath(`chart-manager-${width}.png`) }), contentType: "image/png" });
}
await manager.getByRole("button", { name: "关闭窗口", exact: true }).click();
await mock.emit(task, chart("P3"));
const panel = page.getByLabel("调查实时展示", { exact: true });
await expect(panel.locator('[data-investigation-chart="P3"]')).toHaveCount(1);
await expect(page.locator("[data-floating-window]")).toHaveCount(0);
await panel.getByRole("button", { name: "打开图表管理", exact: true }).click();
await expect(manager).toContainText("3 张图表");
expect(mock.mutations).toEqual([]);
});
test("opening, switching, refreshing and reconnecting tasks restores charts silently, including completed reports", async ({ page }) => {
const running = investigationFixture(1, "运行中历史图表");
const completed = investigationFixture(2, "已完成历史图表");
completed.status = "completed";
completed.lifecycle_status = "completed";
const completedRun = completed.active_run!.run_id;
completed.active_run = null;
completed.latest_report = { revision: 1, execution_generation: 1, source_session_id: "investigation-dev-test", published_at: completed.created_at,
published_by: "fixture", report: { title: "已完成报告", current_conclusion: "合成监测核查完成", conclusion_boundary: "仅供浏览器验证",
stage: "final", outcome: "concluded", stop_reason: null, data_gaps: [], evidence_refs: ["synthetic:pressure"], recommendations: [], pending_items: [],
ui_blocks: [{ evidence_refs: ["synthetic:pressure"], block: { version: "answer-ui@1", block_id: "saved-report-chart", phase: "final", fallback_text: "报告图表",
spec: { root: "chart", elements: { chart: { type: "Chart", props: { ...chart("报告").chart, source: "合成保存证据" }, children: [] } } } } }] } };
const saved = [running, completed].map((task, index) => ({ task_id: task.task_id, event_seq: index + 1,
run_id: task.active_run?.run_id ?? completedRun, execution_generation: 1, occurred_at: task.created_at, command: chart(`P${index + 1}`) }));
const mock = await mockInvestigationPresentation(page, [running, completed], saved);
await selectInvestigation(page, running.title);
const panel = page.getByLabel("调查实时展示", { exact: true });
const manager = page.getByRole("dialog", { name: "图表管理", exact: true });
await expect(panel.locator('[data-investigation-chart="P1"]')).toHaveCount(1);
await expect(page.locator("[data-floating-window]")).toHaveCount(0);
// Create a live request before returning to the same task later.
await mock.emit(running, chart("P1", 23));
await expect(manager).toBeVisible();
await manager.getByRole("button", { name: "关闭窗口", exact: true }).click();
const tasks = page.getByRole("region", { name: "工况任务", exact: true });
await tasks.getByText(completed.title, { exact: true }).first().click();
await expect(panel.locator('[data-investigation-chart="P2"]')).toHaveCount(1);
await expect(panel.getByRole("img", { name: "合成监测 报告", exact: true })).toBeVisible();
await expect(page.locator("[data-floating-window]")).toHaveCount(0);
await panel.getByRole("button", { name: "打开图表管理", exact: true }).click();
await expect(manager).toContainText("2 张图表");
await expect(manager.getByRole("img", { name: "合成监测 报告", exact: true })).toBeVisible();
await manager.getByRole("button", { name: "关闭窗口", exact: true }).click();
await tasks.getByText(running.title, { exact: true }).first().click();
await expect(panel.locator('[data-investigation-chart="P1"]')).toHaveCount(1);
await expect(page.locator("[data-floating-window]")).toHaveCount(0);
await panel.getByRole("button", { name: "打开图表管理", exact: true }).click();
await expect(manager).toBeVisible();
await page.reload({ waitUntil: "domcontentloaded" });
await expect(page.locator("[data-floating-window]")).toHaveCount(0);
await selectInvestigation(page, completed.title);
await expect(panel.locator('[data-investigation-chart="P2"]')).toHaveCount(1);
await expect(page.locator("[data-floating-window]")).toHaveCount(0);
await page.evaluate(() => (window as unknown as { setInvestigationTestConnection: (value: boolean) => void }).setInvestigationTestConnection(false));
await expect(panel).toContainText("连接中断");
await page.evaluate(() => (window as unknown as { setInvestigationTestConnection: (value: boolean) => void }).setInvestigationTestConnection(true));
await expect(panel).toContainText("实时跟随", { timeout: 15_000 });
await expect(page.locator("[data-floating-window]")).toHaveCount(0);
expect(mock.mutations).toEqual([]);
});