fix(qa): 修 QA C1/H1/H2——写章/规则缺项目校验 + 立项向导字段覆盖
C1 (CRITICAL) stream_draft:对不存在 project 流式写章先 fail-fast 404, 否则非法 id 静默烧一次付费/限流 LLM 调用并返 200。在触网关前查 project_repo.get。 H2 (HIGH) create_rule:给不存在 project 加规则原 FK 违例逃逸成 500 → 改为入库前 校验项目存在返 404(仿 chain/_require_project)。 H1 (HIGH) ProjectWizard:第3步「立意」与第4步「主角/金手指」原共用 form.premise 互相覆盖丢数据 → 新增独立 form.protagonist,toCreateRequest 合并两段进 premise (M1 projects 表仍只有 premise,不编造 API)。 回归测试: - test_projects.py:stream_draft 不存在 project → 404 且网关零调用;已有 draft 用例改 seed 真项目。 - test_rules.py:create_rule 不存在 project → 404 不写库;已有用例 seed 真项目。 - wizard.test.ts:premise+protagonist 合并不互相覆盖(2 例)。 门禁绿:ruff/format clean · mypy 210 · pytest 749 · 前端 tsc/lint/vitest 干净。
This commit is contained in:
@@ -44,6 +44,7 @@ describe("toCreateRequest", () => {
|
||||
sellingPoints: ["逆袭", "系统流"],
|
||||
structure: "三幕",
|
||||
premise: " ",
|
||||
protagonist: "",
|
||||
theme: "抗争",
|
||||
};
|
||||
expect(toCreateRequest(form)).toEqual({
|
||||
@@ -56,6 +57,30 @@ describe("toCreateRequest", () => {
|
||||
structure: "三幕",
|
||||
});
|
||||
});
|
||||
|
||||
// QA H1 回归:立意(premise)与主角/金手指(protagonist)是两个独立输入,
|
||||
// 不能互相覆盖——提交时各占一段合并进 premise。
|
||||
it("merges premise and protagonist into premise without overwriting", () => {
|
||||
const form: WizardForm = {
|
||||
...emptyWizardForm,
|
||||
title: "书",
|
||||
premise: "凡人逆袭的代价",
|
||||
protagonist: "主角林川,金手指=吞噬术,限制:每次吞噬折寿",
|
||||
};
|
||||
const req = toCreateRequest(form);
|
||||
expect(req.premise).toBe(
|
||||
"凡人逆袭的代价\n\n主角/金手指:主角林川,金手指=吞噬术,限制:每次吞噬折寿",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps protagonist alone when premise is empty", () => {
|
||||
const form: WizardForm = {
|
||||
...emptyWizardForm,
|
||||
title: "书",
|
||||
protagonist: "主角设定",
|
||||
};
|
||||
expect(toCreateRequest(form).premise).toBe("主角/金手指:主角设定");
|
||||
});
|
||||
});
|
||||
|
||||
// wizard→create 流程:归一后的请求体经 mock 客户端提交,返回新建项目 id。
|
||||
|
||||
Reference in New Issue
Block a user