import { describe, it, expect } from 'vitest'; import { createLongevityDb } from '../../src/lib/longevity/db'; import { seedRegistro, seedPesi, MODEL_VERSION } from '../../src/lib/longevity/registro'; import { apriSessione, registraMisure } from '../../src/lib/longevity/misure'; import { calcolaSessione } from '../../src/lib/longevity/motore'; /** * Riproduce la situazione descritta nella documentazione del cliente: una persona di cui * si conosce solo la composizione corporea, misurata dalla Wellness Tower. Un asse pieno, * tutti gli altri scoperti. È il caso in cui un motore ingenuo mostrerebbe sei zeri. * Dati sintetici: nessuna persona reale. */ describe('un profilo con una sola area misurata', () => { it('mostra l asse coperto e dichiara insufficienti gli altri sei', () => { const db = createLongevityDb(':memory:'); seedRegistro(db); seedPesi(db, MODEL_VERSION); db.prepare(`INSERT INTO soggetti (client_code, sesso) VALUES ('ISL-0001','M')`).run(); // i tre test di composizione esistono nel registro solo dopo il piano degli import: // finche non ci sono, questo test dimostra il comportamento con zero misure fisiche const s = apriSessione(db, { client_code: 'ISL-0001', data: '2026-08-22', tipo: 'checkup', eta_alla_data: 38 }); registraMisure(db, s, 'questionario', []); const r = calcolaSessione(db, s); const insufficienti = Object.values(r.assi).filter((a) => a.stato === 'insufficiente').length; expect(insufficienti).toBe(7); expect(r.fitnessAge).toBeNull(); }); it('nessun asse insufficiente porta con se un valore da mostrare per sbaglio', () => { const db = createLongevityDb(':memory:'); seedRegistro(db); seedPesi(db, MODEL_VERSION); db.prepare(`INSERT INTO soggetti (client_code, sesso) VALUES ('ISL-0002','F')`).run(); const s = apriSessione(db, { client_code: 'ISL-0002', data: '2026-08-22', tipo: 'checkup', eta_alla_data: 35 }); registraMisure(db, s, 'questionario', []); const r = calcolaSessione(db, s); for (const [nome, asse] of Object.entries(r.assi)) { if (asse.stato === 'insufficiente') { expect((asse as { valore?: number }).valore, `${nome} espone un valore`).toBeUndefined(); } } }); /** * Il caso misto: quello che la prima dashboard disegnera' davvero, non "tutto * insufficiente". Realizza per intero la premessa del describe qui sopra — la * composizione corporea davvero misurata dalla Wellness Tower — aggiungendo le * due voci al registro (arrivano col piano degli import; qui bastano due righe, * non serve aspettarle) e registrando le misure end-to-end. */ it('un asse valido (Composizione Corporea) e sei insufficienti, end-to-end', () => { const db = createLongevityDb(':memory:'); seedRegistro(db); seedPesi(db, MODEL_VERSION); db.prepare(`INSERT INTO soggetti (client_code, sesso) VALUES ('ISL-0003','M')`).run(); db.prepare( `INSERT INTO registro_test (test_id, etichetta, tipo_valore, curva, params, asse, sotto_dominio, attivo_da) VALUES ('wt_grasso', 'Grasso % (Wellness Tower)', 'num', 'lin_dec', ?, 'Composizione Corporea', 'grasso', '2026-01-01')` ).run(JSON.stringify({ best: 10, worst: 40 })); db.prepare( `INSERT INTO registro_test (test_id, etichetta, tipo_valore, curva, params, asse, sotto_dominio, attivo_da) VALUES ('wt_muscolo', 'Muscolo % (Wellness Tower)', 'num', 'lin_dec', ?, 'Composizione Corporea', 'muscolo', '2026-01-01')` ).run(JSON.stringify({ best: 50, worst: 30 })); const s = apriSessione(db, { client_code: 'ISL-0003', data: '2026-08-22', tipo: 'checkup', eta_alla_data: 38 }); registraMisure(db, s, 'wellness_tower', [ { test_id: 'wt_grasso', valore_num: 15 }, { test_id: 'wt_muscolo', valore_num: 45 }, ]); const r = calcolaSessione(db, s); expect(r.assi['Composizione Corporea'].stato).toBe('ok'); const insufficienti = Object.entries(r.assi) .filter(([nome, a]) => nome !== 'Composizione Corporea' && a.stato === 'insufficiente'); expect(insufficienti.length).toBe(6); }); });