- 上下文清单、任务列表与详情、恢复控制、运行观察、创作对话与消息流、正式变更决策面板、正文写作与候选审阅、资料研究等页面同步本轮后端能力。 - 事件标签表补齐后端事件类型;查询键与生成客户端随 HTTP 契约重新生成。 - 依赖调整后 lockfile 同步;交互用例与浏览器旅程 spec 一并更新。 - 证据:make 前端检查(lint + typecheck + Pi 工具桥 tsc)exit 0;make 前端测试 37 文件 / 120 用例通过。
71 lines
3.4 KiB
TypeScript
71 lines
3.4 KiB
TypeScript
import { readFileSync } from "node:fs";
|
||
import { expect, test } from "@playwright/test";
|
||
|
||
// @muse-case {"case_id":"NC-browser-dynamic-world","environment":"隔离PG/合成HTTP及浏览器","given":"具名作者、固定来源、隔离测试配置与真实模块存储","when":"通过实际公开入口执行并核对拒绝、状态及持久结果","then":["NC-browser-dynamic-world:新类型具名编辑确认后刷新并再次修改"],"contract":"docs/系统架构/新版设计/模块设计/B02-故事世界.md#作者实体表单与字段提案"}
|
||
test("NC-browser-dynamic-world:新类型具名编辑确认后刷新并再次修改", async ({
|
||
page,
|
||
}, info) => {
|
||
const password = process.env.MUSE_AUTHOR_PASSWORD_FILE;
|
||
const work = process.env.MUSE_WORK_ID;
|
||
if (!password || !work) throw new Error("需要隔离作者和作品");
|
||
await page.goto(`/works/${work}/world`);
|
||
await page.getByLabel("访问口令").fill(readFileSync(password, "utf8").trim());
|
||
await page.getByRole("button", { name: "进入工作台" }).click();
|
||
await page.goto(`/works/${work}/world`);
|
||
await page
|
||
.getByRole("combobox", { name: "资料类型", exact: true })
|
||
.selectOption("port_cost");
|
||
await page.getByRole("button", { name: "添加资料", exact: true }).click();
|
||
await page.getByLabel(/^规矩名称/).fill("过河的规矩");
|
||
await page.getByLabel("渡河代价", { exact: true }).fill("留下一段记忆");
|
||
await page.getByRole("button", { name: "保存为待决资料" }).click();
|
||
const review = page.getByRole("region", { name: "事实审阅" });
|
||
await expect(
|
||
review.getByText("留下一段记忆", { exact: true }).first(),
|
||
).toBeVisible();
|
||
await expect(
|
||
page
|
||
.getByRole("region", { name: "实体清单" })
|
||
.getByText("0 个对象", { exact: true }),
|
||
).toBeVisible();
|
||
await review.getByRole("button", { name: "核对当前作品并打开决定" }).click();
|
||
await review.getByRole("button", { name: "确认这份资料" }).click();
|
||
await expect(
|
||
page
|
||
.getByRole("region", { name: "实体清单" })
|
||
.getByText("1 个对象", { exact: true }),
|
||
).toBeVisible();
|
||
await page.reload();
|
||
await page
|
||
.getByRole("region", { name: "实体清单" })
|
||
.getByRole("button", { name: /过河的规矩/ })
|
||
.click();
|
||
await page.getByRole("button", { name: "编辑资料", exact: true }).click();
|
||
await expect(page.getByLabel("渡河代价", { exact: true })).toHaveValue(
|
||
"留下一段记忆",
|
||
);
|
||
await page.getByLabel("渡河代价", { exact: true }).fill("一枚旧铜钱");
|
||
await page.getByRole("button", { name: "保存为待决资料" }).click();
|
||
await expect(
|
||
review.getByText("一枚旧铜钱", { exact: true }).first(),
|
||
).toBeVisible();
|
||
await review.getByRole("button", { name: "核对当前作品并打开决定" }).click();
|
||
await review.getByRole("button", { name: "确认这份资料" }).click();
|
||
await expect(
|
||
page
|
||
.getByRole("region", { name: "实体清单" })
|
||
.getByRole("button", { name: /r2/ }),
|
||
).toBeVisible();
|
||
await expect(
|
||
page.getByRole("region", { name: "版本轨迹" }).getByText(/r2/),
|
||
).toBeVisible();
|
||
await expect(review.getByText(/尚未生效/)).toHaveCount(0);
|
||
await expect(
|
||
review.getByRole("listitem").filter({ hasText: "渡河代价" }),
|
||
).toHaveText("渡河代价:留下一段记忆 → 一枚旧铜钱");
|
||
await page.screenshot({
|
||
path: info.outputPath("动态资料编辑与确认.png"),
|
||
fullPage: true,
|
||
});
|
||
});
|