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
91 lines
3.4 KiB
TypeScript
91 lines
3.4 KiB
TypeScript
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);
|
|
});
|
|
});
|