diff --git a/tests/component/wsMixin.test.js b/tests/component/wsMixin.test.js index 69d4eef..52dbcd5 100644 --- a/tests/component/wsMixin.test.js +++ b/tests/component/wsMixin.test.js @@ -224,5 +224,102 @@ describe('createWsMixin (wsMixin.js)', () => { wrapper.unmount() expect(ws.close).toHaveBeenCalled() }) + + it('beforeUnmount con connessione OPEN chiude con codice 1000', () => { + const wrapper = mountWith() + const ws = ultimaWs() + ws.readyState = MockWebSocket.OPEN + wrapper.unmount() + expect(ws.close).toHaveBeenCalledWith(1000, 'Component unmounting') + }) + + it('beforeUnmount non lancia se ws.close lancia', () => { + const wrapper = mountWith() + const ws = ultimaWs() + ws.readyState = MockWebSocket.OPEN + ws.close.mockImplementation(() => { throw new Error('già chiusa') }) + const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}) + expect(() => wrapper.unmount()).not.toThrow() + expect(consoleSpy).toHaveBeenCalled() + }) + + it('beforeUnmount annulla un reconnectTimeout pendente', () => { + vi.useFakeTimers() + try { + const wrapper = mountWith() + wrapper.vm.isConnecting = false + wrapper.vm.scheduleReconnect() + expect(wrapper.vm.reconnectTimeout).not.toBe(null) + wrapper.unmount() + // se il timer non fosse stato annullato, allo scoccare del delay + // verrebbe creata una nuova connessione anche a componente smontato + const primaDelTimeout = MockWebSocket.instances.length + vi.advanceTimersByTime(30000) + expect(MockWebSocket.instances.length).toBe(primaDelTimeout) + } finally { + vi.useRealTimers() + } + }) + }) + + describe('rami aggiuntivi', () => { + it('connectWebSocket non fa nulla se è già in corso un tentativo di connessione', () => { + const wrapper = mountWith() + const primaDelTimeout = MockWebSocket.instances.length + wrapper.vm.isConnecting = true + wrapper.vm.connectWebSocket() + expect(MockWebSocket.instances.length).toBe(primaDelTimeout) + }) + + it('riconnettendosi con la WebSocket precedente OPEN, la chiude con codice 1000', () => { + const wrapper = mountWith() + const prima = ultimaWs() + prima.readyState = MockWebSocket.OPEN + wrapper.vm.isConnecting = false + wrapper.vm.connectWebSocket() + expect(prima.close).toHaveBeenCalledWith(1000, 'Reconnecting') + }) + + it('se la chiusura della WebSocket precedente lancia, logga e continua a riconnettersi', () => { + const wrapper = mountWith() + const prima = ultimaWs() + prima.readyState = MockWebSocket.OPEN + prima.close.mockImplementation(() => { throw new Error('già chiusa') }) + const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}) + wrapper.vm.isConnecting = false + + expect(() => wrapper.vm.connectWebSocket()).not.toThrow() + expect(consoleSpy).toHaveBeenCalled() + expect(ultimaWs()).not.toBe(prima) + }) + + it('onopen non lancia se il registro fallisce (send che lancia)', () => { + const wrapper = mountWith() + const ws = ultimaWs() + ws.readyState = MockWebSocket.OPEN + ws.send.mockImplementation(() => { throw new Error('boom') }) + const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}) + + expect(() => ws.onopen()).not.toThrow() + expect(wrapper.vm.wsConnected).toBe(true) + expect(consoleSpy).toHaveBeenCalled() + }) + + it('onmessage non lancia su JSON non valido', () => { + mountWith() + const ws = ultimaWs() + const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}) + + expect(() => ws.onmessage({ data: 'non è JSON {{{' })).not.toThrow() + expect(consoleSpy).toHaveBeenCalled() + }) + + it('scheduleReconnect non arma un secondo timer se uno è già pendente', () => { + const wrapper = mountWith() + const spy = vi.spyOn(globalThis, 'setTimeout') + wrapper.vm.reconnectTimeout = 123 // timer già pendente (valore fittizio) + wrapper.vm.scheduleReconnect() + expect(spy).not.toHaveBeenCalled() + }) }) })