docs: allinea README, CLAUDE.md e guida ai test allo stato attuale

- 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
This commit is contained in:
2026-06-21 18:04:13 +02:00
parent c73267d347
commit 1ab57654ad
3 changed files with 36 additions and 6 deletions
+11 -2
View File
@@ -32,14 +32,23 @@ Display (Vue) ──WebSocket──┤── websocket-handler.js ── gam
│ └── persist.js ── .segnapunti/state.json │ └── persist.js ── .segnapunti/state.json
``` ```
**Tutta la logica di gioco** è in `src/gameState.js` come tre funzioni pure esportate: **Tutta la logica di gioco** è in `src/gameState.js` come funzioni pure esportate:
- `createInitialState()` — restituisce lo stato iniziale - `createInitialState()` — restituisce lo stato iniziale
- `applyAction(state, action)` — reducer immutabile (deep-clone via `structuredClone`) - `applyAction(state, action)` — reducer immutabile (deep-clone via `structuredClone`)
- `checkVittoria(state)` — condizioni di vittoria set (25 punti, vantaggio di 2; 15 punti nel set decisivo) - `checkVittoria(state)` — condizioni di vittoria set (25 punti, vantaggio di 2; 15 punti nel set decisivo)
- `punteggio` / `setVinti` / `servizio` — derivano punteggio corrente, set vinti e chi serve dalla `striscia` (lo stato NON memorizza questi valori direttamente)
Punteggio, set e servizio si ricavano sempre dalla `striscia`: al primo punto di ogni set `applyAction('incPunt')` salva in `formInizio` uno snapshot della formazione di partenza (usato dal referto); `decPunt` lo rimuove se il set torna a 0-0.
`src/websocket-handler.js` riceve i messaggi WebSocket, valida che il mittente sia un `controller` (non un `display`), chiama `applyAction`, fa il broadcast del nuovo stato a tutti i client, poi invoca `onStateChange` per persistere su disco. `src/websocket-handler.js` riceve i messaggi WebSocket, valida che il mittente sia un `controller` (non un `display`), chiama `applyAction`, fa il broadcast del nuovo stato a tutti i client, poi invoca `onStateChange` per persistere su disco.
`server.js` (Express) serve entrambe le interfacce sulla porta 3000: `/display``dist/index.html`, `/controller``dist/controller.html`. Singolo endpoint WebSocket su `/ws`. `src/wsMixin.js` è il mixin Vue lato client: gestisce connessione/riconnessione WebSocket (backoff esponenziale) ed espone i computed `punt`/`servHome`/`set`.
`src/referto.js` genera il referto di gara: `buildRefertoHtml(state, now)` è una funzione pura che restituisce l'HTML (testabile), mentre `generaReferto(state)` è il wrapper che apre la finestra con `window.open` e avvia la stampa.
`src/persist.js` carica/salva lo stato su `.segnapunti/state.json`. `src/server-utils.js` ricava gli IP di rete (`getNetworkIPs`, con sorgente iniettabile) e stampa gli URL all'avvio.
`server.js` (Express) espone `createApp(distDir)` (solo routing, testabile) e `startServer(port)` (HTTP + WebSocket); serve entrambe le interfacce sulla porta 3000: `/display``dist/index.html`, `/controller``dist/controller.html`. Singolo endpoint WebSocket su `/ws`. L'avvio automatico parte solo se il file è eseguito come entrypoint.
In sviluppo, `vite-plugin-websocket.js` incorpora il server WebSocket dentro il dev server Vite con middleware di URL rewrite per `/display` e `/controller`. In sviluppo, `vite-plugin-websocket.js` incorpora il server WebSocket dentro il dev server Vite con middleware di URL rewrite per `/display` e `/controller`.
+6
View File
@@ -100,6 +100,7 @@ http://<IP-del-server>:3000/controller
- **Visualizzazione** — alterna tra punteggio grande e formazioni in campo - **Visualizzazione** — alterna tra punteggio grande e formazioni in campo
- **Striscia** — mostra/nasconde lo storico punti sul display - **Striscia** — mostra/nasconde lo storico punti sul display
- **Reset** — azzera la partita (richiede conferma) - **Reset** — azzera la partita (richiede conferma)
- **Referto** — a fine partita, dal dialog *PARTITA FINITA*, genera un referto di gara stampabile/PDF (punteggi per set, formazioni di partenza, andamento punto-punto). *Funzione prototipale.*
### Regole pallavolo integrate ### Regole pallavolo integrate
@@ -181,8 +182,13 @@ Lo stato viene salvato in `.segnapunti/state.json` anche in modalità dev.
| `npm run test:component` | Componenti Vue (Happy-DOM) | | `npm run test:component` | Componenti Vue (Happy-DOM) |
| `npm run test:stress` | Load test WebSocket (50+ client) | | `npm run test:stress` | Load test WebSocket (50+ client) |
| `npm run test:all` | Tutti i test tranne E2E | | `npm run test:all` | Tutti i test tranne E2E |
| `npm run test:ui` | Vitest con interfaccia grafica |
| `npm run test:e2e` | Playwright — Chromium, Firefox, Mobile Chrome | | `npm run test:e2e` | Playwright — Chromium, Firefox, Mobile Chrome |
Le suite Vitest coprono la logica di gioco (`gameState`, inclusa `formInizio`),
il protocollo e il routing del server, la persistenza, il client WebSocket
(`wsMixin`), i componenti Vue e la generazione del referto.
> I test E2E richiedono il server in esecuzione (`npm run serve`) e i browser Playwright installati: > I test E2E richiedono il server in esecuzione (`npm run serve`) e i browser Playwright installati:
> ```bash > ```bash
> npx playwright install chromium firefox > npx playwright install chromium firefox
+19 -4
View File
@@ -90,10 +90,18 @@ Esempi reali nel progetto:
- cambio palla - cambio palla
- vittoria set con regola dei 2 punti di scarto - vittoria set con regola dei 2 punti di scarto
- reset stato - reset stato
- `formInizio` (snapshot formazione di partenza del set)
- generazione del referto (`buildRefertoHtml`)
- persistenza stato su disco (`persist.js`, con `fs` mockato)
- utility di rete (`server-utils.js`)
Quando falliscono: Quando falliscono:
- quasi sempre c'e un problema nella logica core - quasi sempre c'e un problema nella logica core
> Nota: punteggio, set e servizio NON sono campi dello stato: si ricavano dalla
> `striscia` con `punteggio` / `setVinti` / `servizio`. Nei test si impostano gli
> scenari costruendo la `striscia`, non scrivendo `sp.punt`/`sp.set`.
### 5.2 Integration (`tests/integration`) ### 5.2 Integration (`tests/integration`)
Cosa sono: Cosa sono:
@@ -107,6 +115,7 @@ Esempi reali nel progetto:
- broadcast stato ai client - broadcast stato ai client
- validazione input malformati - validazione input malformati
- autorizzazioni (solo controller puo inviare certe azioni) - autorizzazioni (solo controller puo inviare certe azioni)
- routing del server Express (`createApp`: rotte display/controller/asset)
Quando falliscono: Quando falliscono:
- spesso c'e problema nel protocollo messaggi o nei controlli di ruolo - spesso c'e problema nel protocollo messaggi o nei controlli di ruolo
@@ -124,6 +133,8 @@ Esempi reali nel progetto:
- stato connessione - stato connessione
- click bottoni controller - click bottoni controller
- dialog reset/config/cambi - dialog reset/config/cambi
- bottone REFERTO nel dialog PARTITA FINITA
- client WebSocket (`wsMixin`: connessione, riconnessione, `sendWs`)
Quando falliscono: Quando falliscono:
- spesso hai rotto template, computed, metodi o binding - spesso hai rotto template, computed, metodi o binding
@@ -152,15 +163,19 @@ A cosa servono:
- verificano che Controller e Display funzionino davvero insieme - verificano che Controller e Display funzionino davvero insieme
File principali: File principali:
- `helpers.cjs`: helper condivisi (`openController`/`openDisplay`/`resetGame`/`addPoints`)
- `basic-flow.spec.cjs`: flusso base Controller <-> Display - `basic-flow.spec.cjs`: flusso base Controller <-> Display
- `game-operations.spec.cjs`: reset, config, toggle, cambi - `game-operations.spec.cjs`: reset, config, toggle, cambi
- `game-simulation.spec.cjs`: simulazione partita - `game-simulation.spec.cjs`: simulazione partita
- `full-match.spec.cjs`: scenari partita completi - `full-match.spec.cjs`: scenari partita completi
- `referto.spec.cjs`: generazione referto a PARTITA FINITA
- `accessibility.spec.cjs`: controlli accessibilita con axe - `accessibility.spec.cjs`: controlli accessibilita con axe
- `visual-regression.spec.cjs`: confronto screenshot con baseline - `visual-regression.spec.cjs`: confronto screenshot con baseline
Nota importante: Note importanti:
- gli E2E sono configurati in seriale (`workers: 1`) per evitare interferenze sullo stato partita condiviso. - gli E2E sono configurati in seriale (`workers: 1`) per evitare interferenze sullo stato partita condiviso.
- il controller viene aperto in viewport portrait (layout "mobile") tramite `openController`: in landscape userebbe la dashboard estesa con selettori diversi.
- lo stato è UNICO e persistente sul server: ogni test inizia con `resetGame`, che azzera e reimposta i nomi di default per garantire determinismo.
## 6) Come leggere i risultati ## 6) Come leggere i risultati
@@ -169,8 +184,8 @@ Nota importante:
Caso OK (verde): Caso OK (verde):
```text ```text
Test Files 6 passed (6) Test Files 10 passed (10)
Tests 159 passed (159) Tests 212 passed (212)
``` ```
Significa: Significa:
@@ -187,7 +202,7 @@ Caso KO (rosso):
Caso OK: Caso OK:
```text ```text
72 passed 75 passed
``` ```
Caso KO: Caso KO: