TICKET-008 (backend): POST /api/foods/{id}/restore — idempotent, history intact

This commit is contained in:
Craig
2026-07-26 17:45:11 +01:00
parent ce91852321
commit 0c239cdbd4
3 changed files with 107 additions and 0 deletions
+81
View File
@@ -432,3 +432,84 @@ def test_recent_limit_enforced(client):
"""limit > 50 should be rejected."""
resp = client.get("/api/foods/recent?limit=100")
assert resp.status_code == 422
# ── Restore endpoint (TICKET-008, spec §3.1) ─────────────────────────────────
def test_restore_clears_deleted_flag(client):
"""POST /api/foods/{id}/restore clears deleted_at on a soft-deleted food."""
resp = create_food(client, name="RestoreMe")
fid = resp.json()["id"]
client.delete(f"/api/foods/{fid}")
resp = client.post(f"/api/foods/{fid}/restore")
assert resp.status_code == 200, resp.text
assert resp.json()["deleted_at"] is None
# Confirm via GET
resp = client.get(f"/api/foods/{fid}")
assert resp.json()["deleted_at"] is None
def test_restore_404_unknown_id(client):
resp = client.post("/api/foods/99999/restore")
assert resp.status_code == 404
def test_restore_not_deleted_is_sensible(client):
"""Restoring a food that isn't deleted returns it unchanged (idempotent)."""
resp = create_food(client, name="NeverDeleted")
fid = resp.json()["id"]
resp = client.post(f"/api/foods/{fid}/restore")
assert resp.status_code == 200, resp.text
assert resp.json()["id"] == fid
assert resp.json()["deleted_at"] is None
def test_restore_reappears_in_search(client):
"""A restored food shows up in default search again."""
resp = create_food(client, name="RestoreSearchable")
fid = resp.json()["id"]
client.delete(f"/api/foods/{fid}")
resp = client.get("/api/foods", params={"q": "RestoreSearchable"})
assert not any(f["id"] == fid for f in resp.json())
client.post(f"/api/foods/{fid}/restore")
resp = client.get("/api/foods", params={"q": "RestoreSearchable"})
assert any(f["id"] == fid for f in resp.json())
def test_restore_preserves_history(client):
"""Restoring does not touch nutrition fields or created_at (history intact)."""
resp = create_food(client, name="RestoreHistory", calories_per_unit=321.0)
fid = resp.json()["id"]
created_at = resp.json()["created_at"]
client.delete(f"/api/foods/{fid}")
resp = client.post(f"/api/foods/{fid}/restore")
data = resp.json()
assert data["calories_per_unit"] == 321.0
assert data["created_at"] == created_at
def test_restore_still_visible_in_historical_log(client):
"""A food soft-deleted and restored still renders in old log entries (§2.1)."""
resp = create_food(client, name="RestoreLog", calories_per_unit=100.0)
fid = resp.json()["id"]
log_resp = client.post("/api/log", json={
"food_id": fid, "quantity": 200.0, "date": "2026-07-26",
})
assert log_resp.status_code == 201, log_resp.text
client.delete(f"/api/foods/{fid}")
client.post(f"/api/foods/{fid}/restore")
resp = client.get("/api/log", params={"date": "2026-07-26"})
entries = [e for e in resp.json() if e["food_id"] == fid]
assert entries, "log entry missing after delete/restore"
assert entries[0]["food"]["name"] == "RestoreLog"
assert entries[0]["computed_nutrition"]["calories"] == 200.0