fix: align drainage frontend configuration

This commit is contained in:
2026-07-22 15:01:35 +08:00
parent 72850761ce
commit 0995172828
45 changed files with 853 additions and 339 deletions
+6 -6
View File
@@ -1,7 +1,7 @@
import { expect, test } from "playwright/test";
test("Agent panel resizes by drag without exceeding half the viewport", async ({ page }) => {
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
const panel = page.locator('aside[aria-label="Agent 命令面板"]');
const resizeHandle = page.getByRole("separator", { name: "调整 Agent 面板宽度" });
@@ -13,7 +13,7 @@ test("Agent panel resizes by drag without exceeding half the viewport", async ({
await page.mouse.move(handleBox!.x + handleBox!.width / 2, handleBox!.y + handleBox!.height / 2);
await page.mouse.down();
await page.mouse.move(1_200, handleBox!.y + handleBox!.height / 2);
await page.mouse.move(1_200, handleBox!.y + handleBox!.height / 2, { steps: 10 });
await page.mouse.up();
await expect.poll(async () => (await panel.boundingBox())?.width).toBe(720);
@@ -26,12 +26,12 @@ test("Agent panel resizes by drag without exceeding half the viewport", async ({
});
test("collapsed Agent rail is compact and expands as one clear action", async ({ page }) => {
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "折叠 Agent 面板" }).click();
const rail = page.locator('aside[aria-label="Agent 折叠栏"]');
const expandButton = page.getByRole("button", { name: /展开排水助手面板/ });
const expandButton = page.getByRole("button", { name: /展开 Agent 助手面板/ });
await expect(rail).toBeVisible();
await expect(rail).toHaveCSS("width", "72px");
await expect(expandButton).toHaveAttribute("title", /当前|正在/);
@@ -51,7 +51,7 @@ test.describe("mobile touch layout", () => {
test.use({ hasTouch: true, isMobile: true, viewport: { width: 375, height: 812 } });
test("mobile Agent toggle opens the conversation panel by touch", async ({ page }) => {
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
const openButton = page.getByRole("button", { name: "打开 Agent 面板" });
const buttonBox = await openButton.boundingBox();
@@ -67,7 +67,7 @@ test.describe("mobile touch layout", () => {
test("mobile alert summary opens the Agent conversation panel", async ({ page }) => {
await page.clock.setFixedTime(new Date("2026-07-21T10:40:00+08:00"));
await page.setViewportSize({ width: 375, height: 812 });
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: /查看异常处置面板/ }).click();
await page.getByRole("button", { name: "工况汇总" }).click();
@@ -528,6 +528,10 @@ test("stream completion and the plan card remain positionally stable", async ({
.getByRole("button", { name: /执行进度/ })
.filter({ visible: true })
.last();
const latestProgressRegion = latestProgressToggle.locator("..");
const latestExpandedProgress = latestProgressRegion.getByRole("list", {
name: "全部执行进度",
});
await expect(latestProgressToggle).toContainText("最近 3 条");
triggerProgressAppend();
await expect(
@@ -538,9 +542,9 @@ test("stream completion and the plan card remain positionally stable", async ({
resumeStream();
await expect(latestProgressToggle).toContainText("全部 4 条", { timeout: 10_000 });
await expect(page.getByRole("list", { name: "全部执行进度" })).toBeVisible();
await expect(latestExpandedProgress).toBeVisible();
await expect(
page.getByRole("list", { name: "全部执行进度" }).getByText("溢流风险判断完成", { exact: true })
latestExpandedProgress.getByText("溢流风险判断完成", { exact: true })
).toBeVisible();
});
+3 -3
View File
@@ -15,7 +15,7 @@ test("speech capability detection preserves the server hydration tree", async ({
value: class SpeechRecognition {}
});
});
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
await expect(page.getByRole("button", { name: "语音输入" })).toBeVisible();
await expect(page.getByRole("button", { name: "权限批准模式" })).toBeVisible();
@@ -45,7 +45,7 @@ test("speech recognition failure clears the active animation and explains the er
}
});
});
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "语音输入" }).click();
@@ -77,7 +77,7 @@ test("speech recognition writes final transcript into the prompt", async ({ page
}
});
});
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "语音输入" }).click();
+1 -1
View File
@@ -2,7 +2,7 @@ import { expect, test } from "playwright/test";
test("map notice is centered in the mobile viewport", async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 });
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "打开用户菜单" }).click();
await page.getByRole("menuitem", { name: /查看运行状态/ }).click();
+15 -6
View File
@@ -4,7 +4,8 @@ test("frontend actions replace SCADA analysis results and remain legible at 375p
page
}) => {
const receipts: Array<Record<string, unknown>> = [];
await mockAgentActions(page, receipts);
const wfsRequests: string[] = [];
await mockAgentActions(page, receipts, wfsRequests);
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.waitForFunction(() =>
Boolean(window.__waterNetworkMap?.getSource("agent-scada-analysis"))
@@ -105,6 +106,7 @@ test("frontend actions replace SCADA analysis results and remain legible at 375p
})
])
);
expect(wfsRequests).toEqual(expect.arrayContaining(["MP01", "MP02"]));
await page.setViewportSize({ width: 375, height: 812 });
await page.evaluate(() => window.__waterNetworkMap?.resize());
@@ -158,12 +160,19 @@ test("frontend actions replace SCADA analysis results and remain legible at 375p
await expect.poll(() => receipts.length).toBe(4);
});
async function mockAgentActions(page: Page, receipts: Array<Record<string, unknown>>) {
async function mockAgentActions(
page: Page,
receipts: Array<Record<string, unknown>>,
wfsRequests: string[]
) {
let streamRequestCount = 0;
await page.route("**/api/map-features", async (route) => {
const body = route.request().postDataJSON() as { featureIds?: string[] };
const sensorId = body.featureIds?.[0] ?? "";
await page.route(/\/wenzhou\/ows\?/, async (route) => {
const url = new URL(route.request().url());
expect(route.request().method()).toBe("GET");
expect(url.searchParams.get("typeNames")).toBe("wenzhou:geo_scadas_mat");
const sensorId = url.searchParams.get("cql_filter")?.match(/'([^']+)'/)?.[1] ?? "";
wfsRequests.push(sensorId);
if (sensorId === "MP01") await new Promise((resolve) => setTimeout(resolve, 150));
await route.fulfill({
json: {
@@ -179,7 +188,7 @@ async function mockAgentActions(page: Page, receipts: Array<Record<string, unkno
}
]
}
});
}).catch(() => undefined);
});
await page.route("**/api/v1/agent/chat/**", async (route) => {
@@ -2,7 +2,7 @@ import { expect, test } from "playwright/test";
test("top bar uses compact controls on narrow mobile viewports", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
await expect(page.locator('meta[name="viewport"]')).toHaveAttribute(
"content",
@@ -15,7 +15,7 @@ test("top bar uses compact controls on narrow mobile viewports", async ({ page }
test("top bar keeps text horizontal at the desktop breakpoint", async ({ page }) => {
await page.setViewportSize({ width: 1024, height: 844 });
await page.goto("/", { waitUntil: "networkidle" });
await page.goto("/", { waitUntil: "domcontentloaded" });
const header = page.locator("header").first();
await expect(header).toBeVisible();