fix(qa): 修 3 个 QA MEDIUM——规则/档位路由校验收紧

- 规则 GET 不存在 project → 404(原返误导性空 200,掩盖坏 id):list_rules 加
  项目存在校验(仿 C1/H2)。
- 规则 content 纯空白 → 422(原 strip 前校验 min_length,空白行入库成垃圾):
  改 StringConstraints(strip_whitespace=True, min_length=1)。
- 档位路由 tier 限定 writer/analyst/light(Tier Literal)→ 未知档位 422
  (原接受任意字符串)。

回归测试:test_generation(GET rules 404)/ test_rules(空白 content 422)/
test_settings_providers(未知 tier 422)。门禁绿:ruff/format/mypy(210)/pytest。
This commit is contained in:
Yaojia Wang
2026-06-24 17:51:02 +02:00
parent 7a40c7fbb5
commit 3868f80502
6 changed files with 49 additions and 5 deletions

View File

@@ -210,6 +210,16 @@ def _client(app: Any) -> httpx.AsyncClient:
return httpx.AsyncClient(transport=transport, base_url="http://test")
@pytest.mark.asyncio
async def test_list_rules_unknown_project_returns_404() -> None:
# QA MEDIUM 回归GET 规则列表对不存在 project 返 404原返误导性空 200掩盖坏 id
app, _ = _make_app(project_repo=FakeProjectRepo(), gateway=object())
async with _client(app) as client:
resp = await client.get(f"/projects/{uuid.uuid4()}/rules")
assert resp.status_code == 404
assert resp.json()["error"]["code"] == ErrorCode.NOT_FOUND
# ---- 世界观生成 ----

View File

@@ -99,6 +99,19 @@ async def test_create_rule_empty_content_returns_422() -> None:
assert resp.status_code == 422
@pytest.mark.asyncio
async def test_create_rule_whitespace_content_returns_422() -> None:
# QA MEDIUM 回归:纯空白 contentstrip 后为空)应 422不可入库成垃圾行。
client, repo, _session, _project_repo, pid = _make_client()
async with client:
resp = await client.post(
f"/projects/{pid}/rules",
json={"level": "project", "content": " "},
)
assert resp.status_code == 422
assert len(repo.rows) == 0
@pytest.mark.asyncio
async def test_create_rule_unknown_project_returns_404() -> None:
# QA H2 回归:给不存在的 project 加规则应 404不是 500 的 FK 违例逃逸)。

View File

@@ -91,3 +91,16 @@ def test_put_validation_rejects_blank_provider(client: TestClient) -> None:
json={"credentials": [{"provider": "", "api_key": "sk-x"}]},
)
assert resp.status_code == 422
def test_put_validation_rejects_unknown_tier(client: TestClient) -> None:
# QA MEDIUM 回归tier 限定 writer/analyst/light未知档位 → 422原接受任意字符串
resp = client.put(
"/settings/providers",
json={
"tier_routing": [
{"tier": "bogus", "provider": "deepseek", "model": "x", "fallback": []}
]
},
)
assert resp.status_code == 422