test: ripara la suite Vitest e migra gli e2e all'architettura attuale

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
This commit is contained in:
2026-06-21 00:36:02 +02:00
parent ddf68010a4
commit eb37f8319f
19 changed files with 931 additions and 302 deletions
+110
View File
@@ -0,0 +1,110 @@
import { describe, it, expect } from 'vitest'
import { buildRefertoHtml } from '../../src/referto.js'
import { createInitialState } from '../../src/gameState.js'
// Data fissa per asserzioni deterministiche
const NOW = new Date('2026-03-14T20:30:00')
// Costruisce uno stato con una striscia di set arbitraria
function statoConSet(striscia, extra = {}) {
const state = createInitialState()
state.sp.striscia = striscia
state.sp.nomi = { home: 'Antoniana', guest: 'Rivali' }
return { ...state, ...extra }
}
describe('buildRefertoHtml (referto.js)', () => {
it('esclude i set _phantom dal referto', () => {
const striscia = [
{ serv: 'h', ris: 'h'.repeat(25) + 'g'.repeat(20), vinc: 'h' },
{ serv: 'g', ris: '', vinc: 'g', _phantom: true },
{ serv: 'h', ris: 'h'.repeat(25) + 'g'.repeat(18), vinc: 'h' },
]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
// due set reali → "Set 1" e "Set 2", mai "Set 3"
expect(html).toContain('Set 1')
expect(html).toContain('Set 2')
expect(html).not.toContain('Set 3')
})
it('calcola il punteggio finale di ogni set dalla ris', () => {
const striscia = [
{ serv: 'h', ris: 'h'.repeat(25) + 'g'.repeat(20), vinc: 'h' },
{ serv: 'h', ris: '', vinc: null },
]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
// header del set: "Antoniana 25 · 20 Rivali"
expect(html).toContain('<strong>25</strong>')
expect(html).toContain('<strong>20</strong>')
})
it('conta i set vinti usando vinc', () => {
const striscia = [
{ serv: 'h', ris: '', vinc: 'h' },
{ serv: 'g', ris: '', vinc: 'g' },
{ serv: 'h', ris: '', vinc: 'h' },
{ serv: 'h', ris: '', vinc: null },
]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
// risultato 2 1
expect(html).toContain('2 1')
})
it('ricava il vincitore dal conteggio punti se vinc è nullo', () => {
const striscia = [
{ serv: 'h', ris: 'h'.repeat(25) + 'g'.repeat(23), vinc: null },
{ serv: 'h', ris: '', vinc: null },
]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
// il primo set, pur con vinc null, conta come vinto da home → 1 0
expect(html).toContain('1 0')
})
it('include la progressione punto-punto con classi per squadra', () => {
const striscia = [
{ serv: 'h', ris: 'hhg', vinc: null },
]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
expect(html).toContain('punto-h')
expect(html).toContain('punto-g')
expect(html).toContain('1-0')
expect(html).toContain('2-0')
expect(html).toContain('2-1')
})
it('rende la formazione di partenza quando presente', () => {
const striscia = [
{
serv: 'h', ris: 'h', vinc: null,
formInizio: { home: ['4', '8', '15'], guest: ['16', '23', '42'] },
},
]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
expect(html).toContain('Formazione di partenza')
expect(html).toContain('>4<')
expect(html).toContain('>42<')
})
it('mostra "non disponibile" se manca formInizio', () => {
const striscia = [{ serv: 'h', ris: 'h', vinc: null }]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
expect(html).toContain('non disponibile')
})
it('mostra "Nessun punto registrato" per un set senza punti', () => {
const striscia = [{ serv: 'h', ris: '', vinc: null }]
const html = buildRefertoHtml(statoConSet(striscia), NOW)
expect(html).toContain('Nessun punto registrato')
})
it('header contiene nomi squadre, modalità e data iniettata', () => {
const striscia = [{ serv: 'h', ris: '', vinc: null }]
const state = statoConSet(striscia)
state.modalitaPartita = '2/3'
const html = buildRefertoHtml(state, NOW)
expect(html).toContain('Antoniana')
expect(html).toContain('Rivali')
expect(html).toContain('Modalità: 2/3')
expect(html).toContain('14/03/2026')
})
})