0b7cbd00f6
Aggiunge 65 test per ControllerPage.vue (layout esteso/landscape, popup automatico di set vinto con soglia decisiva, modal di configurazione, validazione completa dei cambi giocatore, modal time out con selezione video/ticker/countdown, cleanup dei listener) e 35 per DisplayPage.vue (countdown overlay, riallineamento video su riconnessione, fallback muto per autoplay bloccato, selezione voce per la sintesi vocale). Nessun bug riscontrato nei componenti.
1001 lines
45 KiB
JavaScript
1001 lines
45 KiB
JavaScript
// @vitest-environment happy-dom
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
import { mount, flushPromises } from '@vue/test-utils'
|
|
import ControllerPage from '../../src/components/ControllerPage.vue'
|
|
import { generaReferto } from '../../src/referto.js'
|
|
|
|
// Il referto apre una finestra/print: lo mockiamo per testarne solo l'invocazione.
|
|
vi.mock('../../src/referto.js', () => ({ generaReferto: vi.fn() }))
|
|
|
|
// Mock globale WebSocket per jsdom
|
|
class MockWebSocket {
|
|
static OPEN = 1
|
|
static CONNECTING = 0
|
|
readyState = 0
|
|
onopen = null
|
|
onclose = null
|
|
onmessage = null
|
|
onerror = null
|
|
send = vi.fn()
|
|
close = vi.fn()
|
|
constructor() {
|
|
// Simula connessione immediata
|
|
setTimeout(() => {
|
|
this.readyState = 1
|
|
if (this.onopen) this.onopen()
|
|
}, 0)
|
|
}
|
|
}
|
|
|
|
vi.stubGlobal('WebSocket', MockWebSocket)
|
|
|
|
// Mock di fetch per /spot/list (usato dalla modal time out).
|
|
const fetchMock = vi.fn().mockResolvedValue({ json: async () => [] })
|
|
vi.stubGlobal('fetch', fetchMock)
|
|
|
|
// Forza l'orientamento portrait → il controller usa il layout "mobile"
|
|
// (con .team-pts, .btn-ctrl, ecc.) su cui questi test fanno asserzioni.
|
|
Object.defineProperty(window, 'innerWidth', { value: 400, writable: true, configurable: true })
|
|
Object.defineProperty(window, 'innerHeight', { value: 800, writable: true, configurable: true })
|
|
|
|
// Imposta il punteggio del set in corso costruendo una ris coerente.
|
|
// `serv` ('h'|'g') controlla l'ultimo punto, quindi chi risulta al servizio.
|
|
function setScore(wrapper, home, guest, serv = 'h') {
|
|
const altro = serv === 'h' ? 'g' : 'h'
|
|
const nAltro = serv === 'h' ? guest : home
|
|
const nServ = serv === 'h' ? home : guest
|
|
// mette per ultimo il carattere del battitore desiderato
|
|
wrapper.vm.state.sp.striscia.at(-1).ris = altro.repeat(nAltro) + serv.repeat(nServ)
|
|
}
|
|
|
|
// Helper per creare il componente con stato personalizzato
|
|
function mountController(stateOverrides = {}) {
|
|
const wrapper = mount(ControllerPage, {
|
|
global: {
|
|
stubs: { 'w-app': true, 'w-button': true }
|
|
}
|
|
})
|
|
if (Object.keys(stateOverrides).length > 0) {
|
|
wrapper.vm.state = { ...wrapper.vm.state, ...stateOverrides }
|
|
}
|
|
return wrapper
|
|
}
|
|
|
|
describe('ControllerPage.vue', () => {
|
|
|
|
beforeEach(() => {
|
|
vi.useFakeTimers()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers()
|
|
})
|
|
|
|
// =============================================
|
|
// RENDERING INIZIALE
|
|
// =============================================
|
|
describe('Rendering iniziale', () => {
|
|
it('dovrebbe mostrare i nomi dei team', () => {
|
|
const wrapper = mountController()
|
|
const text = wrapper.text()
|
|
expect(text).toContain('Antoniana')
|
|
expect(text).toContain('Guest')
|
|
})
|
|
|
|
it('dovrebbe mostrare punteggio 0-0', () => {
|
|
const wrapper = mountController()
|
|
const pts = wrapper.findAll('.team-pts')
|
|
expect(pts[0].text()).toBe('0')
|
|
expect(pts[1].text()).toBe('0')
|
|
})
|
|
|
|
it('dovrebbe mostrare SET 0 per entrambi i team', () => {
|
|
const wrapper = mountController()
|
|
const sets = wrapper.findAll('.team-set')
|
|
expect(sets[0].text()).toContain('SET 0')
|
|
expect(sets[1].text()).toContain('SET 0')
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// CLICK PUNTEGGIO
|
|
// =============================================
|
|
describe('Click punteggio', () => {
|
|
it('dovrebbe chiamare sendAction con incPunt home al click sul team home', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.team-score.home-bg').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incPunt', team: 'home' })
|
|
})
|
|
|
|
it('dovrebbe chiamare sendAction con incPunt guest al click sul team guest', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.team-score.guest-bg').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incPunt', team: 'guest' })
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// BOTTONE CAMBIO PALLA
|
|
// =============================================
|
|
describe('Cambio Palla', () => {
|
|
it('dovrebbe essere abilitato a 0-0', () => {
|
|
const wrapper = mountController()
|
|
const btn = wrapper.findAll('.btn-ctrl').find(b => b.text().includes('Cambio Palla'))
|
|
expect(btn.attributes('disabled')).toBeUndefined()
|
|
})
|
|
|
|
it('dovrebbe essere disabilitato se il punteggio non è 0-0', async () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 5, 0)
|
|
await wrapper.vm.$nextTick()
|
|
const btn = wrapper.findAll('.btn-ctrl').find(b => b.text().includes('Cambio Palla'))
|
|
expect(btn.attributes('disabled')).toBeDefined()
|
|
})
|
|
|
|
it('il click quando abilitato invia cambiaPalla', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
const btn = wrapper.findAll('.btn-ctrl').find(b => b.text().includes('Cambio Palla'))
|
|
await btn.trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'cambiaPalla' })
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// DIALOG RESET
|
|
// =============================================
|
|
describe('Dialog Reset', () => {
|
|
it('click Reset dovrebbe aprire la conferma', async () => {
|
|
const wrapper = mountController()
|
|
expect(wrapper.find('.overlay').exists()).toBe(false)
|
|
await wrapper.find('.btn-danger').trigger('click')
|
|
expect(wrapper.vm.confirmReset).toBe(true)
|
|
expect(wrapper.find('.overlay').exists()).toBe(true)
|
|
})
|
|
|
|
it('click NO dovrebbe chiudere la conferma', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.confirmReset = true
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.btn-cancel').trigger('click')
|
|
expect(wrapper.vm.confirmReset).toBe(false)
|
|
})
|
|
|
|
it('click SI dovrebbe chiamare doReset', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
wrapper.vm.confirmReset = true
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.btn-confirm').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'resetta' })
|
|
expect(wrapper.vm.confirmReset).toBe(false)
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// COMPUTED cambiValid
|
|
// =============================================
|
|
describe('cambiValid', () => {
|
|
it('dovrebbe essere false se tutti i campi sono vuoti', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.cambiData = [{ in: '', out: '' }, { in: '', out: '' }]
|
|
expect(wrapper.vm.cambiValid).toBe(false)
|
|
})
|
|
|
|
it('dovrebbe essere true con un cambio completo', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.cambiData = [{ in: '10', out: '1' }, { in: '', out: '' }]
|
|
expect(wrapper.vm.cambiValid).toBe(true)
|
|
})
|
|
|
|
it('dovrebbe essere false con un cambio parziale (solo IN)', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.cambiData = [{ in: '10', out: '' }, { in: '', out: '' }]
|
|
expect(wrapper.vm.cambiValid).toBe(false)
|
|
})
|
|
|
|
it('dovrebbe essere false con un cambio parziale (solo OUT)', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.cambiData = [{ in: '', out: '1' }, { in: '', out: '' }]
|
|
expect(wrapper.vm.cambiValid).toBe(false)
|
|
})
|
|
|
|
it('dovrebbe essere true con due cambi completi', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.cambiData = [{ in: '10', out: '1' }, { in: '11', out: '2' }]
|
|
expect(wrapper.vm.cambiValid).toBe(true)
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// SPEAK
|
|
// =============================================
|
|
describe('speak', () => {
|
|
it('dovrebbe generare "zero a zero" a 0-0', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.wsConnected = true
|
|
wrapper.vm.ws = { readyState: 1, send: vi.fn() }
|
|
wrapper.vm.speak()
|
|
const sent = JSON.parse(wrapper.vm.ws.send.mock.calls[0][0])
|
|
expect(sent.type).toBe('speak')
|
|
expect(sent.text).toBe('zero a zero')
|
|
})
|
|
|
|
it('dovrebbe generare "N pari" a punteggio uguale', () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 5, 5)
|
|
wrapper.vm.wsConnected = true
|
|
wrapper.vm.ws = { readyState: 1, send: vi.fn() }
|
|
wrapper.vm.speak()
|
|
const sent = JSON.parse(wrapper.vm.ws.send.mock.calls[0][0])
|
|
expect(sent.text).toBe('5 pari')
|
|
})
|
|
|
|
it('dovrebbe annunciare prima il punteggio di chi batte (home serve)', () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 15, 10, 'h')
|
|
wrapper.vm.wsConnected = true
|
|
wrapper.vm.ws = { readyState: 1, send: vi.fn() }
|
|
wrapper.vm.speak()
|
|
const sent = JSON.parse(wrapper.vm.ws.send.mock.calls[0][0])
|
|
expect(sent.text).toBe('15 a 10')
|
|
})
|
|
|
|
it('dovrebbe annunciare prima il punteggio di chi batte (guest serve)', () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 10, 15, 'g')
|
|
wrapper.vm.wsConnected = true
|
|
wrapper.vm.ws = { readyState: 1, send: vi.fn() }
|
|
wrapper.vm.speak()
|
|
const sent = JSON.parse(wrapper.vm.ws.send.mock.calls[0][0])
|
|
expect(sent.text).toBe('15 a 10')
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// REFERTO (modal PARTITA FINITA)
|
|
// =============================================
|
|
describe('Referto', () => {
|
|
// Porta il componente allo stato "partita finita" per home in 2/3
|
|
function setPartitaFinita(wrapper) {
|
|
wrapper.vm.state.modalitaPartita = '2/3'
|
|
wrapper.vm.state.sp.striscia = [
|
|
{ serv: 'h', ris: '', vinc: 'h' },
|
|
{ serv: 'h', ris: '', vinc: null },
|
|
]
|
|
wrapper.vm.setVintoTeam = 'home'
|
|
wrapper.vm.showSetVinto = true
|
|
}
|
|
|
|
it('mostra il bottone REFERTO quando la partita è finita', async () => {
|
|
const wrapper = mountController()
|
|
setPartitaFinita(wrapper)
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.vm.isPartitaFinita).toBe(true)
|
|
const btn = wrapper.findAll('.btn-secondary').find(b => b.text().includes('REFERTO'))
|
|
expect(btn).toBeDefined()
|
|
})
|
|
|
|
it('il click su REFERTO invoca generaReferto con lo stato', async () => {
|
|
const wrapper = mountController()
|
|
setPartitaFinita(wrapper)
|
|
await wrapper.vm.$nextTick()
|
|
const btn = wrapper.findAll('.btn-secondary').find(b => b.text().includes('REFERTO'))
|
|
await btn.trigger('click')
|
|
expect(generaReferto).toHaveBeenCalledWith(wrapper.vm.state)
|
|
})
|
|
|
|
it('NON mostra il bottone REFERTO a set vinto (partita non finita)', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.state.modalitaPartita = '3/5'
|
|
wrapper.vm.setVintoTeam = 'home'
|
|
wrapper.vm.showSetVinto = true
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.vm.isPartitaFinita).toBe(false)
|
|
const btn = wrapper.findAll('.btn-secondary').find(b => b.text().includes('REFERTO'))
|
|
expect(btn).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// TIME OUT
|
|
// =============================================
|
|
describe('Time Out', () => {
|
|
it('il click su Time Out apre la modal con l\'elenco dei video', async () => {
|
|
fetchMock.mockResolvedValueOnce({ json: async () => ['a.mp4', 'b.mp4'] })
|
|
const wrapper = mountController()
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
await flushPromises()
|
|
expect(wrapper.vm.showTimeoutModal).toBe(true)
|
|
expect(wrapper.find('.dialog-timeout').exists()).toBe(true)
|
|
expect(wrapper.vm.spotList).toEqual(['a.mp4', 'b.mp4'])
|
|
// le opzioni sono i video più "Nessun video"
|
|
expect(wrapper.findAll('.timeout-video-option')).toHaveLength(3)
|
|
})
|
|
|
|
it('se /spot/list fallisce la modal si apre comunque senza video', async () => {
|
|
fetchMock.mockRejectedValueOnce(new Error('rete assente'))
|
|
const wrapper = mountController()
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
await flushPromises()
|
|
expect(wrapper.vm.showTimeoutModal).toBe(true)
|
|
expect(wrapper.vm.spotList).toEqual([])
|
|
})
|
|
|
|
it('Avvia è disabilitato finché non si sceglie la squadra', async () => {
|
|
const wrapper = mountController()
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
await flushPromises()
|
|
const avvia = wrapper.find('.dialog-timeout .btn-confirm')
|
|
expect(avvia.attributes('disabled')).toBeDefined()
|
|
await wrapper.find('.dialog-timeout .btn-set.home-bg').trigger('click')
|
|
expect(avvia.attributes('disabled')).toBeUndefined()
|
|
})
|
|
|
|
it('Avvia invia startTimeout con squadra e video e chiude la modal', async () => {
|
|
fetchMock.mockResolvedValueOnce({ json: async () => ['a.mp4'] })
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
await flushPromises()
|
|
await wrapper.find('.dialog-timeout .btn-set.guest-bg').trigger('click')
|
|
wrapper.vm.timeoutVideoSel = 'a.mp4'
|
|
await wrapper.find('.dialog-timeout .btn-confirm').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'startTimeout', team: 'guest', video: 'a.mp4' })
|
|
expect(wrapper.vm.showTimeoutModal).toBe(false)
|
|
})
|
|
|
|
it('durante il time out il bottone invia stopTimeout', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
wrapper.vm.state.timeout = true
|
|
wrapper.vm.state.timeoutTeam = 'home'
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'stopTimeout' })
|
|
})
|
|
|
|
it('avviaTimeout non invia nulla se nessuna squadra è selezionata', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.timeoutTeamSel = null
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
wrapper.vm.avviaTimeout()
|
|
expect(spy).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('il ticker del time out aggiorna nowTick periodicamente', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.state.timeoutTeam = 'home'
|
|
wrapper.vm.state.timeoutStartedAt = Date.now()
|
|
wrapper.vm.state.timeout = true
|
|
await wrapper.vm.$nextTick()
|
|
const before = wrapper.vm.nowTick
|
|
vi.advanceTimersByTime(500)
|
|
expect(wrapper.vm.nowTick).toBeGreaterThan(before)
|
|
})
|
|
|
|
it('durante il time out mostra banner con squadra e countdown', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.state.timeoutTeam = 'home'
|
|
wrapper.vm.state.timeoutStartedAt = Date.now() - 10000
|
|
wrapper.vm.state.timeout = true
|
|
await wrapper.vm.$nextTick()
|
|
const banner = wrapper.find('.timeout-banner')
|
|
expect(banner.exists()).toBe(true)
|
|
expect(banner.text()).toContain('TIME OUT')
|
|
expect(banner.text()).toContain('Antoniana')
|
|
expect(banner.text()).toContain('00:20')
|
|
// anche il bottone mostra il countdown
|
|
expect(wrapper.find('.btn-timeout').text()).toBe('00:20')
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// MODALITÀ ESTESA (landscape)
|
|
// =============================================
|
|
describe('Modalità estesa', () => {
|
|
it('con isLandscape=true mostra il layout esteso con i pannelli squadra', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.isLandscape = true
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.find('.e-dash').exists()).toBe(true)
|
|
expect(wrapper.findAll('.e-panel')).toHaveLength(2)
|
|
// in modalità estesa non compare il layout mobile
|
|
expect(wrapper.find('.score-preview').exists()).toBe(false)
|
|
})
|
|
|
|
it('il resize della finestra aggiorna isLandscape', async () => {
|
|
const wrapper = mountController()
|
|
expect(wrapper.vm.isLandscape).toBe(false)
|
|
Object.defineProperty(window, 'innerWidth', { value: 800, writable: true, configurable: true })
|
|
Object.defineProperty(window, 'innerHeight', { value: 400, writable: true, configurable: true })
|
|
window.dispatchEvent(new Event('resize'))
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.vm.isLandscape).toBe(true)
|
|
// ripristina le dimensioni portrait usate dagli altri test
|
|
Object.defineProperty(window, 'innerWidth', { value: 400, writable: true, configurable: true })
|
|
Object.defineProperty(window, 'innerHeight', { value: 800, writable: true, configurable: true })
|
|
})
|
|
|
|
it('il click sul punteggio in modalità estesa invia incPunt', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.isLandscape = true
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.findAll('.e-panel__score')[0].trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incPunt', team: 'home' })
|
|
})
|
|
|
|
it('smontare il componente rimuove i listener di resize e ferma il ticker del time out', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.state.timeout = true
|
|
await wrapper.vm.$nextTick()
|
|
expect(vi.getTimerCount()).toBeGreaterThan(0)
|
|
const removeSpy = vi.spyOn(window, 'removeEventListener')
|
|
wrapper.unmount()
|
|
expect(removeSpy).toHaveBeenCalledWith('resize', expect.any(Function))
|
|
expect(removeSpy).toHaveBeenCalledWith('orientationchange', expect.any(Function))
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// SET VINTO AUTOMATICO (watch squadraVincente)
|
|
// =============================================
|
|
describe('Set vinto automatico', () => {
|
|
it('apre la modal SET VINTO quando il punteggio raggiunge la soglia', async () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 25, 10)
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.vm.showSetVinto).toBe(true)
|
|
expect(wrapper.vm.setVintoTeam).toBe('home')
|
|
expect(wrapper.find('.dialog-title').text()).toBe('SET VINTO')
|
|
})
|
|
|
|
it('non riapre la modal se è già aperta', async () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 25, 10)
|
|
await wrapper.vm.$nextTick()
|
|
wrapper.vm.setVintoTeam = 'guest'
|
|
setScore(wrapper, 25, 24)
|
|
await wrapper.vm.$nextTick()
|
|
// il watch non deve sovrascrivere setVintoTeam perché showSetVinto è già true
|
|
expect(wrapper.vm.setVintoTeam).toBe('guest')
|
|
})
|
|
|
|
it('INDIETRO annulla l\'ultimo punto e chiude la modal', async () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 25, 10)
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.btn-cancel').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'decPunt' })
|
|
expect(wrapper.vm.showSetVinto).toBe(false)
|
|
})
|
|
|
|
it('VAI AL SET SUCCESSIVO invia nuovoSet e apre la configurazione', async () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 25, 10)
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
const btn = wrapper.findAll('.btn-confirm').find(b => b.text().includes('SET SUCCESSIVO'))
|
|
await btn.trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'nuovoSet', team: 'home' })
|
|
expect(wrapper.vm.showSetVinto).toBe(false)
|
|
expect(wrapper.vm.showConfig).toBe(true)
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// CONFIGURAZIONE
|
|
// =============================================
|
|
describe('Configurazione', () => {
|
|
it('apre la modal di configurazione precompilata con lo stato corrente', async () => {
|
|
const wrapper = mountController()
|
|
await wrapper.find('.btn-ctrl:not(.btn-timeout)').exists()
|
|
const btn = wrapper.findAll('.btn-ctrl').find(b => b.text() === 'Config')
|
|
await btn.trigger('click')
|
|
expect(wrapper.vm.showConfig).toBe(true)
|
|
expect(wrapper.vm.configData.nomeHome).toBe('Antoniana')
|
|
expect(wrapper.vm.configData.nomeGuest).toBe('Guest')
|
|
expect(wrapper.vm.configData.modalita).toBe('3/5')
|
|
})
|
|
|
|
it('OK invia le action di configurazione e chiude la modal', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showConfig = true
|
|
wrapper.vm.configData = {
|
|
nomeHome: 'Casa', nomeGuest: 'Ospiti', modalita: '2/3',
|
|
formHome: ['1', '2', '3', '4', '5', '6'],
|
|
formGuest: ['1', '2', '3', '4', '5', '6'],
|
|
}
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.dialog-config .btn-confirm').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'setNomi', home: 'Casa', guest: 'Ospiti' })
|
|
expect(spy).toHaveBeenCalledWith({ type: 'setModalita', modalita: '2/3' })
|
|
expect(spy).toHaveBeenCalledWith({ type: 'setFormazione', team: 'home', form: ['1', '2', '3', '4', '5', '6'] })
|
|
expect(spy).toHaveBeenCalledWith({ type: 'setFormazione', team: 'guest', form: ['1', '2', '3', '4', '5', '6'] })
|
|
expect(wrapper.vm.showConfig).toBe(false)
|
|
})
|
|
|
|
it('Annulla chiude la modal di configurazione senza inviare nulla', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showConfig = true
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.dialog-config .btn-cancel').trigger('click')
|
|
expect(spy).not.toHaveBeenCalled()
|
|
expect(wrapper.vm.showConfig).toBe(false)
|
|
})
|
|
|
|
it('scegliendo la modalità 2/3 il bottone diventa attivo', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showConfig = true
|
|
await wrapper.vm.$nextTick()
|
|
const btn23 = wrapper.findAll('.btn-mode').find(b => b.text() === '2/3')
|
|
await btn23.trigger('click')
|
|
expect(wrapper.vm.configData.modalita).toBe('2/3')
|
|
expect(btn23.classes()).toContain('active')
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// GESTIONE CAMBI GIOCATORE
|
|
// =============================================
|
|
describe('Gestione cambi', () => {
|
|
it('il click su Cambi apre la selezione squadra, poi la modal cambio per la squadra scelta', async () => {
|
|
const wrapper = mountController()
|
|
const btnCambi = wrapper.findAll('.btn-ctrl').find(b => b.text() === 'Cambi')
|
|
await btnCambi.trigger('click')
|
|
expect(wrapper.vm.showCambiTeam).toBe(true)
|
|
await wrapper.find('.dialog-title').exists()
|
|
const btnHome = wrapper.find('.overlay .btn-set.home-bg')
|
|
await btnHome.trigger('click')
|
|
expect(wrapper.vm.showCambiTeam).toBe(false)
|
|
expect(wrapper.vm.showCambi).toBe(true)
|
|
expect(wrapper.vm.cambiTeam).toBe('home')
|
|
})
|
|
|
|
it('Annulla chiude la modal cambi e azzera i campi', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
wrapper.vm.cambiData = [{ in: '10', out: '1' }, { in: '', out: '' }]
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.dialog .btn-cancel').trigger('click')
|
|
expect(wrapper.vm.showCambi).toBe(false)
|
|
expect(wrapper.vm.cambiData).toEqual([{ in: '', out: '' }, { in: '', out: '' }])
|
|
})
|
|
|
|
it('CONFERMA con un cambio valido invia confermaCambi e chiude la modal', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
wrapper.vm.cambiData = [{ in: '10', out: '1' }, { in: '', out: '' }]
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.dialog .btn-confirm').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'confermaCambi', team: 'home', cambi: [{ in: '10', out: '1' }] })
|
|
expect(wrapper.vm.showCambi).toBe(false)
|
|
})
|
|
|
|
it('segnala errore se il numero del giocatore non è formato da sole cifre', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
wrapper.vm.cambiData = [{ in: 'ab', out: '1' }, { in: '', out: '' }]
|
|
wrapper.vm.confermaCambi()
|
|
expect(wrapper.vm.cambiError).toBe('I numeri dei giocatori devono essere cifre')
|
|
})
|
|
|
|
it('segnala errore se il giocatore entrante coincide con l\'uscente', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
wrapper.vm.cambiData = [{ in: '1', out: '1' }, { in: '', out: '' }]
|
|
wrapper.vm.confermaCambi()
|
|
expect(wrapper.vm.cambiError).toBe('Il giocatore 1 non può sostituire sé stesso')
|
|
})
|
|
|
|
it('segnala errore se il giocatore entrante è già in formazione', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
// "2" è già presente nella formazione di default ["1".."6"]
|
|
wrapper.vm.cambiData = [{ in: '2', out: '1' }, { in: '', out: '' }]
|
|
wrapper.vm.confermaCambi()
|
|
expect(wrapper.vm.cambiError).toBe('Il giocatore 2 è già in formazione')
|
|
})
|
|
|
|
it('segnala errore se il giocatore uscente non è in formazione', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
wrapper.vm.cambiData = [{ in: '10', out: '9' }, { in: '', out: '' }]
|
|
wrapper.vm.confermaCambi()
|
|
expect(wrapper.vm.cambiError).toBe('Il giocatore 9 non è in formazione')
|
|
})
|
|
|
|
it('confermaCambi non fa nulla se cambiValid è false', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
wrapper.vm.cambiData = [{ in: '', out: '' }, { in: '', out: '' }]
|
|
wrapper.vm.confermaCambi()
|
|
expect(spy).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// GESTIONE ERRORI WEBSOCKET
|
|
// =============================================
|
|
describe('Gestione errori WebSocket', () => {
|
|
it('onWsMessage con type error logga il messaggio', () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
wrapper.vm.onWsMessage({ type: 'error', message: 'boom' })
|
|
expect(spy).toHaveBeenCalledWith('[Controller] Error:', 'boom')
|
|
spy.mockRestore()
|
|
})
|
|
|
|
it('sendAction senza type non invia nulla', () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendWs')
|
|
wrapper.vm.sendAction({})
|
|
expect(spy).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('sendAction mostra un feedback di errore se non connesso', () => {
|
|
const wrapper = mountController()
|
|
const errSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
wrapper.vm.wsConnected = false
|
|
wrapper.vm.sendAction({ type: 'incPunt', team: 'home' })
|
|
expect(errSpy).toHaveBeenCalledWith('[Controller] Error:', 'Non connesso al server')
|
|
errSpy.mockRestore()
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// DURATA VIDEO SPOT
|
|
// =============================================
|
|
describe('Durata video spot', () => {
|
|
it('formatDurata mostra i secondi arrotondati o un placeholder', () => {
|
|
const wrapper = mountController()
|
|
expect(wrapper.vm.formatDurata(12.4)).toBe('12s')
|
|
expect(wrapper.vm.formatDurata(undefined)).toBe('…')
|
|
expect(wrapper.vm.formatDurata(NaN)).toBe('…')
|
|
})
|
|
|
|
it('probeDurata popola spotDurations quando i metadata del video sono pronti', () => {
|
|
const wrapper = mountController()
|
|
const videoEls = []
|
|
const originalCreateElement = document.createElement.bind(document)
|
|
vi.spyOn(document, 'createElement').mockImplementation((tag) => {
|
|
const el = originalCreateElement(tag)
|
|
if (tag === 'video') videoEls.push(el)
|
|
return el
|
|
})
|
|
wrapper.vm.probeDurata('a.mp4')
|
|
const videoEl = videoEls[0]
|
|
Object.defineProperty(videoEl, 'duration', { value: 42, configurable: true })
|
|
videoEl.onloadedmetadata()
|
|
expect(wrapper.vm.spotDurations['a.mp4']).toBe(42)
|
|
document.createElement.mockRestore()
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// PULSANTI MOBILE (click reali sui bottoni)
|
|
// =============================================
|
|
describe('Pulsanti layout mobile', () => {
|
|
it('ANNULLA PUNTO invia decPunt', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.btn-undo').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'decPunt' })
|
|
})
|
|
|
|
it('i due bottoni SET inviano incSet per la rispettiva squadra', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
const setBtns = wrapper.findAll('.action-row .btn-set')
|
|
await setBtns[0].trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incSet', team: 'home' })
|
|
await setBtns[1].trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incSet', team: 'guest' })
|
|
})
|
|
|
|
it('Formazioni/Striscia/Inverti/Voce inviano le rispettive action', async () => {
|
|
const wrapper = mountController()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
const byLabel = (label) => wrapper.findAll('.btn-ctrl').find(b => b.text().includes(label))
|
|
await byLabel('Formazioni').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'toggleFormazione' })
|
|
await byLabel('Striscia').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'toggleStriscia' })
|
|
await byLabel('Inverti').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'toggleOrder' })
|
|
const wsSendSpy = vi.spyOn(wrapper.vm, 'sendWs')
|
|
wrapper.vm.wsConnected = true
|
|
wrapper.vm.ws = { readyState: 1, send: vi.fn() }
|
|
await byLabel('Voce').trigger('click')
|
|
expect(wsSendSpy).toHaveBeenCalled()
|
|
})
|
|
|
|
it('con order=false lo score-preview mostra prima guest e poi home', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.state.order = false
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
const scores = wrapper.findAll('.team-score')
|
|
expect(scores[0].classes()).toContain('guest-bg')
|
|
expect(scores[1].classes()).toContain('home-bg')
|
|
await scores[0].trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incPunt', team: 'guest' })
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// MODALITÀ ESTESA: interazioni aggiuntive
|
|
// =============================================
|
|
describe('Modalità estesa: interazioni', () => {
|
|
it('il click sul punteggio e sul bottone SET della seconda squadra funzionano', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.isLandscape = true
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.findAll('.e-panel__score')[1].trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incPunt', team: 'guest' })
|
|
await wrapper.findAll('.e-panel__setbtn')[0].trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incSet', team: 'home' })
|
|
await wrapper.findAll('.e-panel__setbtn')[1].trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'incSet', team: 'guest' })
|
|
})
|
|
|
|
it('la barra e-actions invia le action corrispondenti ai bottoni', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.isLandscape = true
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
const byLabel = (label) => wrapper.findAll('.e-act').find(b => b.text().includes(label))
|
|
await byLabel('Annulla').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'decPunt' })
|
|
await byLabel('Cambio Palla').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'cambiaPalla' })
|
|
await byLabel('Inverti').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'toggleOrder' })
|
|
await byLabel('Striscia').trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'toggleStriscia' })
|
|
expect(wrapper.vm.showCambiTeam).toBe(false)
|
|
const btnCambi = wrapper.findAll('.e-act').find(b => b.text() === 'Cambi')
|
|
await btnCambi.trigger('click')
|
|
expect(wrapper.vm.showCambiTeam).toBe(true)
|
|
wrapper.vm.showCambiTeam = false
|
|
await byLabel('Config').trigger('click')
|
|
expect(wrapper.vm.showConfig).toBe(true)
|
|
wrapper.vm.showConfig = false
|
|
await wrapper.find('.e-act--danger').trigger('click')
|
|
expect(wrapper.vm.confirmReset).toBe(true)
|
|
})
|
|
|
|
it('il bottone Voce e il bottone Time Out della barra estesa funzionano', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.isLandscape = true
|
|
await wrapper.vm.$nextTick()
|
|
wrapper.vm.wsConnected = true
|
|
wrapper.vm.ws = { readyState: 1, send: vi.fn() }
|
|
const wsSendSpy = vi.spyOn(wrapper.vm, 'sendWs')
|
|
const btnVoce = wrapper.findAll('.e-act').find(b => b.text() === 'Voce')
|
|
await btnVoce.trigger('click')
|
|
expect(wsSendSpy).toHaveBeenCalled()
|
|
|
|
const btnTimeout = wrapper.find('.e-act.btn-timeout')
|
|
await btnTimeout.trigger('click')
|
|
expect(wrapper.vm.showTimeoutModal).toBe(true)
|
|
wrapper.vm.showTimeoutModal = false
|
|
wrapper.vm.state.timeout = true
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await btnTimeout.trigger('click')
|
|
expect(spy).toHaveBeenCalledWith({ type: 'stopTimeout' })
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// CHIUSURA DIALOG CLICCANDO FUORI (overlay self)
|
|
// =============================================
|
|
describe('Chiusura dialog cliccando fuori', () => {
|
|
it('conferma reset si chiude cliccando fuori dal dialog', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.confirmReset = true
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.overlay').trigger('click')
|
|
expect(wrapper.vm.confirmReset).toBe(false)
|
|
})
|
|
|
|
it('configurazione si chiude cliccando fuori dal dialog', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showConfig = true
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.overlay').trigger('click')
|
|
expect(wrapper.vm.showConfig).toBe(false)
|
|
})
|
|
|
|
it('scelta squadra cambi si chiude cliccando fuori dal dialog', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showCambiTeam = true
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.overlay').trigger('click')
|
|
expect(wrapper.vm.showCambiTeam).toBe(false)
|
|
})
|
|
|
|
it('la modal cambi si chiude cliccando fuori dal dialog', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.overlay').trigger('click')
|
|
expect(wrapper.vm.showCambi).toBe(false)
|
|
})
|
|
|
|
it('la modal time out si chiude cliccando fuori dal dialog', async () => {
|
|
const wrapper = mountController()
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
await flushPromises()
|
|
await wrapper.find('.overlay').trigger('click')
|
|
expect(wrapper.vm.showTimeoutModal).toBe(false)
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// DIALOG PARTITA FINITA / CONFIGURAZIONE: dettagli
|
|
// =============================================
|
|
describe('Dettagli dialog', () => {
|
|
it('CHIUDI chiude il dialog partita finita senza inviare action', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.state.modalitaPartita = '2/3'
|
|
wrapper.vm.state.sp.striscia = [
|
|
{ serv: 'h', ris: '', vinc: 'h' },
|
|
{ serv: 'h', ris: '', vinc: null },
|
|
]
|
|
wrapper.vm.setVintoTeam = 'home'
|
|
wrapper.vm.showSetVinto = true
|
|
await wrapper.vm.$nextTick()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
const chiudi = wrapper.findAll('.btn-confirm').find(b => b.text() === 'CHIUDI')
|
|
await chiudi.trigger('click')
|
|
expect(spy).not.toHaveBeenCalled()
|
|
expect(wrapper.vm.showSetVinto).toBe(false)
|
|
})
|
|
|
|
it('isPartitaFinita è false in modalità amichevole anche a set vinto', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.state.modalitaPartita = 'amichevole'
|
|
wrapper.vm.setVintoTeam = 'home'
|
|
expect(wrapper.vm.isPartitaFinita).toBe(false)
|
|
})
|
|
|
|
it('la vittoria della squadra guest apre comunque la modal SET VINTO', async () => {
|
|
const wrapper = mountController()
|
|
setScore(wrapper, 10, 25, 'g')
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.vm.setVintoTeam).toBe('guest')
|
|
})
|
|
|
|
it('nel set decisivo la soglia di vittoria scende a 15 punti', async () => {
|
|
const wrapper = mountController()
|
|
// 4 set già assegnati (2 a testa): il quinto è il set decisivo (3/5)
|
|
wrapper.vm.state.sp.striscia = [
|
|
{ serv: 'h', ris: '', vinc: 'h' },
|
|
{ serv: 'h', ris: '', vinc: 'g' },
|
|
{ serv: 'h', ris: '', vinc: 'h' },
|
|
{ serv: 'h', ris: '', vinc: 'g' },
|
|
{ serv: 'h', ris: '', vinc: null },
|
|
]
|
|
setScore(wrapper, 15, 10)
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.vm.setVintoTeam).toBe('home')
|
|
})
|
|
|
|
it('i bottoni modalità 3/5 e amichevole aggiornano configData', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showConfig = true
|
|
await wrapper.vm.$nextTick()
|
|
const btn35 = wrapper.findAll('.btn-mode').find(b => b.text() === '3/5')
|
|
await btn35.trigger('click')
|
|
expect(wrapper.vm.configData.modalita).toBe('3/5')
|
|
const btnAmichevole = wrapper.findAll('.btn-mode').find(b => b.text() === 'Amichevole')
|
|
await btnAmichevole.trigger('click')
|
|
expect(wrapper.vm.configData.modalita).toBe('amichevole')
|
|
expect(btnAmichevole.classes()).toContain('active')
|
|
})
|
|
|
|
it('i campi di testo di configurazione aggiornano configData tramite v-model', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showConfig = true
|
|
await wrapper.vm.$nextTick()
|
|
const inputs = wrapper.findAll('.dialog-config .input-field')
|
|
await inputs[0].setValue('Casa Nuova')
|
|
await inputs[1].setValue('Ospiti Nuovi')
|
|
expect(wrapper.vm.configData.nomeHome).toBe('Casa Nuova')
|
|
expect(wrapper.vm.configData.nomeGuest).toBe('Ospiti Nuovi')
|
|
})
|
|
|
|
it('i campi numerici della formazione aggiornano configData tramite v-model', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showConfig = true
|
|
await wrapper.vm.$nextTick()
|
|
const numInputs = wrapper.findAll('.dialog-config .input-num')
|
|
// 6 campi per home + 6 per guest: li valorizziamo tutti per coprire ogni binding v-model
|
|
for (let i = 0; i < numInputs.length; i++) {
|
|
await numInputs[i].setValue(String(i))
|
|
}
|
|
// il DOM ordina le celle come 3,2,1 / 4,5,0: verifichiamo l'insieme dei valori digitati
|
|
expect(new Set(wrapper.vm.configData.formHome)).toEqual(new Set(['0', '1', '2', '3', '4', '5']))
|
|
expect(new Set(wrapper.vm.configData.formGuest)).toEqual(new Set(['6', '7', '8', '9', '10', '11']))
|
|
})
|
|
|
|
it('la selezione squadra guest per i cambi apre la modal con cambiTeam=guest', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.showCambiTeam = true
|
|
await wrapper.vm.$nextTick()
|
|
await wrapper.find('.overlay .btn-set.guest-bg').trigger('click')
|
|
expect(wrapper.vm.cambiTeam).toBe('guest')
|
|
expect(wrapper.vm.showCambi).toBe(true)
|
|
})
|
|
|
|
it('i campi IN/OUT della modal cambi aggiornano cambiData tramite v-model', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.openCambi('home')
|
|
await wrapper.vm.$nextTick()
|
|
const inField = wrapper.find('.cambi-in-field')
|
|
const outField = wrapper.find('.cambi-out-field')
|
|
await inField.setValue('10')
|
|
await outField.setValue('1')
|
|
expect(wrapper.vm.cambiData[0]).toEqual({ in: '10', out: '1' })
|
|
})
|
|
|
|
it('nella modal time out si può selezionare un video dall\'elenco tramite radio', async () => {
|
|
fetchMock.mockResolvedValueOnce({ json: async () => ['a.mp4'] })
|
|
const wrapper = mountController()
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
await flushPromises()
|
|
const radios = wrapper.findAll('input[type=radio]')
|
|
await radios[0].setValue(true)
|
|
expect(wrapper.vm.timeoutVideoSel).toBe('a.mp4')
|
|
await radios[1].setValue(true)
|
|
expect(wrapper.vm.timeoutVideoSel).toBe(null)
|
|
})
|
|
|
|
it('Annulla nella modal time out la chiude senza avviarlo', async () => {
|
|
const wrapper = mountController()
|
|
await wrapper.find('.btn-timeout').trigger('click')
|
|
await flushPromises()
|
|
const spy = vi.spyOn(wrapper.vm, 'sendAction')
|
|
await wrapper.find('.dialog-timeout .btn-cancel').trigger('click')
|
|
expect(spy).not.toHaveBeenCalled()
|
|
expect(wrapper.vm.showTimeoutModal).toBe(false)
|
|
})
|
|
})
|
|
|
|
// =============================================
|
|
// BARRA CONNESSIONE
|
|
// =============================================
|
|
describe('Barra connessione', () => {
|
|
it('dovrebbe avere classe "connected" quando connesso', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.wsConnected = true
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.find('.conn-bar').classes()).toContain('connected')
|
|
})
|
|
|
|
it('non dovrebbe avere classe "connected" quando disconnesso', () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.wsConnected = false
|
|
expect(wrapper.find('.conn-bar').classes()).not.toContain('connected')
|
|
})
|
|
|
|
it('dovrebbe mostrare "Connesso" quando connesso', async () => {
|
|
const wrapper = mountController()
|
|
wrapper.vm.wsConnected = true
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.find('.conn-bar').text()).toContain('Connesso')
|
|
})
|
|
})
|
|
})
|