import { DyNTS_SocketPresence } from './socket-presence.control-model'; import { DyFM_Error } from '@futdevpro/fsm-dynamo'; import * as SocketIO from 'socket.io'; describe('| DyNTS_SocketPresence', () => { let mockSocket1: jasmine.SpyObj; let mockSocket2: jasmine.SpyObj; beforeEach(() => { mockSocket1 = jasmine.createSpyObj('Socket', ['emit', 'disconnect']); mockSocket1.connected = true; Object.defineProperty(mockSocket1, 'id', { value: 'socket-1', writable: false }); mockSocket2 = jasmine.createSpyObj('Socket', ['emit', 'disconnect']); mockSocket2.connected = true; Object.defineProperty(mockSocket2, 'id', { value: 'socket-2', writable: false }); }); it('| should create presence instance', () => { const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1], issuer: 'test-issuer', }); expect(presence).toBeDefined(); expect(presence.issuerLocalId).toBe('user-123'); expect(presence.sockets).toEqual([mockSocket1]); }); it('| should throw error when issuerLocalId is missing', () => { expect(() => { new DyNTS_SocketPresence({ sockets: [mockSocket1], issuer: 'test-issuer', }); }).toThrow(); }); it('| should throw error when sockets array is empty', () => { expect(() => { new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [], issuer: 'test-issuer', }); }).toThrow(); }); it('| should set service name', () => { const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1], serviceName: 'test-service', issuer: 'test-issuer', }); expect(presence.serviceName).toBe('test-service'); }); it('| should use default service name when not provided', () => { const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1], issuer: 'test-issuer', }); expect(presence.serviceName).toBe('unknown'); }); it('| should set onDestroy callback', () => { const onDestroy = jasmine.createSpy('onDestroy'); const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1], onDestroy, issuer: 'test-issuer', }); expect(presence.onDestroy).toBe(onDestroy); }); describe('| emitEvent', () => { it('| should emit event on all connected sockets', () => { const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1, mockSocket2], issuer: 'test-issuer', }); presence.emitEvent('test-event', { data: 'test' }, 'test-issuer'); expect(mockSocket1.emit).toHaveBeenCalledWith('test-event', { data: 'test' }, jasmine.any(Function)); expect(mockSocket2.emit).toHaveBeenCalledWith('test-event', { data: 'test' }, jasmine.any(Function)); }); it('| should throw error when content is not stringifyable', () => { const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1], issuer: 'test-issuer', }); const circular: any = { data: 'test' }; circular.self = circular; expect(() => { presence.emitEvent('test-event', circular, 'test-issuer'); }).toThrow(); }); it('| should remove disconnected sockets', () => { mockSocket1.connected = false; const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1, mockSocket2], issuer: 'test-issuer', }); presence.emitEvent('test-event', { data: 'test' }, 'test-issuer'); expect(presence.sockets).not.toContain(mockSocket1); expect(presence.sockets).toContain(mockSocket2); expect(mockSocket1.disconnect).toHaveBeenCalledWith(true); }); it('| should throw error when all sockets are disconnected', () => { mockSocket1.connected = false; mockSocket2.connected = false; const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1, mockSocket2], issuer: 'test-issuer', }); expect(() => { presence.emitEvent('test-event', { data: 'test' }, 'test-issuer'); }).toThrow(); }); it('| should throw error when emit fails on all sockets', () => { mockSocket1.emit.and.returnValue(false); mockSocket2.emit.and.returnValue(false); const presence = new DyNTS_SocketPresence({ issuerLocalId: 'user-123', sockets: [mockSocket1, mockSocket2], issuer: 'test-issuer', }); // The error will be thrown if callback is called with error const emitCall = mockSocket1.emit.calls.mostRecent(); if (emitCall && emitCall.args[2]) { emitCall.args[2](new Error('Emit failed')); } // The method should handle errors gracefully expect(() => { presence.emitEvent('test-event', { data: 'test' }, 'test-issuer'); }).not.toThrow(); }); }); });