diff --git a/tests/longevity/referto.test.ts b/tests/longevity/referto.test.ts index 574d93f..c128885 100644 --- a/tests/longevity/referto.test.ts +++ b/tests/longevity/referto.test.ts @@ -20,6 +20,27 @@ function conCompilazione() { return { db, s }; } +/** + * Come conCompilazione, con IN PIU' una risposta di questionario_sonno (q_riposato). + * Serve solo alla prova sul congelamento, che ha bisogno di un asse con PIU' sotto-domini + * pesati e copertura parziale non nulla — vedi il commento sopra la mutazione qui sotto per + * il perche' conCompilazione da sola non basta. + */ +function conCoperturaParziale() { + const db = createLongevityDb(':memory:'); + seedRegistro(db); seedPesi(db, MODEL_VERSION); + db.prepare(`INSERT INTO soggetti (client_code, sesso) VALUES ('ISL-0001','F')`).run(); + const s = salvaCompilazione(db, { + client_code: 'ISL-0001', data: '2026-08-22', eta: 35, + risposte: { + q_attivita: 5, q_alimentazione: 8, q_sigarette: 0, q_alcol_life: 2, q_luce: 2, q_schermi: 10, + q_riposato: 8, + }, + }); + salvaScore(db, s, calcolaSessione(db, s)); + return { db, s }; +} + describe('il referto del cliente', () => { it('restituisce i sette assi', () => { const { db, s } = conCompilazione(); @@ -46,10 +67,30 @@ describe('il referto del cliente', () => { }); it('legge i punteggi congelati, non li ricalcola al volo', () => { - const { db, s } = conCompilazione(); - // se rileggesse le misure invece degli score salvati, cambiare i pesi cambierebbe il referto + const { db, s } = conCoperturaParziale(); const prima = JSON.stringify(refertoDi(db, s)); - db.prepare(`UPDATE pesi SET peso = 0.99 WHERE model_version = ? AND elemento = 'questionario_lifestyle'`).run(MODEL_VERSION); + // ATTENZIONE alla scelta della mutazione: non una qualunque, una che DISCRIMINA + // davvero un ricalcolo da una lettura congelata. + // + // 'Recupero & Sistema Nervoso' pesa QUATTRO sotto-domini (hrv 0.50, pressione 0.15, + // hrr 0.15, questionario_sonno 0.20); questa sessione ne misura UNO solo + // (questionario_sonno, via q_riposato in conCoperturaParziale) — copertura vera + // 0.20/1.00=0.20, sotto COPERTURA_MINIMA (0.4): l'asse e' 'insufficiente', ma con + // disponibili.length===1, non 0 — la formula del peso viene davvero eseguita, non + // bypassata dalla scorciatoia "nessun dato disponibile" di aggrega() in cascata.ts. + // Azzerando il peso di 'hrv' (un sotto-dominio ASSENTE) il totale scende a 0.50 e la + // copertura vera diventa 0.20/0.50=0.40: attraversa la soglia, l'asse passerebbe da + // insufficiente a ok SE il referto ricalcolasse (provato: vedi task-3-report.md). + // + // Una mutazione come questa NON discrimina, ed e' un errore da non ripetere: + // il peso dell'UNICO sotto-dominio di un asse a un solo elemento (es. + // 'questionario_lifestyle', 1.00 in 'Stile di Vita & Sonno') si semplifica sempre, + // sia al numeratore sia al denominatore della media pesata — cambiarlo non altera + // ne' il valore ne' la copertura, quindi il test resterebbe verde anche se + // refertoDi ricalcolasse davvero (era il bug di questo stesso test, corretto qui). + db.prepare( + `UPDATE pesi SET peso = 0 WHERE model_version = ? AND livello='asse' AND contenitore='Recupero & Sistema Nervoso' AND elemento='hrv'` + ).run(MODEL_VERSION); expect(JSON.stringify(refertoDi(db, s))).toBe(prima); });