feat(01-05): final cutover — delete data/, prune config.py, async-only tests
- Delete backend/data/ tracked files (D-04): flat-file metadata, settings.json, topics.json, and uploaded files removed from git; backend/data/ added to .gitignore (empty dir remains on macOS due to ACL — no tracked files remain) - Prune backend/config.py: remove DATA_DIR, UPLOADS_DIR, METADATA_DIR, TOPICS_FILE, ensure_data_dirs(); rebase SETTINGS_FILE as derived path from settings.data_dir (Phase 1 flat-file settings kept per plan decision) - Prune backend/tests/conftest.py: remove isolated_data_dir autouse fixture and sync TestClient client fixture; add SQLite type compatibility shim (visit_INET/JSONB) so in-memory db_session can create tables with PostgreSQL-specific column types; add live_services_available fixture - Rewrite backend/tests/test_documents.py: delete all legacy sync tests, remove all @pytest.mark.xfail markers; async-only document tests now use async_client + storage service directly for topic wiring - Rewrite backend/tests/test_health.py: delete legacy sync test_health(client); remove @pytest.mark.xfail from test_health_checks_postgres_and_minio - Port backend/tests/test_topics.py to async_client (sync client removed) - Port backend/tests/test_settings.py to async_client with monkeypatch for SETTINGS_FILE isolation (settings remain flat-file in Phase 1)
This commit is contained in:
@@ -1,11 +1,23 @@
|
||||
def test_list_topics_empty(client):
|
||||
resp = client.get("/api/topics")
|
||||
"""
|
||||
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"] == []
|
||||
|
||||
|
||||
def test_create_topic(client):
|
||||
resp = client.post("/api/topics", json={"name": "Finance", "description": "Financial docs", "color": "#ff0000"})
|
||||
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"
|
||||
@@ -13,60 +25,66 @@ def test_create_topic(client):
|
||||
assert "id" in data
|
||||
|
||||
|
||||
def test_create_topic_deduplication(client):
|
||||
client.post("/api/topics", json={"name": "Finance"})
|
||||
resp = client.post("/api/topics", json={"name": "finance"}) # case-insensitive
|
||||
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 = client.get("/api/topics").json()["topics"]
|
||||
topics = (await async_client.get("/api/topics")).json()["topics"]
|
||||
assert len(topics) == 1
|
||||
|
||||
|
||||
def test_update_topic(client):
|
||||
create = client.post("/api/topics", json={"name": "Old Name"}).json()
|
||||
resp = client.patch(f"/api/topics/{create['id']}", json={"name": "New Name"})
|
||||
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"
|
||||
|
||||
|
||||
def test_update_topic_not_found(client):
|
||||
resp = client.patch("/api/topics/nonexistent", json={"name": "X"})
|
||||
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
|
||||
|
||||
|
||||
def test_delete_topic(client):
|
||||
create = client.post("/api/topics", json={"name": "ToDelete"}).json()
|
||||
resp = client.delete(f"/api/topics/{create['id']}")
|
||||
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 = client.get("/api/topics").json()["topics"]
|
||||
topics = (await async_client.get("/api/topics")).json()["topics"]
|
||||
assert not any(t["name"] == "ToDelete" for t in topics)
|
||||
|
||||
|
||||
def test_delete_topic_cascades_to_documents(client, sample_txt):
|
||||
async def test_delete_topic_cascades_to_documents(async_client, db_session, sample_txt):
|
||||
# Create a topic
|
||||
topic = client.post("/api/topics", json={"name": "Legal"}).json()
|
||||
topic = (await async_client.post("/api/topics", json={"name": "Legal"})).json()
|
||||
|
||||
# Upload doc (no auto classify to control topics manually)
|
||||
# Upload doc (no auto classify)
|
||||
with open(sample_txt, "rb") as f:
|
||||
upload = client.post(
|
||||
"/api/documents/upload",
|
||||
files={"file": ("sample.txt", f, "text/plain")},
|
||||
data={"auto_classify": "false"},
|
||||
upload = (
|
||||
await async_client.post(
|
||||
"/api/documents/upload",
|
||||
files={"file": ("sample.txt", f, "text/plain")},
|
||||
data={"auto_classify": "false"},
|
||||
)
|
||||
).json()
|
||||
|
||||
# Manually set topic on the document via classify endpoint
|
||||
import services.storage as st
|
||||
st.update_document_topics(upload["id"], ["Legal"])
|
||||
# Manually set topic via the storage service
|
||||
from services import storage
|
||||
|
||||
await storage.update_document_topics(db_session, upload["id"], ["Legal"])
|
||||
|
||||
# Delete topic
|
||||
client.delete(f"/api/topics/{topic['id']}")
|
||||
await async_client.delete(f"/api/topics/{topic['id']}")
|
||||
|
||||
# Verify document no longer has the topic
|
||||
doc = client.get(f"/api/documents/{upload['id']}").json()
|
||||
doc = (await async_client.get(f"/api/documents/{upload['id']}")).json()
|
||||
assert "Legal" not in doc["topics"]
|
||||
|
||||
|
||||
def test_delete_topic_not_found(client):
|
||||
resp = client.delete("/api/topics/nonexistent")
|
||||
async def test_delete_topic_not_found(async_client):
|
||||
resp = await async_client.delete("/api/topics/nonexistent")
|
||||
assert resp.status_code == 404
|
||||
|
||||
Reference in New Issue
Block a user