"""Tests de l'assainissement PII des données capturées (titres, texte, OCR). Couche 1 (sans modèle) : filet regex sur la PII structurée (IPP, NIR, TEL, EMAIL, AGE) + règles structurelles cliniques (NOM (NAISSANCE) Prénom ; [Nom Prénom] des fenêtres PACS), avec tokens TYPÉS et COHÉRENTS ([IPP_1]…). Réutilise l'approche du projet `anonymisation` (placeholders + regex). La couche NER (noms libres) viendra en complément. Cas réels remontés en clinique le 28/06 (anonymisés ici par construction). Branche feat/push-log-dgx. """ from __future__ import annotations import sys from pathlib import Path _ROOT = str(Path(__file__).resolve().parents[2]) if _ROOT not in sys.path: sys.path.insert(0, _ROOT) def test_ipp_et_age_tokenises(): from agent_v0.server_v1.pii_sanitizer import anonymize_text titre = "VIOLA (VIOLA) Liliane 90 ans - IPP: 168246 - Expert Sante - Mozilla Firefox" out, ents = anonymize_text(titre) assert "168246" not in out, out # IPP retiré assert "[IPP_1]" in out assert "90 ans" not in out # âge retiré assert "[AGE_1]" in out # le nom format clinique « NOM (NAISSANCE) Prénom » est tokenisé assert "VIOLA" not in out and "Liliane" not in out, out assert "[NOM_1]" in out # le logiciel n'est pas pris pour de la PII assert "Firefox" in out and "Expert Sante" in out types = {e["type"] for e in ents} assert {"IPP", "AGE", "NOM"} <= types def test_nom_entre_crochets_pacs(): """Le PACS met le patient entre crochets : `[DATTIN Alix]`.""" from agent_v0.server_v1.pii_sanitizer import anonymize_text titre = "GXD5 Pacs 4.0.4.307 CIM ARES - [DATTIN Alix] - Mozilla Firefox" out, _ = anonymize_text(titre) assert "DATTIN" not in out and "Alix" not in out, out assert "[NOM_1]" in out assert "Pacs" in out and "Firefox" in out # contexte logiciel préservé def test_coherence_meme_ipp_meme_token(): """Même valeur PII -> même token (sur un mapping partagé de session).""" from agent_v0.server_v1.pii_sanitizer import anonymize_text mapping: dict = {} o1, _ = anonymize_text("IPP: 168246 ouvert", mapping=mapping) o2, _ = anonymize_text("dossier IPP: 168246 fermé", mapping=mapping) o3, _ = anonymize_text("IPP: 270020 autre", mapping=mapping) assert "[IPP_1]" in o1 and "[IPP_1]" in o2 # même patient -> même token assert "[IPP_2]" in o3 # patient différent -> token différent assert "270020" not in o3 def test_email_et_telephone(): from agent_v0.server_v1.pii_sanitizer import anonymize_text out, _ = anonymize_text("contact j.dupont@chu.fr / 06 12 34 56 78") assert "@chu.fr" not in out and "[EMAIL_1]" in out assert "06 12 34 56 78" not in out and "[TEL_1]" in out def test_texte_sans_pii_inchange(): from agent_v0.server_v1.pii_sanitizer import anonymize_text t = "Expert Sante - Consultation - Mozilla Firefox" out, ents = anonymize_text(t) assert out == t assert ents == []