- src/muse 新版全模块(装配/共享/上下文/任务运行/作品规划/故事世界/正文写作/审校修订/知识方法/作者经验/效果评测/交付连载/资料研究/正式变更/元数据/接入/基础设施/编排)+ 测试树(单元/契约/集成/架构/迁移/端到端/夹具) - 129 项功能全部实现与自动验证(功能覆盖.json/矩阵),含 W31 补齐的规则与代价/节奏安排/伏笔与承诺 - 旧实现按处置清单退出(702 条中 324 删,保护合同与未迁移条目留存有据);web/app.py 旧工作台退役,新工作台为唯一写入口 - 数据库/旧库迁移:真实旧库内容批次迁移链(端点守卫/PG作品正文映射/质量资产缺省投影) - 运行手册 docs/运行手册.md;W30 本机服务阶段一已运行(infra PG 为正式内容权威) - R2 执行证据与私有运行材料在 .agents.local/改造/R2-20260909/(不入库)
135 lines
4.1 KiB
TypeScript
135 lines
4.1 KiB
TypeScript
/** 界面替身只验证确认与版本绑定,实际S02/PG证据另由集成用例提供。 */
|
||
import { afterEach, beforeEach, expect, it, vi } from "vitest";
|
||
import {
|
||
cleanup,
|
||
fireEvent,
|
||
render,
|
||
screen,
|
||
waitFor,
|
||
} from "@testing-library/react";
|
||
import { Ui方法详情 } from "../../src/功能/知识方法/方法详情";
|
||
|
||
const mocks = vi.hoisted(() => ({
|
||
get: vi.fn(),
|
||
post: vi.fn(),
|
||
refetch: vi.fn(),
|
||
}));
|
||
vi.mock("../../src/接口/生成/客户端", () => ({
|
||
客户端: { GET: mocks.get, POST: mocks.post },
|
||
}));
|
||
vi.mock("../../src/应用/作者会话", () => ({
|
||
useMuse作者会话: () => ({ data: {} }),
|
||
}));
|
||
vi.mock("../../src/功能/知识方法/数据", () => ({
|
||
useMuse方法类型: () => ({ data: [] }),
|
||
useMuse方法详情: () => ({
|
||
data: {
|
||
title: "动作表现迟疑",
|
||
state: "confirmed",
|
||
current_version: 3,
|
||
type_id: "craft",
|
||
owner: "synthetic",
|
||
versions: [],
|
||
evidence: { sources: [], counters: [], static_refs: [] },
|
||
},
|
||
isPending: false,
|
||
refetch: mocks.refetch,
|
||
}),
|
||
}));
|
||
beforeEach(() => {
|
||
vi.clearAllMocks();
|
||
mocks.get.mockResolvedValue({
|
||
data: {
|
||
payload: {
|
||
target: { version: "3" },
|
||
valid_until: "2030-01-01T00:00:00Z",
|
||
},
|
||
},
|
||
});
|
||
mocks.post.mockResolvedValue({ data: { receipt_id: "receipt" } });
|
||
mocks.refetch.mockResolvedValue({});
|
||
});
|
||
afterEach(cleanup);
|
||
|
||
it("NC-ui-method-enable:核对具体凭据后由作者启用当前版本", async () => {
|
||
render(<Ui方法详情 methodId="method-a" />);
|
||
const enable = screen.getByRole("button", {
|
||
name: "确认启用写手用途",
|
||
}) as HTMLButtonElement;
|
||
expect(enable.disabled).toBe(true);
|
||
fireEvent.change(screen.getByLabelText("启用凭据编号"), {
|
||
target: { value: "proof-a" },
|
||
});
|
||
fireEvent.click(screen.getByRole("button", { name: "核对已测版本" }));
|
||
await waitFor(() => expect(enable.disabled).toBe(false));
|
||
expect(mocks.post).not.toHaveBeenCalled();
|
||
fireEvent.click(enable);
|
||
await waitFor(() => expect(mocks.refetch).toHaveBeenCalledTimes(1));
|
||
expect(mocks.post).toHaveBeenCalledWith(
|
||
"/api/v1/methods/{method_id}/state",
|
||
expect.objectContaining({
|
||
body: expect.objectContaining({
|
||
method_id: "method-a",
|
||
expected_state_revision: 3,
|
||
启用凭据: "proof-a",
|
||
action: "enable",
|
||
}),
|
||
}),
|
||
);
|
||
expect(enable.disabled).toBe(true);
|
||
});
|
||
|
||
it("NC-ui-method-proof-scope:换方法或修改凭据后旧核对不再放行", async () => {
|
||
const view = render(<Ui方法详情 methodId="method-a" />);
|
||
fireEvent.change(screen.getByLabelText("启用凭据编号"), {
|
||
target: { value: "proof-a" },
|
||
});
|
||
fireEvent.click(screen.getByRole("button", { name: "核对已测版本" }));
|
||
await waitFor(() =>
|
||
expect(
|
||
(
|
||
screen.getByRole("button", {
|
||
name: "确认启用写手用途",
|
||
}) as HTMLButtonElement
|
||
).disabled,
|
||
).toBe(false),
|
||
);
|
||
view.rerender(<Ui方法详情 methodId="method-b" />);
|
||
expect(
|
||
(
|
||
screen.getByRole("button", {
|
||
name: "确认启用写手用途",
|
||
}) as HTMLButtonElement
|
||
).disabled,
|
||
).toBe(true);
|
||
fireEvent.change(screen.getByLabelText("启用凭据编号"), {
|
||
target: { value: "proof-b" },
|
||
});
|
||
expect(
|
||
(
|
||
screen.getByRole("button", {
|
||
name: "确认启用写手用途",
|
||
}) as HTMLButtonElement
|
||
).disabled,
|
||
).toBe(true);
|
||
expect(mocks.post).not.toHaveBeenCalled();
|
||
});
|
||
|
||
it("NC-ui-method-proof-error:失效凭据的拒绝可见且不触发启用", async () => {
|
||
mocks.get.mockResolvedValue({ error: { message: "标定来源已停止" } });
|
||
render(<Ui方法详情 methodId="method-a" />);
|
||
fireEvent.change(screen.getByLabelText("启用凭据编号"), {
|
||
target: { value: "stopped" },
|
||
});
|
||
fireEvent.click(screen.getByRole("button", { name: "核对已测版本" }));
|
||
await screen.findByText("标定来源已停止");
|
||
expect(
|
||
(
|
||
screen.getByRole("button", {
|
||
name: "确认启用写手用途",
|
||
}) as HTMLButtonElement
|
||
).disabled,
|
||
).toBe(true);
|
||
expect(mocks.post).not.toHaveBeenCalled();
|
||
});
|