feat: strengthen backup and mobile workflows
ci / gitleaks (push) Successful in 1m19s
ci / docker (push) Successful in 5m48s

This commit is contained in:
2026-09-16 21:12:52 +08:00
parent 6f38190c92
commit 6c234d7d82
64 changed files with 5059 additions and 635 deletions
+7 -7
View File
@@ -204,7 +204,7 @@ def test_countdowns_backup_replace_and_merge_round_trip(client):
assert next(item for item in exported["countdowns"] if item["title"] == "旧日")["archived_at"]
create_countdown(client, title="干扰数据")
restored = client.post("/api/v1/restore", params={"mode": "replace"}, json=exported)
restored = client.post("/api/v1/restore", params={"mode": "merge"}, json=exported)
assert restored.status_code == 200
restored_active = next(item for item in client.get("/api/v1/countdowns").json() if item["title"] == "周年")
assert restored_active["calendar_mode"] == "lunar"
@@ -261,7 +261,7 @@ def test_countdown_backup_merge_remaps_ids_owned_by_another_user(client):
assert len(client.get("/api/v1/countdowns").json()) == 1
exported_by_other = client.get("/api/v1/export").json()
restored_again = client.post("/api/v1/restore", params={"mode": "replace"}, json=exported_by_other)
restored_again = client.post("/api/v1/restore", params={"mode": "merge"}, json=exported_by_other)
assert restored_again.status_code == 200
replaced = client.get("/api/v1/countdowns").json()
assert len(replaced) == 1
@@ -335,20 +335,20 @@ def test_restore_rejects_malformed_countdowns_atomically(client):
malformed = deepcopy(exported)
malformed["countdowns"][0]["archived_at"] = "not-a-date"
response = client.post("/api/v1/restore", params={"mode": "replace"}, json=malformed)
response = client.post("/api/v1/restore", params={"mode": "merge"}, json=malformed)
assert response.status_code == 422
assert [item["id"] for item in client.get("/api/v1/countdowns").json()] == [original["id"]]
for invalid in (None, 7):
malformed = deepcopy(exported)
malformed["countdowns"] = invalid
response = client.post("/api/v1/restore", params={"mode": "replace"}, json=malformed)
response = client.post("/api/v1/restore", params={"mode": "merge"}, json=malformed)
assert response.status_code == 422
assert [item["id"] for item in client.get("/api/v1/countdowns").json()] == [original["id"]]
duplicate = deepcopy(exported)
duplicate["countdowns"].append(deepcopy(duplicate["countdowns"][0]))
response = client.post("/api/v1/restore", params={"mode": "replace"}, json=duplicate)
response = client.post("/api/v1/restore", params={"mode": "merge"}, json=duplicate)
assert response.status_code == 422
assert [item["id"] for item in client.get("/api/v1/countdowns").json()] == [original["id"]]
@@ -359,7 +359,7 @@ def test_restore_rejects_malformed_countdowns_atomically(client):
two_pinned["countdowns"][0]["pinned"] = True
extra["pinned"] = True
two_pinned["countdowns"].append(extra)
response = client.post("/api/v1/restore", params={"mode": "replace"}, json=two_pinned)
response = client.post("/api/v1/restore", params={"mode": "merge"}, json=two_pinned)
assert response.status_code == 200
assert sum(item["pinned"] for item in client.get("/api/v1/countdowns").json()) == 1
@@ -407,7 +407,7 @@ def test_restore_accepts_lunar_dates_whose_solar_anchor_is_in_next_year(client):
assert created.json()["event_date"] == "2002-02-01"
exported = client.get("/api/v1/export").json()
restored = client.post("/api/v1/restore", params={"mode": "replace"}, json=exported)
restored = client.post("/api/v1/restore", params={"mode": "merge"}, json=exported)
assert restored.status_code == 200
item = client.get("/api/v1/countdowns").json()[0]
assert item["event_date"] == "2002-02-01"