101 lines
6.8 KiB
TypeScript
101 lines
6.8 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { mockAgentApi } from "./support/mock-agent-api";
|
|
import { mockWorkbenchContext } from "./support/mock-workbench-context";
|
|
import { TEST_PROJECT_ID } from "./support/mock-scada-api";
|
|
import { readColorAlpha } from "./support/theme-colors";
|
|
|
|
for (const width of [320, 375, 400, 640]) {
|
|
test(`conversation title and topic stay distinct at ${width}px`, async ({ page }, testInfo) => {
|
|
const mobile = width < 400;
|
|
await page.setViewportSize({ width: mobile ? width : 1440, height: 900 });
|
|
await page.emulateMedia({ reducedMotion: "reduce" });
|
|
await mockWorkbenchContext(page);
|
|
const title = "安徽省兴安农牧科技发展有限公司,附近选取不同管道核对供水压力、流量与阀门状态";
|
|
const topicName = "兴安农牧供水异常事件与管道压力问题持续跟踪复核";
|
|
const session = { id: "long-context", session_id: "long-context", title, topic_id: "long-topic", updated_at: Date.now(), created_at: Date.now() };
|
|
await mockAgentApi(page, { sessions: [session] });
|
|
const projectHeaders: string[] = [];
|
|
await page.route("**/api/v1/topics", async (route) => {
|
|
if (route.request().method() === "OPTIONS") return route.fallback();
|
|
projectHeaders.push((await route.request().allHeaders())["x-project-id"]);
|
|
return route.fulfill({ headers: { "Access-Control-Allow-Origin": "*" }, json: { topics: [
|
|
{ id: "long-topic", name: topicName, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }
|
|
] } });
|
|
});
|
|
await page.route("**/api/v1/session/long-context?**", (route) => {
|
|
if (route.request().method() === "OPTIONS") return route.fallback();
|
|
return route.fulfill({ headers: { "Access-Control-Allow-Origin": "*" }, json: {
|
|
...session, purpose: "ordinary_chat", messages: [], is_streaming: false
|
|
} });
|
|
});
|
|
await page.goto("/", { waitUntil: "domcontentloaded" });
|
|
await page.getByRole("button", { name: mobile ? "打开 Agent 面板" : /展开 Agent 助手面板/ }).click();
|
|
const panel = page.getByRole("complementary", { name: "Agent 命令面板" });
|
|
if (!mobile) {
|
|
await page.getByRole("separator", { name: "调整 Agent 面板宽度" }).focus();
|
|
await page.keyboard.press(width === 400 ? "Home" : "End");
|
|
}
|
|
await panel.getByRole("button", { name: "打开 Agent 历史记录" }).click();
|
|
await page.getByRole("dialog", { name: "历史对话", exact: true }).locator(".agent-history-session-trigger").filter({ hasText: title }).click();
|
|
const context = panel.locator(".agent-chat-context-bar");
|
|
const titleElement = context.getByText(title, { exact: true });
|
|
const header = panel.locator(".agent-panel-header");
|
|
const topic = header.getByRole("button", { name: "选择主题", exact: true });
|
|
await expect(topic).toHaveText(topicName);
|
|
await expect(topic).toHaveAccessibleDescription(topicName);
|
|
await expect(context.getByRole("button")).toHaveCount(0);
|
|
await expect(panel.getByText("主题", { exact: true })).toHaveCount(0);
|
|
await expect(topic.locator("svg.lucide-folder")).toBeVisible();
|
|
const contextBox = (await context.boundingBox())!;
|
|
const titleBox = (await titleElement.boundingBox())!;
|
|
const topicBox = (await topic.boundingBox())!;
|
|
expect(titleBox.width).toBeGreaterThanOrEqual(contextBox.width - 26);
|
|
expect(titleBox.height).toBeGreaterThanOrEqual(20);
|
|
if (width < 640) expect(titleBox.height).toBeGreaterThan(20);
|
|
expect(titleBox.height).toBeLessThanOrEqual(40);
|
|
expect(titleBox.y).toBeGreaterThanOrEqual(topicBox.y + topicBox.height);
|
|
const headerBox = (await header.boundingBox())!;
|
|
const navigationBox = (await header.locator("..").boundingBox())!;
|
|
const nameBox = (await header.getByText("供水助手", { exact: true }).boundingBox())!;
|
|
const statusBox = (await header.getByRole("status").boundingBox())!;
|
|
const dividerBox = (await panel.locator("[data-agent-header-divider]").boundingBox())!;
|
|
const actionsBox = (await header.getByRole("group", { name: "对话操作" }).boundingBox())!;
|
|
expect(statusBox.x).toBeGreaterThanOrEqual(nameBox.x + nameBox.width);
|
|
await expect(header.getByRole("status")).toHaveText("在线");
|
|
expect(await header.getByRole("status").evaluate((element) => element.scrollWidth <= element.clientWidth)).toBe(true);
|
|
expect(statusBox.x + statusBox.width).toBeLessThanOrEqual(actionsBox.x - 6);
|
|
expect(Math.abs(statusBox.y + statusBox.height / 2 - nameBox.y - nameBox.height / 2)).toBeLessThanOrEqual(1);
|
|
expect(topicBox.y).toBeGreaterThanOrEqual(nameBox.y + nameBox.height + 6);
|
|
expect(dividerBox.height).toBe(1);
|
|
expect(readColorAlpha(await panel.locator("[data-agent-header-divider]").evaluate((element) => getComputedStyle(element).backgroundColor))).toBeLessThanOrEqual(0.5);
|
|
await expect(context).toHaveCSS("border-bottom-width", "0px");
|
|
expect(titleBox.y).toBeGreaterThanOrEqual(dividerBox.y + dividerBox.height + 12);
|
|
expect(topicBox.x + topicBox.width).toBeLessThanOrEqual(actionsBox.x - 8);
|
|
expect(contextBox.y + contextBox.height - navigationBox.y).toBeLessThanOrEqual(146);
|
|
expect(topicBox.x + topicBox.width).toBeLessThanOrEqual(contextBox.x + contextBox.width - 10);
|
|
expect(await context.evaluate((element) => element.scrollWidth <= element.clientWidth)).toBe(true);
|
|
await topic.click();
|
|
const menu = page.getByRole("menu");
|
|
await expect(menu.getByRole("menuitemradio", { name: topicName, exact: true })).toBeChecked();
|
|
await expect(menu.getByRole("menuitemradio", { name: "未分类", exact: true })).not.toBeChecked();
|
|
await expect(page.getByRole("menuitem", { name: "新建主题", exact: true })).toBeVisible();
|
|
const menuBox = (await menu.boundingBox())!;
|
|
expect(Math.abs(menuBox.x - topicBox.x)).toBeLessThanOrEqual(1);
|
|
expect(menuBox.x + menuBox.width).toBeLessThanOrEqual(mobile ? width : 1440);
|
|
await menu.screenshot({ path: `test-results/agent-context/topic-menu-${width}.png` });
|
|
await page.keyboard.press("Escape");
|
|
await expect(topic).toBeFocused();
|
|
expect(projectHeaders.length).toBeGreaterThan(0);
|
|
expect(projectHeaders.every((id) => id === TEST_PROJECT_ID)).toBe(true);
|
|
await testInfo.attach("context-geometry", { contentType: "application/json", body: JSON.stringify({ width, headerBox, navigationBox, contextBox, titleBox, topicBox, statusBox, dividerBox, actionsBox }) });
|
|
await titleElement.click();
|
|
await panel.screenshot({ path: `test-results/agent-context/context-${width}.png` });
|
|
await topic.click();
|
|
await page.getByRole("menuitemradio", { name: "未分类", exact: true }).click();
|
|
await expect(topic).toHaveText("未分类");
|
|
await topic.click();
|
|
await page.getByRole("menuitemradio", { name: topicName, exact: true }).click();
|
|
await expect(topic).toHaveText(topicName);
|
|
});
|
|
}
|