"""Account export -> restore round-trip, and account deletion.""" from tests.conftest import auth, register async def _seed(client, h): tid = (await client.post("/api/v1/trees", json={"name": "Fam"}, headers=h)).json()["id"] p1 = ( await client.post( f"/api/v1/trees/{tid}/persons", json={"given": "Ada", "surname": "Lovelace"}, headers=h ) ).json()["id"] p2 = ( await client.post(f"/api/v1/trees/{tid}/persons", json={"given": "Kid"}, headers=h) ).json()["id"] await client.post( f"/api/v1/trees/{tid}/relationships", json={"type": "parent_child", "person_from_id": p1, "person_to_id": p2}, headers=h, ) await client.post( f"/api/v1/trees/{tid}/events", json={"event_type": "birth", "person_id": p1, "date_value": "1815"}, headers=h, ) await client.post( f"/api/v1/trees/{tid}/media", files={"file": ("scan.txt", b"hello", "text/plain")}, data={"title": "Scan", "person_id": p1}, headers=h, ) return tid async def test_export_then_restore_roundtrip(client): h = auth(await register(client, "exp@example.com")) await _seed(client, h) export = await client.get("/api/v1/users/me/export", headers=h) assert export.status_code == 200 assert export.headers["content-type"] == "application/zip" blob = export.content assert blob[:2] == b"PK" # zip magic # Restore into new trees (non-destructive: the original stays). r = await client.post( "/api/v1/users/me/import", files={"file": ("provenance-export.zip", blob, "application/zip")}, headers=h, ) assert r.status_code == 200, r.text counts = r.json() assert counts["trees"] == 1 and counts["persons"] == 2 assert counts["events"] == 1 and counts["media"] == 1 trees = (await client.get("/api/v1/trees", headers=h)).json() assert len(trees) == 2 # original + restored # The restored tree has the people, with a working relationship and media. restored = [t for t in trees if t["name"] == "Fam"][1]["id"] ppl = (await client.get(f"/api/v1/trees/{restored}/persons", headers=h)).json() assert {p["primary_name"] for p in ppl} == {"Ada Lovelace", "Kid"} rels = (await client.get(f"/api/v1/trees/{restored}/relationships", headers=h)).json() assert len(rels) == 1 med = (await client.get(f"/api/v1/trees/{restored}/media", headers=h)).json() assert len(med) == 1 and med[0]["title"] == "Scan" async def test_delete_account_requires_email_then_revokes(client): token = await register(client, "del@example.com") h = auth(token) await _seed(client, h) # Wrong email is rejected. bad = await client.request( "DELETE", "/api/v1/users/me", data={"confirm_email": "nope@example.com"}, headers=h ) assert bad.status_code == 403 ok = await client.request( "DELETE", "/api/v1/users/me", data={"confirm_email": "del@example.com"}, headers=h ) assert ok.status_code == 204 # Session is revoked — the token no longer works. assert (await client.get("/api/v1/users/me", headers=h)).status_code == 401