import { test, expect, describe } from "bun:test"; import { ClientManager } from "../src/services/ClientManager.ts"; import { SignalingService } from "../src/services/SignalingService.ts"; import type { IWebSocketClient } from "../src/interfaces/ISignalingMessage.ts"; class MockWebSocket { sentMessages: string[] = []; send(data: string) { this.sentMessages.push(data); } close() {} } describe("Basic WebRTC Broadcasting Tests", () => { test("ClientManager should add and retrieve clients", () => { const clientManager = new ClientManager(); const mockWs = new MockWebSocket(); const client: IWebSocketClient = { id: "test-client", ws: mockWs, role: "publisher" }; clientManager.addClient(client); expect(clientManager.getClient("test-client")).toBe(client); expect(clientManager.getPublisher()).toBe(client); }); test("ClientManager should track subscribers separately", () => { const clientManager = new ClientManager(); const subscriber1: IWebSocketClient = { id: "sub-1", ws: new MockWebSocket(), role: "subscriber" }; const subscriber2: IWebSocketClient = { id: "sub-2", ws: new MockWebSocket(), role: "subscriber" }; clientManager.addClient(subscriber1); clientManager.addClient(subscriber2); const subscribers = clientManager.getSubscribers(); expect(subscribers.length).toBe(2); expect(subscribers).toContain(subscriber1); expect(subscribers).toContain(subscriber2); }); test("SignalingService should create client connections", () => { const clientManager = new ClientManager(); const signalingService = new SignalingService(clientManager); const mockWs = new MockWebSocket(); const clientId = signalingService.handleConnection(mockWs, "publisher"); expect(typeof clientId).toBe("string"); expect(clientId.length).toBeGreaterThan(0); expect(mockWs.sentMessages.length).toBe(1); const message = JSON.parse(mockWs.sentMessages[0]); expect(message.type).toBe("join"); expect(message.data.clientId).toBe(clientId); expect(message.data.role).toBe("publisher"); }); test("SignalingService should handle disconnections", () => { const clientManager = new ClientManager(); const signalingService = new SignalingService(clientManager); const mockWs = new MockWebSocket(); const clientId = signalingService.handleConnection(mockWs, "publisher"); expect(clientManager.getPublisher()).toBeTruthy(); signalingService.handleDisconnection(clientId); expect(clientManager.getPublisher()).toBeNull(); }); test("Complete publisher-subscriber flow", () => { const clientManager = new ClientManager(); const signalingService = new SignalingService(clientManager); // Add publisher const publisherWs = new MockWebSocket(); const publisherId = signalingService.handleConnection(publisherWs, "publisher"); // Add subscriber const subscriberWs = new MockWebSocket(); const subscriberId = signalingService.handleConnection(subscriberWs, "subscriber"); // Clear initial connection messages publisherWs.sentMessages = []; subscriberWs.sentMessages = []; // Send offer from publisher const offerMessage = { type: "offer" as const, data: { sdp: "test-offer" } }; signalingService.handleMessage(publisherId, offerMessage); // Check subscriber received the offer expect(subscriberWs.sentMessages.length).toBe(1); const receivedMessage = JSON.parse(subscriberWs.sentMessages[0]); expect(receivedMessage.type).toBe("offer"); expect(receivedMessage.data.sdp).toBe("test-offer"); expect(receivedMessage.senderId).toBe(publisherId); // Send answer from subscriber const answerMessage = { type: "answer" as const, data: { sdp: "test-answer" } }; signalingService.handleMessage(subscriberId, answerMessage); // Check publisher received the answer expect(publisherWs.sentMessages.length).toBe(1); const publisherMessage = JSON.parse(publisherWs.sentMessages[0]); expect(publisherMessage.type).toBe("answer"); expect(publisherMessage.data.sdp).toBe("test-answer"); expect(publisherMessage.senderId).toBe(subscriberId); }); });