import { describe, it, expect } from 'vitest'; import { durata, dataBreve, dataOra, ultimi, kpiSport, perSettimana, riepilogoAtleti } from '../src/lib/stress-index/sport'; import type { Athlete, Session } from '../src/lib/stress-index/data'; const RIF = '2026-07-12'; const sess = (id: string, athleteId: string, startedAt: string, trimp: number): Session => ({ id, athleteId, startedAt, durationSec: 1800, sport: null, hrAvg: 120, hrMax: 150, trimp, dfaA1: 1.2, rpe: 5 }); const athletes: Athlete[] = [ { clientId: 'a', name: 'A. Uno', sport: 'Corsa' }, { clientId: 'b', name: 'B. Due', sport: null }, ]; // Ordinate dalla più recente, come le espone data.ts const sessions: Session[] = [ sess('s1', 'a', '2026-07-12T09:00', 40), sess('s2', 'a', '2026-07-08T09:00', 30), sess('s3', 'a', '2026-07-02T09:00', 60), // settimana precedente sess('s4', 'b', '2026-06-20T09:00', 20), // oltre i 30 giorni? no: 22 giorni prima sess('s5', 'b', '2026-04-01T09:00', 15), // fuori da tutte le finestre ]; describe('formattazioni', () => { it('durata: ore, minuti e secondi', () => { expect(durata(4860)).toBe('1h 21m'); expect(durata(3275)).toBe('54m 35s'); expect(durata(5)).toBe('5s'); }); it('date in forma breve ed estesa', () => { expect(dataBreve('2026-07-30T11:27')).toBe('30 lug 2026'); expect(dataOra('2026-07-30T11:27')).toBe('30 lug 2026 alle 11:27'); }); }); describe('finestre temporali', () => { it('gli ultimi 7 giorni includono il giorno di riferimento ed escludono il settimo indietro', () => { expect(ultimi(sessions, 7, RIF).map((s) => s.id)).toEqual(['s1', 's2']); }); it('gli ultimi 30 giorni allargano a chi ha misurato nel mese', () => { expect(ultimi(sessions, 30, RIF).map((s) => s.id)).toEqual(['s1', 's2', 's3', 's4']); }); }); describe('kpi', () => { it('conta sessioni, carico settimanale e atleti attivi nel mese', () => { expect(kpiSport(sessions, RIF)).toEqual([ { label: 'Sessioni totali', value: 5 }, { label: 'Questa settimana', value: 2, note: 'ultimi 7gg' }, { label: 'TRIMP medio', value: 70, note: 'settimanale' }, { label: 'Atleti attivi', value: 2, note: 'ultimi 30gg' }, ]); }); }); describe('sessioni per settimana', () => { const righe = perSettimana(sessions, 4, RIF); it('produce una riga per settimana, la più recente per ultima', () => { expect(righe).toHaveLength(4); // 2026-07-12 è una domenica: la sua settimana parte lunedì 06/07 expect(righe[righe.length - 1].settimana).toBe('06/07'); }); it('conta le sessioni nella settimana giusta', () => { const perEtichetta = Object.fromEntries(righe.map((r) => [r.settimana, r.sessioni])); expect(perEtichetta['06/07']).toBe(2); // s1 e s2 expect(perEtichetta['29/06']).toBe(1); // s3 }); }); describe('riepilogo atleti', () => { const riepilogo = riepilogoAtleti(sessions, athletes, RIF); it('somma il carico dei 7 giorni e riporta ultima sessione e conteggio mensile', () => { expect(riepilogo[0]).toEqual({ clientId: 'a', name: 'A. Uno', sport: 'Corsa', sessioni30: 3, trimp7: 70, ultimoTrimp: 40, ultimaSessione: '2026-07-12T09:00', trend: 'stabile', }); }); it('resta stabile quando lo scarto fra le due settimane è minimo', () => { // b non ha nulla negli ultimi 7 giorni né nei 7 precedenti → nessuno scarto, resta stabile expect(riepilogo[1].trend).toBe('stabile'); expect(riepilogo[1].sessioni30).toBe(1); }); });