# ============================================================================== # Author: Simon-Pierre Boucher # File: tests/test_db.py # Desc: Tests de la persistance — upsert, détection de changements, délai de # grâce (2 syncs), dérive, clé de déduplication inter-sources. # ============================================================================== from __future__ import annotations from sortika import db from sortika.schema import Event def _ev(eid="1", title="Fête au parc", price="Gratuit", source="sitq"): return Event(source=source, external_id=eid, url=f"https://x/{eid}", title=title, city="Québec", tourist_region="Québec", start_date="2027-01-15", price_label=price).finalize() def test_sync_lifecycle(tmp_path): con = db.connect(tmp_path / "t.db") s = db.sync_source(con, "sitq", [_ev()]) assert (s["added"], s["removed"]) == (1, 0) # inchangé s = db.sync_source(con, "sitq", [_ev()]) assert (s["added"], s["updated"], s["unchanged"]) == (0, 0, 1) # changement de contenu détecté s = db.sync_source(con, "sitq", [_ev(price="Adulte 10 $")]) assert s["updated"] == 1 row = con.execute("SELECT is_free, price_min FROM events").fetchone() assert (row["is_free"], row["price_min"]) == (0, 10.0) # disparition : grâce au 1er raté, retrait au 2e s = db.sync_source(con, "sitq", []) assert s["removed"] == 0 s = db.sync_source(con, "sitq", []) assert s["removed"] == 1 assert con.execute("SELECT active FROM events").fetchone()[0] == 0 def test_drift_suspends_removals(tmp_path): con = db.connect(tmp_path / "t.db") batch = [_ev(eid=str(i), title=f"Événement {i}") for i in range(20)] for _ in range(3): db.sync_source(con, "sitq", batch) # chute brutale à 2 événements → alerte, aucun retrait s = db.sync_source(con, "sitq", batch[:2]) assert "alert" in s and s["removed"] == 0 n = con.execute("SELECT COUNT(*) FROM events WHERE active=1").fetchone()[0] assert n == 20 def test_dedup_key_cross_source(): a = _ev(source="sitq", title="Grand marché de Noël") b = Event(source="montreal", external_id="99", url="https://y", title=" GRAND MARCHÉ de Noël ", city="Québec", start_date="2027-01-15").finalize() assert a.dedup_key() == b.dedup_key() assert a.dedup_key() != _ev(title="Autre événement").dedup_key()