import { describe, it, expect, beforeEach, vi } from 'vitest' import { createSession, clearSessions } from '../../server/utils/liveSessions.js' import { handleWebSocketMessage } from '../../server/utils/webrtcSignaling.js' vi.mock('../../server/utils/mediasoup.js', () => { const mockConnect = vi.fn().mockResolvedValue(undefined) const mockRouter = { id: 'mock-router', rtpCapabilities: { codecs: [] } } const mockTransport = { id: 'mock-transport', connect: mockConnect } return { getRouter: vi.fn().mockResolvedValue(mockRouter), createTransport: vi.fn().mockResolvedValue({ transport: mockTransport, params: { id: 'mock-transport', iceParameters: {}, iceCandidates: [], dtlsParameters: {} }, }), getTransport: vi.fn().mockReturnValue(mockTransport), closeRouter: vi.fn().mockResolvedValue(undefined), getProducer: vi.fn().mockReturnValue(null), } }) describe('webrtcSignaling', () => { const testState = { sessionId: null, } const userId = 'test-user' beforeEach(async () => { clearSessions() const session = await createSession(userId, 'Test') testState.sessionId = session.id }) it('returns error when session not found', async () => { const res = await handleWebSocketMessage(userId, 'non-existent-id', 'get-router-rtp-capabilities', {}) expect(res).toEqual({ error: 'Session not found' }) }) it('returns Forbidden when userId does not match session', async () => { const res = await handleWebSocketMessage('other-user', testState.sessionId, 'create-transport', {}) expect(res).toEqual({ error: 'Forbidden' }) }) it('returns error for unknown message type', async () => { const res = await handleWebSocketMessage(userId, testState.sessionId, 'unknown-type', {}) expect(res).toEqual({ error: 'Unknown message type: unknown-type' }) }) it('returns transportId and dtlsParameters required for connect-transport', async () => { const res = await handleWebSocketMessage(userId, testState.sessionId, 'connect-transport', {}) expect(res?.error).toContain('transportId') }) it('get-router-rtp-capabilities returns router RTP capabilities', async () => { const res = await handleWebSocketMessage(userId, testState.sessionId, 'get-router-rtp-capabilities', {}) expect(res?.type).toBe('router-rtp-capabilities') expect(res?.data).toEqual({ codecs: [] }) }) it('create-transport returns transport params', async () => { const res = await handleWebSocketMessage(userId, testState.sessionId, 'create-transport', {}) expect(res?.type).toBe('transport-created') expect(res?.data).toBeDefined() }) it('connect-transport connects with valid params', async () => { await handleWebSocketMessage(userId, testState.sessionId, 'create-transport', {}) const res = await handleWebSocketMessage(userId, testState.sessionId, 'connect-transport', { transportId: 'mock-transport', dtlsParameters: { role: 'client', fingerprints: [] }, }) expect(res?.type).toBe('transport-connected') expect(res?.data?.connected).toBe(true) }) it('returns error when transport.connect throws', async () => { const { getTransport } = await import('../../server/utils/mediasoup.js') getTransport.mockReturnValueOnce({ id: 'mock-transport', connect: vi.fn().mockRejectedValue(new Error('Connection failed')), }) await handleWebSocketMessage(userId, testState.sessionId, 'create-transport', {}) const res = await handleWebSocketMessage(userId, testState.sessionId, 'connect-transport', { transportId: 'mock-transport', dtlsParameters: { role: 'client', fingerprints: [] }, }) expect(res?.error).toBe('Connection failed') }) })