Aggiunge un'icona nera (nuovo asset serv-nero.png, più visibile del
serv.png bianco su sfondo chiaro) accanto al nome della squadra che
serviva all'inizio di ogni set nel referto stampabile.
Corregge inoltre generaReferto: la stampa partiva subito dopo
document.close(), prima che l'icona (risorsa esterna asincrona)
finisse di caricare, risultando in un riquadro vuoto. Ora attende
l'evento 'load' della finestra popup prima di chiamare print().
Riflette i test aggiunti nei commit precedenti: rilevamento
piattaforma di server-utils, avvio effettivo di startServer, rami di
errore del WebSocket handler, cleanup/riconnessione di wsMixin,
side-effect di generaReferto e layout esteso del controller.
Aggiorna anche i conteggi di esempio (15 file/362 test Vitest, 81
E2E) e documenta come verificare la copertura (>99% statement).
Aggiunge 65 test per ControllerPage.vue (layout esteso/landscape,
popup automatico di set vinto con soglia decisiva, modal di
configurazione, validazione completa dei cambi giocatore, modal
time out con selezione video/ticker/countdown, cleanup dei listener)
e 35 per DisplayPage.vue (countdown overlay, riallineamento video su
riconnessione, fallback muto per autoplay bloccato, selezione voce
per la sintesi vocale). Nessun bug riscontrato nei componenti.
startServer() non era mai invocato nei test: solo createApp() (routing)
era coperto. Mocka src/persist.js per non toccare .segnapunti/state.json
reale, e verifica l'ascolto HTTP, l'accettazione dell'upgrade su /ws,
il rifiuto su altri percorsi e la persistenza dello stato dopo
un'azione del controller.
Aggiunge test per beforeUnmount con connessione OPEN e con ws.close
che lancia, l'annullamento del reconnectTimeout allo smontaggio, la
guardia isConnecting, la chiusura della WebSocket precedente prima
di riconnettersi (incluso il caso in cui close lancia), gli errori
di registrazione/parsing nei gestori onopen/onmessage e la guardia
di scheduleReconnect contro timer doppi.
Aggiunge scenari in cui ws.send o ws.terminate lanciano eccezioni e
in cui applyAction fallisce a metà azione: verifica che l'errore
venga loggato e lo stato precedente ripristinato senza propagare
l'eccezione al chiamante.
getNetworkIPs() senza parametri usa isWSL()/execSync/os.networkInterfaces,
codice mai esercitato perché tutti gli altri test iniettano `nets`
per bypassarlo. Mocka fs/child_process/os per coprire in modo
deterministico i rami WSL, non-WSL, fallimento PowerShell e lettura
/proc fallita.
buildRefertoHtml mancava il caso vinc nullo con guest in vantaggio;
generaReferto (window.open/print) non era testato affatto perché
richiede un DOM — aggiunto un test component in happy-dom che mocka
window.open.
Aggiunge casi per team 'guest' in nuovoSet, cambi senza array
`cambi`, resetta con striscia vuota e startTimeout senza startedAt:
gameState.js passa dal 100% al 100% statement ma sale al 99% branch.
Cornice nera, barre teal "SET N" per set, badge A/B per squadre e
box risultato finale in stile tabella, per avvicinare il referto
stampabile all'aspetto del referto cartaceo FIPAV mantenendo solo
i dati che l'app traccia realmente.
La striscia salva ora storico cambi formazione e time out per ogni
set, con riferimento al punteggio al momento dell'evento anziché a
un timestamp: startTimeout accumula in set.timeouts, confermaCambi
in set.cambi. Il referto elenca entrambi ordinati per punteggio.
Copre il percorso completo controller -> display: apertura modal,
vincolo squadra su Avvia, avvio con "nessun video" (deterministico,
non dipende dal contenuto di spot/), overlay e banner con countdown,
chiusura anticipata e annullamento della modal.
Aggiunge i casi non ancora coperti: il setTimeout di scheduleReconnect
riapre davvero la connessione, un costruttore WebSocket che lancia
programma comunque il retry, onerror azzera lo stato, sendWs ritorna
false se send lancia.
Copre apertura modal con fetch di /spot/list (incluso il fallback di
rete), il vincolo squadra obbligatoria su Avvia, l'invio di
startTimeout/stopTimeout e il banner con countdown durante il time
out attivo.
Nessun test component copriva ancora l'overlay introdotto con
startTimeout/stopTimeout: placeholder senza video, riproduzione con
src corretto, fallback a fine video, countdown e dissolvenza oltre i
30s. Stub di play/pause/load su HTMLMediaElement, non implementati da
happy-dom.
Aggiunge una cartella spot temporanea ai fixture del routing: elenco
ordinato dei soli .mp4, file serviti da /spot/<file>, [] se la
cartella non esiste.
La documentazione descriveva ancora il vecchio toggleTimeout (video in
loop/sequenza); aggiornata a startTimeout/stopTimeout con scelta
squadra/video, countdown e auto-chiusura server-side a 30s.
Unit: attivazione con squadra/video/inizio, rifiuto di squadre non valide,
azzeramento completo con stopTimeout. Integration (fake timers): startedAt
iniettato dal server, auto-chiusura a 30s con broadcast e persistenza,
annullamento del timer su stop manuale e riarmo su nuovo avvio.
- README: referto tra le funzionalità del controller; comando test:ui e aree
coperte dalle suite
- CLAUDE.md: referto.js (buildRefertoHtml/generaReferto), wsMixin/persist/
server-utils, createApp/startServer; nota su formInizio e stato derivato
dalla striscia
- tests/README: conteggi aggiornati (212 Vitest / 75 e2e) e nuove suite
- screenshot stabili: animations disabilitate e mask su .connection-status
- migrata agli helper condivisi
- baseline rigenerate per Chromium, Firefox e Mobile Chrome
- usa openController/openDisplay + resetGame per stato pulito
- esclude la regola color-contrast anche sul controller (colori brand
giallo/blu valutati separatamente, come già per il display)
Porta una partita 2/3 a conclusione, intercetta il popup aperto dal bottone
REFERTO e verifica il contenuto (titolo, set, risultato). window.print è
neutralizzato per non bloccare il test.
- nuovo tests/e2e/helpers.cjs: openController (viewport portrait per il layout
mobile), openDisplay, resetGame, addPoints
- resetGame gestisce il dialog di vittoria persistente e reimposta i nomi di
default (lo stato è condiviso e persistente: serve per il determinismo)
- full-match/game-simulation: gestito il dialog SET VINTO automatico a 25/15
- basic-flow/game-operations: migrati agli helper condivisi
La suite era allineata a una vecchia forma dello stato (sp.punt/sp.set/
sp.servHome) e a una vecchia architettura e2e (controller su :3001).
Baseline iniziale: 77/170 test Vitest falliti.
Vitest (ora 212/212 verdi):
- gameState.test.js: riscritto con helper che derivano punteggio/set/
servizio dalla striscia; aggiunto blocco formInizio
- server-utils.js: getNetworkIPs accetta interfacce iniettabili e
printServerInfo accetta gli IP iniettabili (deterministico anche su WSL);
filtro LAN unificato (esclude 127./169.254./172.)
- websocket + stress: punteggio letto via punteggio(striscia)
- ControllerPage/DisplayPage: forzato layout mobile (viewport portrait),
punteggi impostati via striscia; aggiunto test bottone REFERTO
- nuovi: referto.test.js, persist.test.js (mock fs), wsMixin.test.js,
integration/server.test.js (routing)
Refactor di supporto:
- referto.js: estratta buildRefertoHtml(state, now) pura; generaReferto
resta wrapper con window.open/print
- server.js: estratti createApp()/startServer(); avvio solo se entrypoint
e2e (migrazione parziale, NON ancora verificata verde):
- tutti i riferimenti controller :3001 -> :3000/controller
- forzato viewport portrait sul controller prima del goto
- reset helper: chiude il dialog di configurazione che doReset apre
- game-simulation: gestione del dialog SET VINTO automatico a 25
Aggiunge checkVittoriaPartita per rilevare la vittoria della partita
(2 set in 2/3, 3 set in 3/5). nuovoSet ora registra il set vincente
senza resettare il punteggio quando la partita è finita. Il controller
mostra "PARTITA FINITA" al posto di "SET VINTO" con solo il tasto CHIUDI.
La striscia diventa un array di set: ogni elemento è { serv, r[] }
dove r è la sequenza di scorer ('home'|'guest') del set.
- Un rally = un elemento in r: minimo non-derivabile
- Tutti i set (passati e corrente) sono conservati nell'array
- Dal set corrente si derivano: punteggio, servizio, cambio palla, rotazione
- Dal set completo si derivano: vincitore (r.at(-1)), score finale (count)
- storicoServizio eliminato: l'undo legge l'entry precedente di r
DisplayPage calcola le strip visive (home/guest) tramite computed
da striscia.at(-1).r senza dati ridondanti nel modello.
Quando una squadra raggiunge il punteggio di vittoria (25 con +2 di
scarto, 15 nel set decisivo), il controller mostra un dialog "SET VINTO"
con il nome della squadra vincente.
Alla conferma: invia l'azione nuovoSet (incrementa il set, azzera punti,
striscia, storico servizio e formazioni) e apre automaticamente il dialog
di configurazione per inserire le formazioni del set successivo.
Unifica i due server Express (display :3000, controller :3001) in un
unico processo su PORT (default 3000). Le route /display e /controller
servono rispettivamente index.html e controller.html.
In sviluppo elimina il server proxy su :3001; il plugin Vite riscrive
/display → / e /controller → /controller.html internamente.
printServerInfo aggiornata alla firma a porta singola.
- spiega obiettivi e differenze tra unit, integration, component, stress ed E2E
- aggiunge istruzioni passo-passo per esecuzione e lettura risultati
- documenta gestione snapshot visual e troubleshooting errori comuni
- include checklist pratica pre-push
- aggiunge configurazione playwright.config.cjs per compatibilita runtime
- aggiorna playwright.config.ts con progetto Mobile Chrome
- migra i test E2E da .js a .spec.cjs
- rimuove i vecchi file E2E non piu usati
- allinea i test visual con snapshot baseline aggiornate
- aggiunge test per gameState e utilita server
- aggiunge test di integrazione WebSocket
- aggiunge test componenti Vue (ControllerPage/DisplayPage)
- aggiunge test stress su carico WebSocket
- aggiorna configurazione Vitest per includere nuove cartelle e ambiente componenti
- aggiorna script npm e dipendenze di test
- Introduce Vitest per Unit e Integration Test.
- Introduce Playwright per End-to-End Test.
- Aggiuge documentazione dettagliata in tests/README.md.
- Aggiorna .gitignore per escludere i report di coverage