test(server): copri l'avvio effettivo di startServer (HTTP + WebSocket)
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.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { describe, it, expect, vi, beforeAll, afterAll } from 'vitest'
|
||||
import WebSocket from 'ws'
|
||||
import { createInitialState } from '../../src/gameState.js'
|
||||
|
||||
// startServer() usa src/persist.js per caricare/salvare lo stato reale su disco
|
||||
// (.segnapunti/state.json): lo mockiamo per non toccare lo stato di una partita
|
||||
// vera durante i test, ed esercitare in isolamento l'avvio di HTTP + WebSocket.
|
||||
const saveState = vi.fn()
|
||||
vi.mock('../../src/persist.js', () => ({
|
||||
loadState: () => createInitialState(),
|
||||
saveState,
|
||||
}))
|
||||
|
||||
const { startServer } = await import('../../server.js')
|
||||
|
||||
describe('startServer (server.js)', () => {
|
||||
let server
|
||||
let port
|
||||
|
||||
beforeAll(async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
server = startServer(0)
|
||||
await new Promise((resolve) => server.on('listening', resolve))
|
||||
port = server.address().port
|
||||
consoleSpy.mockRestore()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await new Promise((resolve) => server.close(resolve))
|
||||
})
|
||||
|
||||
it('stampa le info del server all\'avvio', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
const s = startServer(0)
|
||||
await new Promise((resolve) => s.on('listening', resolve))
|
||||
const allLogs = consoleSpy.mock.calls.map(c => c[0]).join('\n')
|
||||
expect(allLogs).toContain('Segnapunti Server')
|
||||
consoleSpy.mockRestore()
|
||||
await new Promise((resolve) => s.close(resolve))
|
||||
})
|
||||
|
||||
it('accetta una connessione WebSocket su /ws', async () => {
|
||||
const ws = new WebSocket(`ws://127.0.0.1:${port}/ws`)
|
||||
await new Promise((resolve, reject) => {
|
||||
ws.on('open', resolve)
|
||||
ws.on('error', reject)
|
||||
})
|
||||
ws.close()
|
||||
})
|
||||
|
||||
it('rifiuta l\'upgrade su un percorso diverso da /ws', async () => {
|
||||
const ws = new WebSocket(`ws://127.0.0.1:${port}/altro-percorso`)
|
||||
await new Promise((resolve) => {
|
||||
ws.on('error', () => resolve())
|
||||
ws.on('open', () => { ws.close(); resolve() })
|
||||
})
|
||||
})
|
||||
|
||||
it('un\'azione dal controller invoca saveState (onStateChange)', async () => {
|
||||
saveState.mockClear()
|
||||
const ws = new WebSocket(`ws://127.0.0.1:${port}/ws`)
|
||||
await new Promise((resolve, reject) => {
|
||||
ws.on('open', resolve)
|
||||
ws.on('error', reject)
|
||||
})
|
||||
ws.send(JSON.stringify({ type: 'register', role: 'controller' }))
|
||||
await new Promise((resolve) => ws.once('message', resolve))
|
||||
|
||||
ws.send(JSON.stringify({ type: 'action', action: { type: 'incPunt', team: 'home' } }))
|
||||
await new Promise((resolve) => ws.once('message', resolve))
|
||||
|
||||
expect(saveState).toHaveBeenCalled()
|
||||
ws.close()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user