Fix #169: keep citation links on GEDCOM export
Export emitted SOUR records but never the per-fact SOUR links, so a Provenance→Provenance round-trip destroyed the sources graph (citations were dropped). Emit citation links on the facts they sit on: - person-level → 1 SOUR @Sx@ (2 PAGE) - name-level → 2 SOUR under 1 NAME - event-level → 2 SOUR under the event (incl. partnership events in FAM) - relationship → 1 SOUR under FAM Citations whose source didn't export are skipped. Test: a person + event citation round-trips through export→import into a fresh tree with their pages intact. GEDCOM suite 6 passed. Closes #169 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Justin Paul <justin@jpaul.me>
This commit is contained in:
@@ -77,6 +77,58 @@ async def test_gedcom_export_and_reimport(client):
|
||||
assert resp.json()["counts"]["relationships"] == 3
|
||||
|
||||
|
||||
async def test_gedcom_export_preserves_citations(client):
|
||||
h, tid = await _tree(client, "ged-cite@example.com")
|
||||
pid = (
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid}/persons", json={"given": "Ada", "surname": "Vance"}, headers=h
|
||||
)
|
||||
).json()["id"]
|
||||
eid = (
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid}/events",
|
||||
json={"event_type": "birth", "person_id": pid, "date_value": "1898"},
|
||||
headers=h,
|
||||
)
|
||||
).json()["id"]
|
||||
sid = (
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid}/sources", json={"title": "1900 Census"}, headers=h
|
||||
)
|
||||
).json()["id"]
|
||||
# A person-level and an event-level citation on the same source.
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid}/citations",
|
||||
json={"source_id": sid, "person_id": pid, "page": "p.12"},
|
||||
headers=h,
|
||||
)
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid}/citations",
|
||||
json={"source_id": sid, "event_id": eid, "page": "line 5"},
|
||||
headers=h,
|
||||
)
|
||||
|
||||
text = (await client.get(f"/api/v1/trees/{tid}/gedcom/export", headers=h)).text
|
||||
# Citation links + pages are emitted (previously dropped).
|
||||
assert "1 SOUR @S1@" in text # person-level
|
||||
assert "2 PAGE p.12" in text
|
||||
assert "2 SOUR @S1@" in text # event-level (under 1 BIRT)
|
||||
assert "3 PAGE line 5" in text
|
||||
|
||||
# Round-trip into a fresh tree: the citations survive.
|
||||
tid2 = (await client.post("/api/v1/trees", json={"name": "RT"}, headers=h)).json()["id"]
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid2}/gedcom/import",
|
||||
files={"file": ("rt.ged", text.encode(), "text/plain")},
|
||||
headers=h,
|
||||
)
|
||||
cites = (await client.get(f"/api/v1/trees/{tid2}/citations", headers=h)).json()
|
||||
assert len(cites) >= 2
|
||||
assert any(c["person_id"] for c in cites)
|
||||
assert any(c["event_id"] for c in cites)
|
||||
assert {"p.12", "line 5"} <= {c.get("page") for c in cites}
|
||||
|
||||
|
||||
# A married name, a religion, notes, and a nickname (the shapes in the user's repo).
|
||||
RICH = b"""0 HEAD
|
||||
1 CHAR UTF-8
|
||||
|
||||
Reference in New Issue
Block a user