""" Topics API tests — async only (Plan 05 cutover). Legacy sync tests (using the flat-file storage layer and sync TestClient) were updated to async in Plan 05 to match the new session-injected API routes. """ from __future__ import annotations async def test_list_topics_empty(async_client): resp = await async_client.get("/api/topics") assert resp.status_code == 200 assert resp.json()["topics"] == [] async def test_create_topic(async_client): resp = await async_client.post( "/api/topics", json={"name": "Finance", "description": "Financial docs", "color": "#ff0000"}, ) assert resp.status_code == 200 data = resp.json() assert data["name"] == "Finance" assert data["color"] == "#ff0000" assert "id" in data async def test_create_topic_deduplication(async_client): await async_client.post("/api/topics", json={"name": "Finance"}) resp = await async_client.post("/api/topics", json={"name": "finance"}) # case-insensitive assert resp.status_code == 200 topics = (await async_client.get("/api/topics")).json()["topics"] assert len(topics) == 1 async def test_update_topic(async_client): create = (await async_client.post("/api/topics", json={"name": "Old Name"})).json() resp = await async_client.patch(f"/api/topics/{create['id']}", json={"name": "New Name"}) assert resp.status_code == 200 assert resp.json()["name"] == "New Name" async def test_update_topic_not_found(async_client): resp = await async_client.patch( "/api/topics/00000000-0000-0000-0000-000000000000", json={"name": "X"}, ) assert resp.status_code == 404 async def test_delete_topic(async_client): create = (await async_client.post("/api/topics", json={"name": "ToDelete"})).json() resp = await async_client.delete(f"/api/topics/{create['id']}") assert resp.status_code == 200 assert resp.json()["success"] is True topics = (await async_client.get("/api/topics")).json()["topics"] assert not any(t["name"] == "ToDelete" for t in topics) async def test_delete_topic_cascades_to_documents(async_client, db_session, sample_txt): # Create a topic topic = (await async_client.post("/api/topics", json={"name": "Legal"})).json() # Upload doc (no auto classify) with open(sample_txt, "rb") as f: upload = ( await async_client.post( "/api/documents/upload", files={"file": ("sample.txt", f, "text/plain")}, data={"auto_classify": "false"}, ) ).json() # Manually set topic via the storage service from services import storage await storage.update_document_topics(db_session, upload["id"], ["Legal"]) # Delete topic await async_client.delete(f"/api/topics/{topic['id']}") # Verify document no longer has the topic doc = (await async_client.get(f"/api/documents/{upload['id']}")).json() assert "Legal" not in doc["topics"] async def test_delete_topic_not_found(async_client): resp = await async_client.delete("/api/topics/nonexistent") assert resp.status_code == 404