- src/muse 新版全模块(装配/共享/上下文/任务运行/作品规划/故事世界/正文写作/审校修订/知识方法/作者经验/效果评测/交付连载/资料研究/正式变更/元数据/接入/基础设施/编排)+ 测试树(单元/契约/集成/架构/迁移/端到端/夹具) - 129 项功能全部实现与自动验证(功能覆盖.json/矩阵),含 W31 补齐的规则与代价/节奏安排/伏笔与承诺 - 旧实现按处置清单退出(702 条中 324 删,保护合同与未迁移条目留存有据);web/app.py 旧工作台退役,新工作台为唯一写入口 - 数据库/旧库迁移:真实旧库内容批次迁移链(端点守卫/PG作品正文映射/质量资产缺省投影) - 运行手册 docs/运行手册.md;W30 本机服务阶段一已运行(infra PG 为正式内容权威) - R2 执行证据与私有运行材料在 .agents.local/改造/R2-20260909/(不入库)
118 lines
3.8 KiB
TypeScript
118 lines
3.8 KiB
TypeScript
import { afterEach, expect, it, vi } from "vitest";
|
||
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||
import { Ui独立比较 } from "../../src/功能/审校修订/独立比较";
|
||
afterEach(() => {
|
||
cleanup();
|
||
vi.unstubAllGlobals();
|
||
});
|
||
const record = {
|
||
receipt_id: "receipt-a",
|
||
proof: {
|
||
version: "revision-comparison-proof-v1",
|
||
source: {
|
||
session_id: "session-a",
|
||
round: 1,
|
||
candidate: { candidate_id: "candidate-a" },
|
||
},
|
||
outcome: "incomplete",
|
||
comparison_complete: false,
|
||
validation_modes: ["offline_contract"],
|
||
calibration_status: "uncalibrated",
|
||
decisions: [],
|
||
},
|
||
current: {
|
||
stopped: false,
|
||
selection: "original",
|
||
automatic_adoption: false,
|
||
reasons: ["unknown_cost"],
|
||
},
|
||
};
|
||
function answer(value: unknown) {
|
||
return new Response(JSON.stringify(value), {
|
||
headers: { "Content-Type": "application/json" },
|
||
});
|
||
}
|
||
it("NC-revision-proof-incomplete:缺判断和未标定保持可见,读取不派发或采纳", async () => {
|
||
const calls: Request[] = [];
|
||
vi.stubGlobal(
|
||
"fetch",
|
||
vi.fn(async (req: Request) => {
|
||
calls.push(req);
|
||
return answer(record);
|
||
}),
|
||
);
|
||
render(
|
||
<Ui独立比较 sessionId="session-a" round={1} candidateId="candidate-a" />,
|
||
);
|
||
expect(calls).toHaveLength(0);
|
||
fireEvent.change(screen.getByLabelText("比较回执编号"), {
|
||
target: { value: "receipt-a" },
|
||
});
|
||
fireEvent.click(screen.getByRole("button", { name: "核对比较记录" }));
|
||
await screen.findByText(/当前建议保留原文/);
|
||
expect(screen.getByText(/缺少完整独立判断/)).toBeTruthy();
|
||
expect(screen.getByText(/尚未经文学标定/)).toBeTruthy();
|
||
expect(screen.getByText(/只覆盖工程合同验证/)).toBeTruthy();
|
||
expect(calls).toHaveLength(1);
|
||
expect(calls[0].method).toBe("GET");
|
||
});
|
||
it("NC-revision-proof-scope:其他会话的证明不能显示为当前候选的建议", async () => {
|
||
vi.stubGlobal(
|
||
"fetch",
|
||
vi.fn(async () =>
|
||
answer({
|
||
...record,
|
||
proof: {
|
||
...record.proof,
|
||
source: { ...record.proof.source, session_id: "other-session" },
|
||
},
|
||
}),
|
||
),
|
||
);
|
||
render(
|
||
<Ui独立比较 sessionId="session-a" round={1} candidateId="candidate-a" />,
|
||
);
|
||
fireEvent.change(screen.getByLabelText("比较回执编号"), {
|
||
target: { value: "receipt-a" },
|
||
});
|
||
fireEvent.click(screen.getByRole("button", { name: "核对比较记录" }));
|
||
await screen.findByText(/返回记录与本次返修不一致/);
|
||
expect(screen.queryByText(/当前建议/)).toBeNull();
|
||
});
|
||
|
||
it("NC-revision-proof-selection:作者选段的二版比较记录仍绑定本轮确切候选", async () => {
|
||
vi.stubGlobal(
|
||
"fetch",
|
||
vi.fn(async () =>
|
||
answer({
|
||
...record,
|
||
proof: { ...record.proof, version: "revision-comparison-proof-v2" },
|
||
}),
|
||
),
|
||
);
|
||
render(
|
||
<Ui独立比较 sessionId="session-a" round={1} candidateId="candidate-a" />,
|
||
);
|
||
fireEvent.change(screen.getByLabelText("比较回执编号"), {
|
||
target: { value: "receipt-a" },
|
||
});
|
||
fireEvent.click(screen.getByRole("button", { name: "核对比较记录" }));
|
||
await screen.findByText(/当前建议保留原文/);
|
||
});
|
||
|
||
it("NC-revision-proof-candidate:同会话上一轮候选的证明不能冒充本轮结果", async () => {
|
||
vi.stubGlobal(
|
||
"fetch",
|
||
vi.fn(async () => answer(record)),
|
||
);
|
||
render(
|
||
<Ui独立比较 sessionId="session-a" round={2} candidateId="candidate-b" />,
|
||
);
|
||
fireEvent.change(screen.getByLabelText("比较回执编号"), {
|
||
target: { value: "receipt-a" },
|
||
});
|
||
fireEvent.click(screen.getByRole("button", { name: "核对比较记录" }));
|
||
await screen.findByText(/返回记录与本次返修不一致/);
|
||
expect(screen.queryByText(/当前建议/)).toBeNull();
|
||
});
|