Add the core labeling data model (label sets, ad-hoc Main->Sub class hierarchy, frames, bounding-box labels, per-frame/per-set label status) behind a FastAPI app, with SQLite as the default swappable DATABASE_URL. Multi-user support is attribution-only for now (get-or-create by username, no login flow yet). Dataset versioning/promotion is intentionally deferred - it needs its own design pass around snapshot semantics. Each test gets a fully isolated app+DB via create_app(database_url=...) rather than relying on process-global state. 13/13 tests pass; also verified live end-to-end against a running uvicorn instance. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
48 lines
1.7 KiB
Python
48 lines
1.7 KiB
Python
def test_create_and_list_sets(client):
|
|
resp = client.post("/sets", json={"name": "Enemy", "description": "Enemy sprites"})
|
|
assert resp.status_code == 201
|
|
|
|
resp = client.get("/sets")
|
|
assert resp.status_code == 200
|
|
assert [s["name"] for s in resp.json()] == ["Enemy"]
|
|
|
|
|
|
def test_create_set_rejects_duplicate_name(client):
|
|
client.post("/sets", json={"name": "Enemy"})
|
|
resp = client.post("/sets", json={"name": "Enemy"})
|
|
assert resp.status_code == 409
|
|
|
|
|
|
def test_get_missing_set(client):
|
|
resp = client.get("/sets/999")
|
|
assert resp.status_code == 404
|
|
|
|
|
|
def test_create_main_and_sub_class(client):
|
|
set_id = client.post("/sets", json={"name": "Enemy"}).json()["id"]
|
|
|
|
resp = client.post(f"/sets/{set_id}/main-classes", json={"name": "Enemy"})
|
|
assert resp.status_code == 201
|
|
main_class_id = resp.json()["id"]
|
|
|
|
resp = client.post(f"/main-classes/{main_class_id}/sub-classes", json={"name": "Bat"})
|
|
assert resp.status_code == 201
|
|
assert resp.json()["name"] == "Bat"
|
|
|
|
resp = client.get(f"/sets/{set_id}")
|
|
assert resp.json()["main_classes"][0]["sub_classes"][0]["name"] == "Bat"
|
|
|
|
|
|
def test_main_class_requires_existing_set(client):
|
|
resp = client.post("/sets/999/main-classes", json={"name": "Enemy"})
|
|
assert resp.status_code == 404
|
|
|
|
|
|
def test_sub_class_rejects_duplicate_name_under_same_main_class(client):
|
|
set_id = client.post("/sets", json={"name": "Enemy"}).json()["id"]
|
|
main_class_id = client.post(f"/sets/{set_id}/main-classes", json={"name": "Enemy"}).json()["id"]
|
|
client.post(f"/main-classes/{main_class_id}/sub-classes", json={"name": "Bat"})
|
|
|
|
resp = client.post(f"/main-classes/{main_class_id}/sub-classes", json={"name": "Bat"})
|
|
assert resp.status_code == 409
|