510d7ca4ec
Primo passo della separazione sito / piattaforme decisa da Adriano il 03/09: due applicazioni autosufficienti, senza workspace di root, cosi' che ognuna resti un progetto Astro completo ed estraibile. Qui non cambia niente del codice: solo la radice. I pattern del .gitignore che avevano una barra erano ancorati alla radice e dopo lo spostamento non avrebbero piu' coperto niente (data/*.db*, uploads/*): resi validi a qualunque profondita'. Suite: 45 file, 347 test verdi prima e dopo lo spostamento. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EndnceRA5WnA6rvA5iV9WL
82 lines
4.0 KiB
TypeScript
82 lines
4.0 KiB
TypeScript
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);
|
|
});
|
|
});
|