state-hub/tests/test_intake.py
tegwick 059de9358e
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 23s
feat(consistency): rebuild authoritative intake IDs
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
2026-08-22 12:23:43 +02:00

168 lines
6.6 KiB
Python

"""Tests for the `intake` work-record entity (CUST-WP-0061-T01, work-record
stage 3). Real PostgreSQL test database, no mocking — matches
tests/test_routers_core.py conventions.
"""
from __future__ import annotations
import pytest
async def _create_domain(client, slug="testdomain", name="Test Domain"):
r = await client.post("/domains/", json={"slug": slug, "name": name})
assert r.status_code == 201, r.text
return r.json()
async def _create_topic(client, domain_slug="testdomain", slug="testtopic", title="Test Topic"):
r = await client.post("/topics/", json={
"slug": slug, "title": title, "domain": domain_slug,
})
assert r.status_code == 201, r.text
return r.json()
async def _create_intake(client, topic_id=None, workplan_id=None, repo_id=None,
title="Qonto MCP mailing", lane="green", **extra):
payload = {"title": title, "lane": lane, **extra}
if topic_id is not None:
payload["topic_id"] = topic_id
if workplan_id is not None:
payload["workplan_id"] = workplan_id
if repo_id is not None:
payload["repo_id"] = repo_id
r = await client.post("/intakes/", json=payload)
assert r.status_code == 201, r.text
return r.json()
class TestIntakeCreateAndRead:
async def test_create_requires_a_scope(self, client):
r = await client.post("/intakes/", json={"title": "orphan intake", "lane": "green"})
assert r.status_code == 422
async def test_create_with_topic_scope(self, client):
await _create_domain(client)
topic = await _create_topic(client)
body = await _create_intake(client, topic_id=topic["id"])
assert body["status"] == "open"
assert body["lane"] == "green"
assert body["outcome"] is None
async def test_create_preserves_explicit_authoritative_id(self, client):
await _create_domain(client)
topic = await _create_topic(client)
expected = "11111111-1111-4111-8111-111111111111"
r = await client.post(
"/intakes/",
json={"id": expected, "title": "file intake", "topic_id": topic["id"]},
)
assert r.status_code == 201
assert r.json()["id"] == expected
async def test_get_unknown_intake_404s(self, client):
r = await client.get("/intakes/00000000-0000-0000-0000-000000000000")
assert r.status_code == 404
async def test_list_filters_by_topic(self, client):
await _create_domain(client)
topic = await _create_topic(client)
other_topic = await _create_topic(client, slug="other-topic", title="Other")
await _create_intake(client, topic_id=topic["id"], title="in scope")
await _create_intake(client, topic_id=other_topic["id"], title="out of scope")
r = await client.get("/intakes/", params={"topic_id": topic["id"]})
assert r.status_code == 200
titles = [i["title"] for i in r.json()]
assert titles == ["in scope"]
class TestIntakeLifecycle:
async def test_route_moves_open_to_routed(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"])
r = await client.post(f"/intakes/{intake['id']}/route", json={"routed_note": "green lane, ready"})
assert r.status_code == 200
assert r.json()["status"] == "routed"
assert r.json()["routed_note"] == "green lane, ready"
async def test_route_from_closed_is_rejected(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"])
await client.post(f"/intakes/{intake['id']}/close", json={"outcome": "declined"})
r = await client.post(f"/intakes/{intake['id']}/route", json={})
assert r.status_code == 409
async def test_close_declined_does_not_require_promoted_to(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"])
r = await client.post(f"/intakes/{intake['id']}/close", json={"outcome": "declined"})
assert r.status_code == 200
body = r.json()
assert body["status"] == "closed"
assert body["outcome"] == "declined"
assert body["closed_at"] is not None
async def test_close_promoted_without_promoted_to_is_rejected(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"])
r = await client.post(f"/intakes/{intake['id']}/close", json={"outcome": "promoted"})
assert r.status_code == 422
async def test_close_promoted_with_promoted_to_succeeds(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"], title="AWQ-010")
r = await client.post(
f"/intakes/{intake['id']}/close",
json={"outcome": "promoted", "promoted_to": "BINKY-WP-0005"},
)
assert r.status_code == 200
body = r.json()
assert body["outcome"] == "promoted"
assert body["promoted_to"] == "BINKY-WP-0005"
async def test_close_already_closed_is_rejected(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"])
await client.post(f"/intakes/{intake['id']}/close", json={"outcome": "declined"})
r = await client.post(f"/intakes/{intake['id']}/close", json={"outcome": "absorbed"})
assert r.status_code == 409
class TestIntakeNotes:
async def test_add_note_appears_on_intake(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"])
r = await client.post(
f"/intakes/{intake['id']}/notes",
json={"content": "vetted, looks real", "author": "agt-rhythm-bridge"},
)
assert r.status_code == 201
notes = r.json()["notes"]
assert len(notes) == 1
assert notes[0]["content"] == "vetted, looks real"
assert notes[0]["author"] == "agt-rhythm-bridge"
class TestIntakeUUIDv7:
async def test_id_is_uuidv7(self, client):
await _create_domain(client)
topic = await _create_topic(client)
intake = await _create_intake(client, topic_id=topic["id"])
import uuid
u = uuid.UUID(intake["id"])
assert u.version == 7