test(vitest): amplia la suite con test unitari, integrazione, componenti e stress
- 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
This commit is contained in:
118
tests/stress/websocket-load.test.js
Normal file
118
tests/stress/websocket-load.test.js
Normal file
@@ -0,0 +1,118 @@
|
||||
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)
|
||||
}
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user