- 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
119 lines
3.8 KiB
JavaScript
119 lines
3.8 KiB
JavaScript
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
|
|
import { setupWebSocketHandler } from '../../src/websocket-handler.js'
|
|
import { EventEmitter } from 'events'
|
|
|
|
class MockWebSocket extends EventEmitter {
|
|
constructor() {
|
|
super()
|
|
this.readyState = 1
|
|
}
|
|
send = vi.fn()
|
|
terminate = vi.fn()
|
|
}
|
|
|
|
class MockWebSocketServer extends EventEmitter {
|
|
clients = new Set()
|
|
}
|
|
|
|
function connectAndRegister(wss, role) {
|
|
const ws = new MockWebSocket()
|
|
wss.emit('connection', ws)
|
|
wss.clients.add(ws)
|
|
ws.emit('message', JSON.stringify({ type: 'register', role }))
|
|
ws.send.mockClear()
|
|
return ws
|
|
}
|
|
|
|
describe('Stress Test WebSocket', () => {
|
|
let wss
|
|
let handler
|
|
|
|
beforeEach(() => {
|
|
wss = new MockWebSocketServer()
|
|
handler = setupWebSocketHandler(wss)
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('dovrebbe gestire 50 client display connessi simultaneamente', () => {
|
|
const displays = []
|
|
for (let i = 0; i < 50; i++) {
|
|
displays.push(connectAndRegister(wss, 'display'))
|
|
}
|
|
|
|
expect(handler.getClients().size).toBe(50)
|
|
|
|
// Un controller invia un'azione
|
|
const controller = connectAndRegister(wss, 'controller')
|
|
controller.emit('message', JSON.stringify({
|
|
type: 'action',
|
|
action: { type: 'incPunt', team: 'home' }
|
|
}))
|
|
|
|
// Tutti i display devono aver ricevuto il broadcast
|
|
for (const display of displays) {
|
|
expect(display.send).toHaveBeenCalled()
|
|
const msg = JSON.parse(display.send.mock.calls[display.send.mock.calls.length - 1][0])
|
|
expect(msg.type).toBe('state')
|
|
expect(msg.state.sp.punt.home).toBe(1)
|
|
}
|
|
})
|
|
|
|
it('dovrebbe gestire 100 azioni rapide in sequenza con stato finale corretto', () => {
|
|
const controller = connectAndRegister(wss, 'controller')
|
|
|
|
// 60 punti home, 40 punti guest
|
|
for (let i = 0; i < 60; i++) {
|
|
controller.emit('message', JSON.stringify({
|
|
type: 'action',
|
|
action: { type: 'incPunt', team: 'home' }
|
|
}))
|
|
}
|
|
for (let i = 0; i < 40; i++) {
|
|
controller.emit('message', JSON.stringify({
|
|
type: 'action',
|
|
action: { type: 'incPunt', team: 'guest' }
|
|
}))
|
|
}
|
|
|
|
// Lo stato finale dipende da checkVittoria che blocca a 25+2
|
|
// Home arriva a 25-0 → vittoria → blocca. Quindi punti home = 25
|
|
const state = handler.getState()
|
|
expect(state.sp.punt.home).toBe(25)
|
|
// Guest: non può segnare dopo vittoria? No, checkVittoria blocca solo il team che ha vinto?
|
|
// Controlliamo: checkVittoria controlla ENTRAMBI i team.
|
|
// A 25-0 → vittoria=true → incPunt per guest è anche bloccato
|
|
expect(state.sp.punt.guest).toBe(0)
|
|
})
|
|
|
|
it('dovrebbe garantire che tutti i display ricevano ogni update sotto carico', () => {
|
|
const displays = []
|
|
for (let i = 0; i < 10; i++) {
|
|
displays.push(connectAndRegister(wss, 'display'))
|
|
}
|
|
|
|
const controller = connectAndRegister(wss, 'controller')
|
|
|
|
// 5 azioni rapide
|
|
for (let i = 0; i < 5; i++) {
|
|
controller.emit('message', JSON.stringify({
|
|
type: 'action',
|
|
action: { type: 'incPunt', team: 'home' }
|
|
}))
|
|
}
|
|
|
|
// Ogni display deve aver ricevuto esattamente 5 broadcast
|
|
for (const display of displays) {
|
|
expect(display.send).toHaveBeenCalledTimes(5)
|
|
}
|
|
|
|
// Verifica stato finale su tutti i display
|
|
for (const display of displays) {
|
|
const lastMsg = JSON.parse(display.send.mock.calls[4][0])
|
|
expect(lastMsg.state.sp.punt.home).toBe(5)
|
|
}
|
|
})
|
|
})
|