test: migrate workbench fixtures to persistent event streams

Static fulfilled SSE bodies closed immediately and made ordinary UI cases reconnect. Serve persistent fixture streams, retain outage and cursor recovery coverage, and update legacy approval and investigation assertions for current disclosures and SVG diagrams.

Validation: 12 related browser scenarios, 877 unit tests, type checking, scoped ESLint, and diff checks. Unrelated SCADA replay changes remain outside this commit.
This commit is contained in:
2026-11-02 18:56:57 +08:00
parent 0ec74b15b2
commit 78481903d7
7 changed files with 125 additions and 53 deletions
+22 -21
View File
@@ -1,4 +1,5 @@
import { expect, test } from "@playwright/test";
import { mockWorkbenchEventStream } from "./support/mock-workbench-event-stream";
import { mockAgentApi } from "./support/mock-agent-api";
import { expectThemeColor, readRenderedContrast } from "./support/theme-colors";
@@ -755,9 +756,7 @@ test.describe("外围系统", () => {
generated_at: "2026-09-23T08:30:00Z"
} })
);
await page.route("http://server.test/api/v1/workbench/events**", (route) =>
route.fulfill({ contentType: "text/event-stream", body: ": test keepalive\n\n" })
);
await mockWorkbenchEventStream(page);
await page.route("http://server.test/api/v1/operational-tasks**", async (route) => {
const request = route.request();
const url = new URL(request.url());
@@ -805,33 +804,37 @@ test.describe("外围系统", () => {
await expect(conditionPanel).toBeVisible();
await conditionPanel.getByRole("button", { name: /调查任务/ }).click();
await expect(conditionPanel.getByRole("heading", { name: "水质投诉调查", exact: true })).toBeVisible();
await expect(conditionPanel.getByText("调查处理流程", { exact: true })).toBeVisible();
await expect(conditionPanel.getByText(/已完成 5 项 · 执行中 3 项 · 待人工或资料 3 项/)).toBeVisible();
await expect(conditionPanel.locator('[data-execution-node]')).toHaveCount(13);
await expect(conditionPanel.getByText(/历史流程按原始依赖展示/)).toBeVisible();
const expectSavedPlan = async (taskPanel: typeof conditionPanel) => {
const diagram = taskPanel.getByRole("region", { name: "调查脉络", exact: true });
await diagram.scrollIntoViewIfNeeded();
await expect(diagram.locator("svg g.node")).toHaveCount(plan.nodes.length);
await expect(diagram.locator("svg .flowchart-link")).toHaveCount(plan.edges.length);
await expect(diagram.getByLabel("图示状态说明")).toContainText("未标注状态");
await expect(diagram.locator("svg g.node").filter({ hasText: "形成调查结论" })).toBeVisible();
return diagram;
};
const diagram = await expectSavedPlan(conditionPanel);
await expect(conditionPanel.getByText(/并行处理/)).toHaveCount(0);
await expect(conditionPanel.getByRole("button", { name: "完整工程图" })).toHaveCount(0);
await expect(conditionPanel.getByText("节点与执行记录", { exact: true })).toHaveCount(0);
await expect(conditionPanel.getByLabel("计划版本", { exact: true })).toHaveCount(0);
await expect(conditionPanel.locator('[data-execution-node]')).toHaveCount(13);
await expect(conditionPanel.getByText("等待水箱清洗记录", { exact: true }).first()).toBeVisible();
await expect(diagram.locator("svg g.node").filter({ hasText: "核对水箱记录" })).toBeVisible();
const report = conditionPanel.getByRole("region", { name: "任务报告" });
await expect(report.getByText(/疑似二次供水环节问题,待现场核验/)).toBeVisible();
await expect(report.getByText("完整调查报告", { exact: true })).toHaveCount(0);
await expect(report.getByText(/结论边界/)).toBeVisible();
await expect(conditionPanel.getByText("TJWater operational task", { exact: true })).toHaveCount(0);
await expect(conditionPanel.getByText("browser-session-1", { exact: true })).toHaveCount(0);
await conditionPanel.getByText("调查处理流程", { exact: true }).scrollIntoViewIfNeeded();
await diagram.scrollIntoViewIfNeeded();
await expect(conditionPanel.getByText("前置工作与条件", { exact: true })).toHaveCount(0);
await conditionPanel.getByText("调查处理流程", { exact: true }).scrollIntoViewIfNeeded();
await diagram.scrollIntoViewIfNeeded();
await expect(page.getByText("已建立水质投诉调查", { exact: true })).toBeHidden({ timeout: 10_000 });
await page.addStyleTag({ content: "[data-sonner-toaster] { display: none !important; }" });
await page.evaluate(() => document.fonts.ready);
await testInfo.attach("water-quality-condition-task-1280", {
body: await conditionPanel.screenshot({ path: testInfo.outputPath("execution-plan-desktop.png") }),
contentType: "image/png"
});
await conditionPanel.locator('[data-execution-node="conclusion"]').scrollIntoViewIfNeeded();
await diagram.locator("svg g.node").filter({ hasText: "形成调查结论" }).scrollIntoViewIfNeeded();
await testInfo.attach("water-quality-condition-task-second-fork-1280", {
body: await conditionPanel.screenshot({ path: testInfo.outputPath("execution-plan-second-fork-desktop.png") }),
contentType: "image/png"
@@ -849,20 +852,18 @@ test.describe("外围系统", () => {
}
await responsiveConditionPanel.getByRole("button", { name: /调查任务/ }).click();
await expect(responsiveConditionPanel.getByRole("heading", { name: "水质投诉调查" })).toBeVisible();
const responsiveWorkflowStep = responsiveConditionPanel.locator('[data-execution-node="upstream"]');
const responsiveDiagram = await expectSavedPlan(responsiveConditionPanel);
const responsiveWorkflowStep = responsiveDiagram.locator("svg g.node").filter({ hasText: "校验上游水质监测" });
await responsiveWorkflowStep.scrollIntoViewIfNeeded();
await expect(responsiveWorkflowStep).toBeVisible();
await responsiveConditionPanel.getByText("调查处理流程", { exact: true }).scrollIntoViewIfNeeded();
await expect(responsiveConditionPanel.locator('[data-execution-node]')).toHaveCount(13);
await expect(responsiveConditionPanel.getByText(/历史流程按原始依赖展示/)).toBeVisible();
await responsiveDiagram.scrollIntoViewIfNeeded();
await expect(responsiveConditionPanel.getByRole("button", { name: "放大流程图" })).toHaveCount(0);
await page.waitForTimeout(350);
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(width);
await expect.poll(() => page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(width);
await testInfo.attach(`water-quality-condition-task-${width}`, {
body: await page.screenshot({ path: testInfo.outputPath(`execution-plan-${width}.png`) }),
contentType: "image/png"
});
await responsiveConditionPanel.locator('[data-execution-node="conclusion"]').scrollIntoViewIfNeeded();
await responsiveDiagram.locator("svg g.node").filter({ hasText: "形成调查结论" }).scrollIntoViewIfNeeded();
await page.evaluate(() => document.fonts.ready);
await testInfo.attach(`water-quality-condition-task-second-fork-${width}`, {
body: await page.screenshot({ path: testInfo.outputPath(`execution-plan-second-fork-${width}.png`) }),
@@ -900,7 +901,7 @@ test.describe("外围系统", () => {
await recovered.getByRole("button", { name: /调查任务/ }).click();
const taskRow = recovered.getByRole("button", { name: /水质投诉调查/ }).first();
await taskRow.click();
await expect(recovered.getByText(/历史流程按原始依赖展示/)).toBeVisible();
await expectSavedPlan(recovered);
expect(agentRequests.filter((body) => "trigger_context" in body)).toHaveLength(0);
});