feat(tests): pytest-asyncio test suite — 119 tests across 3 modules

Infrastructure (T01):
- tests/conftest.py: sync schema setup (psycopg2), per-test table
  truncation, async ASGI client with get_session override
- pyproject.toml: [tool.pytest.ini_options] asyncio_mode=auto
- Makefile: make test target with TEST_DATABASE_URL

Core router tests (T02): 19 tests
- domains, topics, workstreams, tasks, decisions + state summary
- Caught real bug: topic router missing duplicate-slug 409 guard (fixed)

TD/EP/Contributions/SBOM tests (T03): 10 tests
- CRUD + status transitions + lifecycle guard + SBOM ingest

MCP smoke tests (T04): 12 tests
- get_state_summary, create_task, update_task_status,
  add_progress_event, flag_for_human HTTP shapes

CI gate (T05): make test documented in CLAUDE.md session protocol

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-18 12:00:06 +01:00
parent 2522464ced
commit 75d25e9d3b
7 changed files with 798 additions and 1 deletions

View File

@@ -40,6 +40,9 @@ async def create_topic(
session: AsyncSession = Depends(get_session),
) -> Topic:
domain_id = await _resolve_domain_id(body.domain, session)
existing = await session.execute(select(Topic).where(Topic.slug == body.slug))
if existing.scalar_one_or_none():
raise HTTPException(status_code=409, detail=f"Topic slug '{body.slug}' already exists")
topic = Topic(
slug=body.slug,
title=body.title,