- 上下文清单、任务列表与详情、恢复控制、运行观察、创作对话与消息流、正式变更决策面板、正文写作与候选审阅、资料研究等页面同步本轮后端能力。 - 事件标签表补齐后端事件类型;查询键与生成客户端随 HTTP 契约重新生成。 - 依赖调整后 lockfile 同步;交互用例与浏览器旅程 spec 一并更新。 - 证据:make 前端检查(lint + typecheck + Pi 工具桥 tsc)exit 0;make 前端测试 37 文件 / 120 用例通过。
64 lines
3.2 KiB
TypeScript
64 lines
3.2 KiB
TypeScript
/** 真 HTTP/PG 与真实浏览器;模型交付由隔离环境的合成宿主预先产生。 */
|
||
import { readFileSync, writeFileSync } from "node:fs";
|
||
import { expect, test } from "@playwright/test";
|
||
|
||
test.use({ trace: "off" });
|
||
|
||
// @muse-case {"case_id":"NC-browser-planning-shadow","environment":"真实浏览器与隔离HTTP/PG;不代表真实模型","given":"已授权隔离环境及预先完成的受控规划交付","when":"浏览器创建新任务并确认已有模型候选","then":["真实创建任务仅显示已创建;模型候选经作者点击确认后才成为正式规划"],"contract":"docs/系统架构/新版设计/模块设计/B01-作品规划.md"}
|
||
test("NC-browser-planning-shadow:创建真实任务与确认模型规划候选", async ({
|
||
page,
|
||
}, info) => {
|
||
if (!process.env.MUSE_WORKBENCH_URL || !process.env.MUSE_AUTHOR_PASSWORD_FILE)
|
||
throw new Error("需要隔离后端和作者口令文件,不连接默认服务。");
|
||
const errors: string[] = [];
|
||
page.on("pageerror", (e) => errors.push(String(e)));
|
||
await page.goto("/");
|
||
await page
|
||
.getByLabel("访问口令")
|
||
.fill(readFileSync(process.env.MUSE_AUTHOR_PASSWORD_FILE, "utf8").trim());
|
||
await page.getByRole("button", { name: "进入工作台" }).click();
|
||
await page.getByRole("link", { name: /任务记录/ }).waitFor();
|
||
page.on("console", (m) => {
|
||
if (m.type() === "error" && !/favicon/.test(m.text()))
|
||
errors.push(m.text());
|
||
});
|
||
await page.goto("/works/gen-work/plans?node=ch-3&schema=fine_outline");
|
||
await expect(page.getByText(/模型规划 · 待决定/)).toBeVisible();
|
||
await page.getByLabel("规划要求").fill("保留本章方向,再比较一个承接方案");
|
||
await page.getByLabel("规划模型配置").fill("plan-config");
|
||
const 要求框 = await page.getByLabel("规划要求").boundingBox();
|
||
const 配置框 = await page.getByLabel("规划模型配置").boundingBox();
|
||
if (!要求框 || !配置框) throw new Error("规划输入控件不可见");
|
||
expect(配置框.y).toBeGreaterThan(要求框.y + 要求框.height);
|
||
const created = page.waitForResponse(
|
||
(r) =>
|
||
r.url().endsWith("/planning-tasks") && r.request().method() === "POST",
|
||
);
|
||
await page.getByRole("button", { name: "创建规划任务" }).click();
|
||
const response = await created;
|
||
expect(response.status()).toBe(201);
|
||
const receipt = await response.json();
|
||
await expect(
|
||
page.getByText(new RegExp("任务已创建:" + receipt.task_id)),
|
||
).toBeVisible();
|
||
await page.screenshot({
|
||
path: `${info.outputDir}/规划任务与模型候选.png`,
|
||
fullPage: true,
|
||
});
|
||
await page.getByRole("button", { name: /模型规划 · 待决定/ }).click();
|
||
await page.getByRole("button", { name: "确认这份规划", exact: true }).click();
|
||
await expect(
|
||
page.getByText("这份规划已确认。", { exact: true }),
|
||
).toBeVisible();
|
||
await expect(page.getByText(/模型规划 · 已确认/)).toBeVisible();
|
||
await page.screenshot({
|
||
path: `${info.outputDir}/规划确认结果.png`,
|
||
fullPage: true,
|
||
});
|
||
writeFileSync(
|
||
`${info.outputDir}/规划回执.json`,
|
||
JSON.stringify({ created_task_id: receipt.task_id }),
|
||
);
|
||
expect(errors, "不得有页面异常或未预期的接口失败").toEqual([]);
|
||
});
|