Files
董宏凯 8c3d6a02fc feat: 业务链条发布审核流程 + 编辑器去除岗位职责输入框
- 发布改为可选「确认审核 / 直接发布」:链条编辑页与圆桌「业务链条」弹窗行为一致;审核中可撤回
- 管理员在业务链条列表新增「待审核」筛选,审核发布后进入公共库
- 后端 roundtable_chains 新增 pending_review 字段(启动期自动补列)与 scope=pending 筛选;新增审核流程测试
- 编辑器席位去掉「岗位职责」输入框(保存时存量值原样保留)
2026-08-25 17:30:29 +08:00

103 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""业务链条「发布审核」流程测试。
覆盖:
- store:``pending_review`` 随 create(缺省 False)/ update 持久化;
- store:``scope="pending"`` 仅管理员返回全部待审核链条;非管理员按 ``mine`` 退化;
- 完整审核流:owner 提交审核 → 管理员在 pending 列表看到 → 发布(``is_public=True`` +
``pending_review=False``)后从 pending 列表消失、进入 public 列表。
"""
from __future__ import annotations
import pytest
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
async def _make_repo():
from deerflow.persistence.base import Base
from deerflow.persistence.roundtable_chains.model import RoundtableChainRow # noqa: F401 注册表
from deerflow.persistence.roundtable_chains.sql import RoundtableChainRepository
engine = create_async_engine("sqlite+aiosqlite:///:memory:")
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
sf = async_sessionmaker(engine, expire_on_commit=False)
return RoundtableChainRepository(sf), engine
_SEATS = [
{"agent_id": "a", "name": "情报收集", "description": ""},
{"agent_id": "b", "name": "环境评估", "description": ""},
]
@pytest.mark.asyncio
async def test_pending_review_flag_roundtrip():
repo, engine = await _make_repo()
try:
row = await repo.create_chain("u1", {"id": "c1", "title": "链", "seats": _SEATS})
# 缺省 False。
assert row["pending_review"] is False
# owner 提交审核 → True。
updated = await repo.update_chain("c1", "u1", pending_review=True)
assert updated is not None and updated["pending_review"] is True
# 撤回 / 管理员发布清回 → False。
updated = await repo.update_chain("c1", "u1", pending_review=False)
assert updated is not None and updated["pending_review"] is False
finally:
await engine.dispose()
@pytest.mark.asyncio
async def test_scope_pending_lists_all_users_pending_for_admin():
repo, engine = await _make_repo()
try:
await repo.create_chain("u1", {"id": "c1", "title": "U1 待审", "seats": _SEATS})
await repo.create_chain("u1", {"id": "c2", "title": "U1 草稿", "seats": _SEATS})
await repo.create_chain("u2", {"id": "c3", "title": "U2 待审", "seats": _SEATS})
await repo.update_chain("c1", "u1", pending_review=True)
await repo.update_chain("c3", "u2", pending_review=True)
# 管理员 pending → 只含两条待审核链条(跨账号)。
rows = await repo.list_chains("admin", scope="pending", is_admin=True)
assert {r["id"] for r in rows} == {"c1", "c3"}
# 非管理员误传 pending(is_admin=False)→ 退化为 mine:只见自己的(c1/c2),
# 绝不越权看到他人待审核链条。
rows = await repo.list_chains("u1", scope="pending", is_admin=False)
assert {r["id"] for r in rows} == {"c1", "c2"}
finally:
await engine.dispose()
@pytest.mark.asyncio
async def test_full_review_flow_owner_submit_admin_publish():
repo, engine = await _make_repo()
try:
await repo.create_chain("u1", {"id": "c1", "title": "走审核的链", "seats": _SEATS})
# ① owner 提交审核。
await repo.update_chain("c1", "u1", pending_review=True)
# ② 管理员在「待审核」列表看到。
pending = await repo.list_chains("admin", scope="pending", is_admin=True)
assert [r["id"] for r in pending] == ["c1"]
# ③ 管理员审核发布:is_public=True + 清除待审核标记。
published = await repo.update_chain(
"c1", "admin", is_public=True, pending_review=False, is_admin=True
)
assert published is not None
assert published["is_public"] is True
assert published["pending_review"] is False
# owner 不变。
assert published["owner_id"] == "u1"
# ④ 发布后:pending 列表为空,public 列表可见(任何账号)。
assert await repo.list_chains("admin", scope="pending", is_admin=True) == []
public = await repo.list_chains("u2", scope="public")
assert [r["id"] for r in public] == ["c1"]
finally:
await engine.dispose()