# ============================================================================== # Author: Simon-Pierre Boucher # File: tests/test_perimetre_qc.py # Desc: Périmètre québécois (§1-2) — garde QC de la boule de neige (les # profils reliés IG ramènent des vedettes mondiales sans filtre) et # rapprochement par compte identique dans sync_source (anti-doublons) # ============================================================================== """Régressions du 2026-08-20 : vedettes américaines + fiches en double. 1. snowball-ig émettait TOUS les profils reliés Instagram (cristiano, selenagomez, ferrari, nasa… — 3 767 fiches hors-périmètre en un passage). 2. `_find_existing` exigeait une confiance forte des DEUX côtés : une fiche à signal `mention` (0.60) n'était jamais retrouvée → sync_source créait une seconde fiche et l'upsert des comptes lui réassignait le compte, laissant l'originale orpheline (691 doublons). """ from creaka import db from creaka.connectors.snowball import SnowballConnector from creaka.identity import account from creaka.schema import Creator def _creator(name, accounts, **kw): return Creator(source="test", external_id="", display_name=name, platforms=accounts, **kw).finalize() def _source_avec_relies(related): acc = account("instagram", "createur.qc", "profil_source").finalize() acc.metrics["related_profiles"] = related return _creator("Créateur QC", [acc]) def test_snowball_ecarte_les_vedettes_mondiales(): src = _source_avec_relies([ {"username": "cristiano", "full_name": "Cristiano Ronaldo"}, {"username": "selenagomez", "full_name": "Selena Gomez"}, {"username": "ferrari", "full_name": "Ferrari"}, {"username": "nasa", "full_name": "NASA"}, ]) assert SnowballConnector().enrich([src]) == [] def test_marqueur_queb_exige_fin_de_mot(): # faux positifs constatés le 2026-08-20 : « queb » nu matchait dans # « quebra » (portugais) et « jacquebrazil » from creaka.connectors.youtube_recherche import is_quebec assert not is_quebec("tatiquebrabarraco Tati Quebra Barraco") assert not is_quebec("jacquebrazil") assert is_quebec("onlyqueb") # queb en fin de mot assert is_quebec("grainsduquebec") # quebec collé dans un handle assert is_quebec("Créatrice québécoise à Montréal") def test_snowball_ecarte_les_organismes_qc(): # revue du 2026-08-20 : villes, tourisme, ministères, partis, festivals… # portent des marqueurs QC mais ne sont pas des créateurs src = _source_avec_relies([ {"username": "villequebec", "full_name": "Ville de Québec"}, {"username": "tourismecharlevoix", "full_name": "Tourisme Charlevoix"}, {"username": "transports_quebec", "full_name": "Transports Québec"}, {"username": "justepourrirequebec", "full_name": "Juste pour rire"}, {"username": "humoriste.mtl", "full_name": "Humoriste MTL"}, ]) handles = {c.platforms[0].handle for c in SnowballConnector().enrich([src])} assert handles == {"humoriste.mtl"} def test_snowball_garde_les_profils_marques_qc(): src = _source_avec_relies([ {"username": "humoriste.mtl", "full_name": "Humoriste MTL"}, {"username": "chroniques.quebec", "full_name": "Chroniques"}, {"username": "katyperry", "full_name": "Katy Perry"}, ]) handles = {c.platforms[0].handle for c in SnowballConnector().enrich([src])} assert handles == {"humoriste.mtl", "chroniques.quebec"} def test_compte_identique_fusionne_jamais_de_doublon(tmp_path): con = db.connect(tmp_path / "t.db") faible = _creator("misslavoie", [account("instagram", "misslavoie", "mention")]) s1 = db.sync_source(con, "snowball-ig", [faible]) assert s1["added"] == 1 # ré-observation du MÊME compte avec signal fort (ex. enrichissement) : # la fiche existante est réutilisée, jamais de seconde fiche fort = _creator("Jade Lavoie", [account("instagram", "misslavoie", "profil_source")]) s2 = db.sync_source(con, "autre-source", [fort]) assert s2["added"] == 0 and s2["updated"] == 1 assert con.execute("SELECT count(*) FROM creators").fetchone()[0] == 1 # aucun orphelin : chaque fiche possède encore son compte orphans = con.execute( "SELECT count(*) FROM creators WHERE id NOT IN " "(SELECT creator_id FROM accounts)").fetchone()[0] assert orphans == 0