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 干净。
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
"""chain_deps._libpq_conn_string 单测——剥离 SQLAlchemy 驱动后缀(回归)。
|
||
|
||
bug:runtime checkpointer 工厂曾把 `postgresql+psycopg://…`(settings 的 sync URL)
|
||
原样喂给 `AsyncPostgresSaver.from_conn_string`,psycopg 不识别 `+psycopg` 方言段 →
|
||
`ProgrammingError: missing "=" …` → 多章链 job 直接 failed。E2E 用 MemorySaver 覆盖,
|
||
从不走真 conn string,故此路径无回归保护。本用例锁住「剥离后缀」语义。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import pytest
|
||
from ww_api.services import chain_deps
|
||
|
||
|
||
class _StubSettings:
|
||
def __init__(self, url: str) -> None:
|
||
self.database_url_sync = url
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
("raw", "expected"),
|
||
[
|
||
(
|
||
"postgresql+psycopg://writer:writer@localhost:5432/writer",
|
||
"postgresql://writer:writer@localhost:5432/writer",
|
||
),
|
||
("postgresql+asyncpg://u:p@h:5432/db", "postgresql://u:p@h:5432/db"),
|
||
("postgresql://u:p@h:5432/db", "postgresql://u:p@h:5432/db"),
|
||
],
|
||
)
|
||
def test_libpq_conn_string_strips_driver_suffix(
|
||
monkeypatch: pytest.MonkeyPatch, raw: str, expected: str
|
||
) -> None:
|
||
# Arrange
|
||
monkeypatch.setattr(chain_deps, "get_settings", lambda: _StubSettings(raw))
|
||
# Act
|
||
result = chain_deps._libpq_conn_string()
|
||
# Assert
|
||
assert result == expected
|
||
assert "+psycopg" not in result
|
||
assert "+asyncpg" not in result
|