LazyBoy2/tests/agent_profile_ui.mjs

130 lines
5.4 KiB
JavaScript
Raw Normal View History

2026-09-15 09:07:16 +00:00
import { chromium } from "../tools/playwright/node_modules/playwright/index.mjs";
import assert from "node:assert/strict";
import { mkdirSync } from "node:fs";
const outDir = "/tmp/lazyboy2-agent-profile-ui";
mkdirSync(outDir, { recursive: true });
const owner = {
id: "owner",
name: "測試",
title: "市場研究員",
description: "用白話講研究結果",
tags: ["研究"],
avatar_color: "#08A99D",
avatar_shape: "round",
expertise: "市場研究員 — 研究 — 用白話講研究結果",
preview: "任務結束了",
running: false,
};
const agents = [owner];
let patched = null;
let created = null;
const browser = await chromium.launch({ headless: true });
try {
const context = await browser.newContext({ locale: "zh-TW" });
const page = await context.newPage();
page.setDefaultTimeout(8000);
await page.addInitScript(() => {
localStorage.setItem("lazyboy.locale", "zh-Hant");
localStorage.setItem("lazyboy.theme", "dark");
});
await page.emulateMedia({ colorScheme: "dark" });
page.on("pageerror", (e) => console.error(e.message));
await page.route("**/api/**", async (route) => {
const req = route.request();
const path = new URL(req.url()).pathname;
if (path === "/api/agents" && req.method() === "GET") {
return route.fulfill({ json: { agents } });
}
if (path === "/api/agents" && req.method() === "POST") {
created = JSON.parse(req.postData() || "{}");
const row = { id: "newbie", preview: "新對話", running: false, ...created };
agents.unshift(row);
return route.fulfill({ json: row });
}
const agentMatch = path.match(/^\/api\/agents\/([^/]+)$/);
if (agentMatch && req.method() === "PATCH") {
patched = JSON.parse(req.postData() || "{}");
const current = agents.find((row) => row.id === agentMatch[1]) || owner;
Object.assign(current, patched);
return route.fulfill({ json: current });
}
if (agentMatch && req.method() === "GET") {
const current = agents.find((row) => row.id === agentMatch[1]) || owner;
return route.fulfill({
json: {
...current,
transcript: current.id === "owner"
? [
{ role: "user", content: "幫我查一下", at: new Date().toISOString() },
{ role: "assistant", content: "任務結束了", at: new Date().toISOString() },
]
: [],
activity: { state: "idle", running: false, queued: false, active_task_ids: [], observed_at_ms: Date.now() },
},
});
}
if (path.endsWith("/activity")) {
return route.fulfill({
json: { state: "idle", running: false, queued: false, active_task_ids: [], observed_at_ms: Date.now() },
});
}
if (path.endsWith("/events")) {
return route.fulfill({ contentType: "text/event-stream", body: "data: {\"events\":[]}\n\n" });
}
2026-09-16 06:40:00 +00:00
if (path.endsWith("/computer")) {
return route.fulfill({ json: { ready: true, state: "ready", viewer_url: "/fixture-viewer" } });
}
2026-09-15 09:07:16 +00:00
return route.fulfill({ json: {} });
});
await page.goto(process.env.LAZYBOY_TEST_UI_URL || "http://127.0.0.1:5173");
const row = page.locator(".bot-row").filter({ hasText: "測試" });
await row.waitFor();
assert.match(await row.locator("small").innerText(), /任務結束了/);
assert.equal(await row.locator(".bot-tag").innerText(), "研究");
await page.screenshot({ path: `${outDir}/sidebar.png` });
await row.click({ button: "right" });
await page.getByRole("menuitem", { name: "Agent 設定" }).click();
const dialog = page.locator(".settings-dialog");
await dialog.waitFor();
await dialog.getByLabel("名稱").waitFor();
assert.equal(await dialog.locator(".shape-grid button").count(), 0);
await dialog.locator(".avatar-hit").click();
assert.equal(await dialog.locator(".shape-grid button").count(), 8);
await dialog.getByRole("tab", { name: "上傳" }).waitFor();
await dialog.locator(".dialog-title").click();
await dialog.getByLabel("名稱").waitFor();
assert.equal(await dialog.locator(".shape-grid button").count(), 0);
await dialog.locator("textarea").fill("用更短的句子回答");
await dialog.getByRole("button", { name: "儲存" }).click();
await dialog.waitFor({ state: "hidden" });
assert.equal(patched?.description, "用更短的句子回答");
assert.equal(patched?.name, "測試");
await page.screenshot({ path: `${outDir}/saved.png` });
await page.locator(".create-menu-wrap .icon-button").click();
await page.getByRole("menuitem", { name: "新增 Agent" }).click();
const create = page.locator(".settings-dialog");
const createBtn = create.getByRole("button", { name: "建立" });
assert.equal(await createBtn.isDisabled(), true);
await create.getByLabel("名稱").fill("小研");
assert.equal(await createBtn.isDisabled(), true);
await create.getByLabel("描述").fill("用白話講研究結果");
await create.getByLabel("標題").fill("市場研究員");
await create.getByLabel("標籤(選填)").fill("研究");
await createBtn.click();
await create.waitFor({ state: "hidden" });
assert.equal(created?.name, "小研");
assert.equal(created?.description, "用白話講研究結果");
assert.equal(created?.title, "市場研究員");
assert.deepEqual(created?.tags, ["研究"]);
await page.locator(".bot-row").filter({ hasText: "小研" }).waitFor();
await page.screenshot({ path: `${outDir}/created.png` });
console.log("agent_profile_ui ok");
} finally {
await browser.close();
}