feat: refactor artifact analysis workspace

This commit is contained in:
2026-08-19 16:09:51 +08:00
parent bfadc95f93
commit d2f2895c36
26 changed files with 998 additions and 2278 deletions
+3 -2
View File
@@ -184,11 +184,12 @@ test("Main Frame navigation respects forced color mode", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
const navigation = page.getByRole("complementary", { name: "工作台导航" });
const taskbar = page.getByRole("toolbar", { name: "工作区窗口任务栏" });
const workspace = page.locator("#main-workspace");
await expect(navigation).toBeVisible();
await expect(navigation).toHaveCSS("backdrop-filter", "none");
await expect(navigation).toHaveCSS("box-shadow", "none");
await expect(taskbar).toHaveCSS("box-shadow", "none");
await expect(workspace).toBeVisible();
await expect(page.getByRole("toolbar", { name: "工作区窗口任务栏" })).toHaveCount(0);
});
async function expectAcrylicSurface(shell: Locator, allowedFilteredDescendant?: string) {
+24 -31
View File
@@ -1,52 +1,45 @@
import { expect, test } from "@playwright/test";
import { mockAgentApi } from "./support/mock-agent-api";
test("unified workbench navigation collapses and restores the main workspace", async ({ page }) => {
test("the docked Agent collapses and restores the main workspace", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
const navigation = page.getByRole("complementary", { name: "工作台导航" });
const agentPanel = page.getByRole("complementary", { name: "Agent 命令面板" });
const workspace = page.locator("#main-workspace");
await expect(navigation).toHaveCSS("width", "368px");
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(368);
const expandedWidth = Math.round((await agentPanel.boundingBox())?.width ?? 0);
expect(expandedWidth).toBeGreaterThan(400);
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(expandedWidth);
await page.getByRole("button", { name: "折叠工作台导航" }).click();
await expect(navigation).toHaveCSS("width", "48px");
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(48);
await page.getByRole("button", { name: "折叠 Agent 面板" }).click();
await expect(page.getByLabel("Agent 折叠栏")).toBeVisible();
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(72);
await page.getByRole("button", { name: "展开工作台导航" }).click();
await expect(navigation).toHaveCSS("width", "368px");
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(368);
await page.getByLabel(/展开 Agent 助手面板/).click();
await expect(agentPanel).toBeVisible();
await expect.poll(async () => Math.round((await workspace.boundingBox())?.x ?? 0)).toBe(expandedWidth);
});
test("unified navigation switches between Agent and condition panes", async ({ page }) => {
test("the floating condition feed coordinates with the docked Agent", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
const mainFrame = page.getByTestId("workbench-main-frame");
await expect(page.locator('aside[aria-label="Agent 命令面板"]')).toBeVisible();
const prompt = page.getByPlaceholder("输入调度问题,Agent 将通过后端会话流式响应");
await prompt.fill("保留尚未发送的诊断问题");
await mainFrame.getByRole("button", { name: "工况任务", exact: true }).click();
const conditionPanel = page.getByRole("region", { name: "工况任务", exact: true });
await expect(conditionPanel).toBeVisible();
await expect(page.locator('aside[aria-label="Agent 命令面板"]')).toBeHidden();
await conditionPanel.getByRole("button", { name: "展开工况任务" }).click();
await expect(conditionPanel.getByRole("button", { name: "收起工况任务" })).toBeVisible();
await conditionPanel.getByRole("button", { name: "收起工况任务" }).click();
await mainFrame.getByRole("button", { name: "Agent", exact: true }).click();
await expect(page.locator('aside[aria-label="Agent 命令面板"]')).toBeVisible();
await expect(prompt).toHaveValue("保留尚未发送的诊断问题");
const topBarConditionToggle = page
const conditionToggle = page
.locator("header.acrylic-navigation")
.getByRole("button", { name: "工况任务", exact: true });
await page.getByRole("button", { name: "折叠工作台导航" }).click();
await expect(page.getByRole("complementary", { name: "工作台导航" })).toHaveCSS("width", "48px");
await topBarConditionToggle.click();
await expect(page.getByRole("complementary", { name: "工作台导航" })).toHaveCSS("width", "368px");
await expect(page.getByRole("region", { name: "工况任务", exact: true })).toBeVisible();
await topBarConditionToggle.click();
await conditionToggle.click();
const conditionPanel = page.getByRole("region", { name: "工况任务", exact: true });
await expect(conditionPanel).toBeVisible();
await expect(page.locator('aside[aria-label="Agent 命令面板"]')).toBeVisible();
await conditionPanel.getByRole("button", { name: "展开工况任务" }).click();
await expect(page.getByLabel("Agent 折叠栏")).toBeVisible();
await expect(conditionPanel.getByRole("button", { name: "收起工况任务" })).toBeVisible();
await conditionPanel.getByRole("button", { name: "收起工况任务" }).click();
await expect(page.locator('aside[aria-label="Agent 命令面板"]')).toBeVisible();
await expect(prompt).toHaveValue("保留尚未发送的诊断问题");
await conditionToggle.click();
await expect(conditionPanel).toBeHidden();
});
test("Agent resize handle stays hidden in the mobile layout", async ({ page }) => {
@@ -2,6 +2,7 @@ import { expect, test, type Locator } from "@playwright/test";
test("scheduled conditions keep acrylic blur outside transformed ancestors", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "工况任务", exact: true }).click();
const panel = page.getByRole("region", { name: "工况任务", exact: true });
await expect(panel).toBeVisible();
@@ -111,6 +112,7 @@ test("narrow desktop keeps Agent and expanded conditions from overlapping", asyn
test("switching conditions keeps the detail viewport fully expanded", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "工况任务", exact: true }).click();
const panel = page.getByRole("region", { name: "工况任务", exact: true });
await panel.getByRole("button", { name: "展开工况任务" }).click();
@@ -168,6 +170,7 @@ test("keeps execution spinners without breathing badges after selecting timeline
page
}) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "工况任务", exact: true }).click();
const panel = page.getByRole("region", { name: "工况任务", exact: true });
await panel.getByRole("button", { name: "展开工况任务" }).click();
@@ -199,6 +202,7 @@ test("keeps execution spinners without breathing badges after selecting timeline
test("shows completed field work as a static waiting-for-reply state", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "工况任务", exact: true }).click();
const panel = page.getByRole("region", { name: "工况任务", exact: true });
await panel.getByRole("button", { name: "展开工况任务" }).click();
+1
View File
@@ -2,6 +2,7 @@ import { expect, test, type Locator } from "@playwright/test";
test("native scroll regions share the workbench scrollbar presentation", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "工况任务", exact: true }).click();
const reference = page
.getByRole("region", { name: "工况任务", exact: true })
@@ -21,6 +21,7 @@ test("opening Agent and condition panels does not move the map camera", async ({
await page.getByRole("button", { name: /展开 Agent 助手面板/ }).click();
await expect(page.locator('aside[aria-label="Agent 命令面板"]')).toBeVisible();
await page.getByRole("button", { name: "工况任务", exact: true }).click();
const conditionPanel = page.getByRole("region", { name: "工况任务", exact: true });
await conditionPanel.getByRole("button", { name: "展开工况任务" }).click();
await expect(conditionPanel).toHaveCSS("width", "880px");
-5
View File
@@ -192,7 +192,6 @@ async function selectBasemap(page: Page, label: "浅色" | "影像") {
async function expectDesktopMainFrameGeometry(page: Page) {
const navigation = page.getByRole("complementary", { name: "工作台导航" });
const workspace = page.locator("#main-workspace");
const taskbar = page.getByRole("toolbar", { name: "工作区窗口任务栏" });
const mapWindow = page.locator("#workspace-map");
const agentPanel = page.locator('aside[aria-label="Agent 命令面板"]');
await expect(navigation).toHaveCSS("width", "368px");
@@ -201,20 +200,16 @@ async function expectDesktopMainFrameGeometry(page: Page) {
const navigationBox = await navigation.boundingBox();
const workspaceBox = await workspace.boundingBox();
const taskbarBox = await taskbar.boundingBox();
const mapBox = await mapWindow.boundingBox();
const agentBox = await agentPanel.boundingBox();
expect(navigationBox).not.toBeNull();
expect(workspaceBox).not.toBeNull();
expect(taskbarBox).not.toBeNull();
expect(mapBox).not.toBeNull();
expect(agentBox).not.toBeNull();
expect(navigationBox!.x).toBe(0);
expect(navigationBox!.y).toBe(56);
expect(workspaceBox!.x).toBe(navigationBox!.x + navigationBox!.width);
expect(workspaceBox!.y).toBe(navigationBox!.y);
expect(taskbarBox!.x).toBe(workspaceBox!.x);
expect(taskbarBox!.y).toBe(workspaceBox!.y + workspaceBox!.height);
expect(mapBox).toEqual(workspaceBox);
expect(agentBox!.x).toBeGreaterThanOrEqual(48);
expect(agentBox!.x).toBeLessThanOrEqual(49);
+109 -227
View File
@@ -1,250 +1,132 @@
import { expect, test, type Page } from "@playwright/test";
import { mockAgentApi } from "./support/mock-agent-api";
test("temporary Agent analysis windows float above the persistent map workspace", async ({ page }) => {
test("the default workspace docks Agent beside the persistent map", async ({ page }) => {
await page.setViewportSize({ width: 1600, height: 900 });
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
const frame = page.getByTestId("workbench-main-frame");
const mapWindow = page.locator("#workspace-map");
const testButton = page.getByRole("button", { name: "测试打开 Agent 多图表窗口" }).first();
const workspace = page.locator("#main-workspace");
const map = page.locator("#workspace-map");
await expect(frame).toBeVisible();
await expect(mapWindow).toBeVisible();
await expect(testButton).toBeVisible();
await expect(page.getByLabel("工作台导航")).toHaveCount(0);
await expect(workspace).toHaveAttribute("data-layout-mode", "default");
await expect(map).toBeVisible();
await expect(page.getByLabel("Agent 命令面板")).toBeVisible();
await expect(mapWindow.getByRole("navigation", { name: "地图工具" })).toBeVisible();
await expect(page.locator(".workspace-window-titlebar")).toHaveCount(0);
await testButton.click();
await expect(page.getByRole("heading", { name: "北辰分区压力异常诊断", exact: true })).toBeVisible();
await expect(mapWindow).toBeVisible();
await testButton.click();
await expect(page.getByRole("heading", { name: "供水服务分区平衡分析", exact: true })).toBeVisible();
await expect(page.getByText("2 / 6 个临时分析窗")).toBeVisible();
await openWindowOperationMenu(page, "供水服务分区平衡分析");
await page.getByRole("menuitem", { name: "最小化" }).click();
await expect(page.getByRole("button", { name: "恢复供水服务分区平衡分析" })).toBeVisible();
await page.getByRole("button", { name: "恢复供水服务分区平衡分析" }).click();
await expect(page.getByRole("heading", { name: "供水服务分区平衡分析", exact: true })).toBeVisible();
await openWindowOperationMenu(page, "供水服务分区平衡分析");
await page.getByRole("menuitem", { name: "关闭并销毁" }).click();
await openWindowOperationMenu(page, "北辰分区压力异常诊断");
await page.getByRole("menuitem", { name: "关闭并销毁" }).click();
await expect(mapWindow).toBeVisible();
await expect(page.getByRole("heading", { name: "北辰分区压力异常诊断", exact: true })).toHaveCount(0);
await expect(page.getByText("0 / 6 个临时分析窗")).toBeVisible();
await expect(map.getByRole("navigation", { name: "地图工具" })).toBeVisible();
await expect(page.getByRole("region", { name: "工况任务", exact: true })).toHaveCount(0);
await expect(page.getByRole("button", { name: "任务视图" })).toHaveCount(0);
});
test("the map document floats and minimizes to its taskbar entry", async ({ page }) => {
test("a generated Artifact stays in peek until explicitly opened", async ({ page }) => {
await page.setViewportSize({ width: 1600, height: 900 });
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "生成 Agent 模拟分析成果" }).click();
const peek = page.getByRole("complementary", { name: "Agent 成果预览" });
await expect(peek).toBeVisible();
await expect(peek).toContainText("北辰分区压力异常诊断");
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "default");
await expect(page.getByRole("heading", { name: "北辰分区压力异常诊断" })).toHaveCount(0);
await peek.getByRole("button", { name: "打开成果" }).click();
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "map_split");
await expect(page.locator("#workspace-map")).toBeVisible();
await expect(page.locator("#artifact-workspace")).toBeVisible();
await expect(page.getByRole("heading", { name: "北辰分区压力异常诊断" })).toBeVisible();
await expect(page.getByLabel("Agent 折叠栏")).toBeVisible();
});
test("Agent expands over an active Artifact without resizing the main workspace", async ({ page }) => {
await page.setViewportSize({ width: 1600, height: 900 });
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await openFirstArtifact(page);
const workspace = page.locator("#main-workspace");
const mapWindow = page.locator("#workspace-map");
const dockedBox = await workspace.boundingBox();
expect(dockedBox).not.toBeNull();
await openWindowOperationMenu(page, "供水管网地图");
await page.getByRole("menuitem", { name: "恢复为浮动窗口" }).click();
const floatingBox = await mapWindow.boundingBox();
expect(floatingBox).not.toBeNull();
expect(floatingBox!.width).toBeLessThan(dockedBox!.width);
expect(floatingBox!.height).toBeLessThan(dockedBox!.height);
await expect(mapWindow).toHaveCSS("border-radius", "0px");
const floatingClassName = await mapWindow.getAttribute("class");
expect(floatingClassName).not.toContain("ring-1");
expect(await mapWindow.evaluate((element) => getComputedStyle(element).boxShadow)).not.toBe("none");
await expect(page.getByRole("button", { name: "打开供水管网地图窗口操作" })).toBeAttached();
await openWindowOperationMenu(page, "供水管网地图");
await page.getByRole("menuitem", { name: "最小化" }).click();
await expect(mapWindow).toBeHidden();
const restoreTask = page.getByRole("button", { name: "恢复供水管网地图" });
await expect(restoreTask).toBeVisible();
await restoreTask.click();
await expect(mapWindow).toBeVisible();
await expect(page.getByRole("button", { name: "打开供水管网地图窗口操作" })).toBeAttached();
});
test("the test control cycles through three trusted document profiles", async ({ page }) => {
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
const testButton = page.getByRole("button", { name: "测试打开 Agent 多图表窗口" }).first();
await testButton.click();
await testButton.click();
await testButton.click();
await expect(page.getByRole("heading", { name: "北辰分区压力异常诊断", exact: true })).toBeAttached();
await expect(page.getByRole("heading", { name: "供水服务分区平衡分析", exact: true })).toBeAttached();
await expect(page.getByRole("heading", { name: "低压事件调度处置流程", exact: true })).toBeVisible();
await expect(page.getByText("3 / 6 个临时分析窗")).toBeVisible();
});
test("task view shows every window and fills the workspace with the selected one", async ({ page }) => {
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
const testButton = page.getByRole("button", { name: "测试打开 Agent 多图表窗口" }).first();
await testButton.click();
await testButton.click();
await openWindowOperationMenu(page, "北辰分区压力异常诊断");
await page.getByRole("menuitem", { name: "最小化" }).click();
await page.getByRole("button", { name: "任务视图" }).click();
await expect(page.getByRole("dialog", { name: "任务视图" })).toBeVisible();
await expect(page.getByRole("button", { name: /打开供水管网地图并铺满主视图/ })).toBeVisible();
await expect(page.getByRole("button", { name: /打开北辰分区压力异常诊断并铺满主视图,当前已最小化/ })).toBeVisible();
await expect(page.getByRole("button", { name: /打开供水服务分区平衡分析并铺满主视图/ })).toBeVisible();
await page.getByRole("button", { name: /打开供水服务分区平衡分析并铺满主视图/ }).click();
await expect(page.getByRole("dialog", { name: "任务视图" })).toHaveCount(0);
const workspaceBox = await page.locator("#main-workspace").boundingBox();
const selectedBox = await page.locator("section[aria-label='供水服务分区平衡分析']").boundingBox();
expect(workspaceBox).not.toBeNull();
expect(selectedBox).not.toBeNull();
expect(Math.abs(selectedBox!.width - workspaceBox!.width)).toBeLessThanOrEqual(2);
expect(Math.abs(selectedBox!.height - workspaceBox!.height)).toBeLessThanOrEqual(2);
await page.getByRole("button", { name: "任务视图" }).click();
await page.keyboard.press("Escape");
await expect(page.getByRole("dialog", { name: "任务视图" })).toHaveCount(0);
await expect(page.getByRole("button", { name: "任务视图" })).toBeFocused();
});
test("temporary documents survive a mobile breakpoint round trip", async ({ page }) => {
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "测试打开 Agent 多图表窗口" }).first().click();
const analysisHeading = page.locator("h2", { hasText: "北辰分区压力异常诊断" });
await expect(analysisHeading).toBeVisible();
await page.setViewportSize({ width: 390, height: 844 });
await expect(page.locator("#workspace-map")).toBeVisible();
await expect(analysisHeading).toBeAttached();
await expect(analysisHeading).toBeHidden();
await page.setViewportSize({ width: 1440, height: 900 });
await expect(analysisHeading).toBeVisible();
await expect(page.locator("#workspace-map")).toBeVisible();
});
test("layout presets arrange transient windows and keep the map visible", async ({ page }) => {
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
const testButton = page.getByRole("button", { name: "测试打开 Agent 多图表窗口" }).first();
await testButton.click();
await testButton.click();
await testButton.click();
await applyTaskViewLayout(page, "主次");
const workspace = page.locator("#main-workspace");
await expect(workspace).toHaveAttribute("data-layout-mode", "primary");
await expect(page.locator("#workspace-map")).toBeVisible();
await expect(page.locator("section[aria-label='低压事件调度处置流程']")).toBeVisible();
await expect(page.locator("section[aria-label='北辰分区压力异常诊断']")).toBeHidden();
await expect(page.locator("section[aria-label='低压事件调度处置流程']")).toHaveCSS("border-radius", "0px");
const workspaceBox = await workspace.boundingBox();
const primaryBox = await page.locator("section[aria-label='低压事件调度处置流程']").boundingBox();
expect(workspaceBox).not.toBeNull();
expect(primaryBox).not.toBeNull();
expect(primaryBox!.width).toBeGreaterThan(workspaceBox!.width * 0.6);
await testButton.click();
await expect(page.locator("section[aria-label='北辰分区压力异常诊断']").last()).toBeVisible();
const newPrimaryBox = await page.locator("section[aria-label='北辰分区压力异常诊断']").last().boundingBox();
expect(newPrimaryBox).not.toBeNull();
expect(newPrimaryBox!.width).toBeGreaterThan(workspaceBox!.width * 0.6);
});
test("dragging a small window onto the primary window swaps their complete slots", async ({ page }) => {
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "测试打开 Agent 多图表窗口" }).first().click();
await applyTaskViewLayout(page, "主次");
const mapWindow = page.locator("#workspace-map");
const analysisWindow = page.locator("section[aria-label='北辰分区压力异常诊断']");
const mapBefore = await mapWindow.boundingBox();
const analysisBefore = await analysisWindow.boundingBox();
expect(mapBefore).not.toBeNull();
expect(analysisBefore).not.toBeNull();
expect(mapBefore!.width).toBeLessThan(analysisBefore!.width);
await page.mouse.move(mapBefore!.x + 72, mapBefore!.y + 22);
await page.keyboard.down("Alt");
await page.mouse.down();
await page.mouse.move(
analysisBefore!.x + analysisBefore!.width / 2,
analysisBefore!.y + analysisBefore!.height / 2,
{ steps: 10 }
);
await expect(page.getByText("释放以交换")).toBeVisible();
await page.mouse.up();
await page.keyboard.up("Alt");
const mapAfter = await mapWindow.boundingBox();
const analysisAfter = await analysisWindow.boundingBox();
expect(mapAfter).not.toBeNull();
expect(analysisAfter).not.toBeNull();
expect(mapAfter!.width).toBeGreaterThan(analysisAfter!.width);
expect(Math.abs(mapAfter!.x - analysisBefore!.x)).toBeLessThanOrEqual(2);
expect(Math.abs(analysisAfter!.x - mapBefore!.x)).toBeLessThanOrEqual(2);
await expect(page.getByText("供水管网地图与北辰分区压力异常诊断已交换位置")).toBeAttached();
});
test("dropping on blank workspace exits auto layout and Escape cancels a drag", async ({ page }) => {
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "测试打开 Agent 多图表窗口" }).first().click();
await applyTaskViewLayout(page, "双栏");
const workspace = page.locator("#main-workspace");
const analysisWindow = page.locator("section[aria-label='北辰分区压力异常诊断']");
const before = await analysisWindow.boundingBox();
const workspaceBox = await workspace.boundingBox();
const before = await workspace.boundingBox();
expect(before).not.toBeNull();
expect(workspaceBox).not.toBeNull();
await page.mouse.move(before!.x + 80, before!.y + 22);
await page.keyboard.down("Alt");
await page.mouse.down();
await page.mouse.move(workspaceBox!.x + 4, workspaceBox!.y + 4, { steps: 8 });
await page.keyboard.press("Escape");
await page.keyboard.up("Alt");
await expect(workspace).toHaveAttribute("data-layout-mode", "split");
const afterCancel = await analysisWindow.boundingBox();
expect(Math.abs(afterCancel!.x - before!.x)).toBeLessThanOrEqual(2);
await page.getByLabel(/展开 Agent 助手面板/).click();
await expect(page.getByLabel("Agent 命令面板")).toBeVisible();
const after = await workspace.boundingBox();
await page.mouse.move(before!.x + 80, before!.y + 22);
await page.keyboard.down("Alt");
await page.mouse.down();
await page.mouse.move(workspaceBox!.x + 4, workspaceBox!.y + 4, { steps: 8 });
await page.mouse.up();
await page.keyboard.up("Alt");
await expect(workspace).toHaveAttribute("data-layout-mode", "free");
await expect(page.getByText("北辰分区压力异常诊断已转为自由排列")).toBeAttached();
expect(after).not.toBeNull();
expect(after!.x).toBe(before!.x);
expect(after!.width).toBe(before!.width);
});
async function openWindowOperationMenu(page: Page, title: string) {
const window = page.locator(`section[aria-label='${title}']`);
await page.getByRole("button", { name: `切换到${title}` }).click();
await window.hover();
await page.getByRole("button", { name: `打开${title}窗口操作` }).click();
}
test("spatial Artifacts switch between split, focus and peek", async ({ page }) => {
await page.setViewportSize({ width: 1600, height: 900 });
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await openFirstArtifact(page);
async function applyTaskViewLayout(page: Page, layoutName: string) {
await page.getByRole("button", { name: "任务视图" }).click();
await page.getByRole("button", { name: new RegExp(`^${layoutName}`) }).click();
await page.getByRole("button", { name: "专注分析" }).click();
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "focus");
await expect(page.locator("#workspace-map")).toBeHidden();
await page.getByRole("button", { name: "显示地图" }).click();
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "map_split");
await expect(page.locator("#workspace-map")).toBeVisible();
await page.getByRole("button", { name: "将成果收起为预览" }).click();
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "default");
await expect(page.getByRole("complementary", { name: "Agent 成果预览" })).toBeVisible();
await expect(page.getByLabel("Agent 命令面板")).toBeVisible();
await page.getByRole("button", { name: "销毁预览成果" }).click();
await expect(page.getByRole("complementary", { name: "Agent 成果预览" })).toHaveCount(0);
await expect(page.locator("#workspace-map")).toBeVisible();
});
test("non-spatial Artifacts open directly in focus mode", async ({ page }) => {
await page.setViewportSize({ width: 1600, height: 900 });
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "生成 Agent 模拟分析成果" }).click();
await page.getByRole("button", { name: "销毁预览成果" }).click();
await page.getByRole("button", { name: "生成 Agent 模拟分析成果" }).click();
await page.getByRole("button", { name: "打开成果" }).click();
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "focus");
await expect(page.getByRole("heading", { name: "供水服务分区平衡分析" })).toBeVisible();
await expect(page.locator("#workspace-map")).toBeHidden();
await expect(page.getByRole("button", { name: "显示地图" })).toHaveCount(0);
});
test("narrow workspaces switch between Artifact and map as pages", async ({ page }) => {
await page.setViewportSize({ width: 1180, height: 820 });
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await openFirstArtifact(page);
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "focus");
await page.getByRole("button", { name: "显示地图" }).click();
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "map_only");
await expect(page.locator("#workspace-map")).toBeVisible();
await expect(page.locator("#artifact-workspace")).toBeHidden();
await page.getByRole("button", { name: "返回分析成果" }).click();
await expect(page.locator("#main-workspace")).toHaveAttribute("data-layout-mode", "focus");
await expect(page.locator("#artifact-workspace")).toBeVisible();
});
test("the condition feed remains floating and starts closed", async ({ page }) => {
await page.setViewportSize({ width: 1600, height: 900 });
await prepareMainFrame(page);
await page.goto("/", { waitUntil: "domcontentloaded" });
await expect(page.getByRole("region", { name: "工况任务", exact: true })).toHaveCount(0);
await page.getByRole("button", { name: "工况任务", exact: true }).click();
await expect(page.getByRole("region", { name: "工况任务", exact: true })).toBeVisible();
});
async function openFirstArtifact(page: Page) {
await page.getByRole("button", { name: "生成 Agent 模拟分析成果" }).click();
await page.getByRole("button", { name: "打开成果" }).click();
}
async function prepareMainFrame(page: Page) {