From 6638d6fe44b6ce1b29aecf6366850c1e5d008654 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Fri, 3 Jul 2026 12:00:25 +0200 Subject: [PATCH] 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. --- tests/integration/startServer.test.js | 75 +++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 tests/integration/startServer.test.js diff --git a/tests/integration/startServer.test.js b/tests/integration/startServer.test.js new file mode 100644 index 0000000..aafc163 --- /dev/null +++ b/tests/integration/startServer.test.js @@ -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() + }) +})