Kazeia-central/tests/test_questionnaires.py

71 lines
3.0 KiB
Python

"""Tests feature Questionnaires : PHQ-9 fourni, authoring QCM, scoring, assignation,
résultats chiffrés dans le dossier patient."""
import nacl.pwhash
from kazeia_central.core.store import Store
from kazeia_central.features.medical.questionnaires import service as svc
_OPS = nacl.pwhash.argon2id.OPSLIMIT_MIN
_MEM = nacl.pwhash.argon2id.MEMLIMIT_MIN
NOW = 1_700_000_000_000
def _store(tmp_path):
s = Store(tmp_path / "c.db", kdf_ops=_OPS, kdf_mem=_MEM)
s.unlock("pw")
return s
def test_phq9_seeded_and_undeletable(tmp_path):
s = _store(tmp_path)
ids = {q["id"] for q in svc.list_questionnaires(s)}
assert "phq9" in ids
q = svc.get_questionnaire(s, "phq9")
assert q["builtin"] is True and len(q["definition"]["questions"]) == 9
assert svc.delete_questionnaire(s, "phq9", now=NOW)["deleted"] is False # fourni → protégé
def test_phq9_scoring_bands(tmp_path):
s = _store(tmp_path)
defn = svc.get_questionnaire(s, "phq9")["definition"]
assert svc.score(defn, [0] * 9) == {"total_score": 0, "interpretation": defn["scoring"]["ranges"][0]["label"]}
top = svc.score(defn, [3] * 9)
assert top["total_score"] == 27 and "sévère" in top["interpretation"].lower()
def test_authoring_custom_qcm(tmp_path):
s = _store(tmp_path)
defn = {
"type": "qcm",
"questions": [{"text": "Sommeil ?", "choices": [{"label": "Bon", "score": 0},
{"label": "Mauvais", "score": 2}]}],
"scoring": {"method": "sum", "ranges": [{"min": 0, "max": 1, "label": "ok"},
{"min": 2, "max": 2, "label": "alerte"}]},
}
svc.save_questionnaire(s, "sommeil", "Suivi sommeil", defn, now=NOW, actor="dr")
assert svc.score(defn, [1])["interpretation"] == "alerte"
assert svc.delete_questionnaire(s, "sommeil", now=NOW)["deleted"] is True
def test_assign_list_deactivate(tmp_path):
s = _store(tmp_path)
r = svc.assign(s, "phq9", "SER1", "p_1", {"mode": "recurring", "every_days": 7}, now=NOW, actor="dr")
aid = r["assignment_id"]
ags = svc.assignments(s, serial="SER1")
assert len(ags) == 1 and ags[0]["frequency"]["every_days"] == 7 and ags[0]["active"] == 1
svc.deactivate(s, aid, now=NOW, actor="dr")
assert svc.assignments(s, serial="SER1") == [] # active_only → filtré
def test_result_into_patient_dossier_encrypted(tmp_path):
s = _store(tmp_path)
out = svc.record_result(s, "phq9", "SER1", "p_1", [2, 2, 1, 1, 0, 0, 0, 0, 0], now=NOW, actor="dr")
assert out["total_score"] == 6 and out["interpretation"]
res = svc.patient_results(s, "SER1", "p_1")
assert len(res) == 1 and res[0]["result"]["total_score"] == 6
assert res[0]["result"]["answers"][0] == 2
# PII chiffrée au repos : le blob brut ne contient pas l'interprétation en clair
raw = s._db.execute("SELECT result_enc FROM questionnaire_results").fetchone()["result_enc"]
assert isinstance(raw, (bytes, memoryview)) and b"interpretation" not in bytes(raw)