Files
WebRTC-Broadcast/tests/SignalingService.test.ts
2025-09-05 00:36:54 -04:00

176 lines
5.2 KiB
TypeScript

import { test, expect, describe, beforeEach } from "bun:test";
import { SignalingService } from "../src/services/SignalingService.ts";
import { ClientManager } from "../src/services/ClientManager.ts";
import type { ISignalingMessage } from "../src/interfaces/ISignalingMessage.ts";
class MockWebSocket {
sentMessages: string[] = [];
closed = false;
send(data: string) {
this.sentMessages.push(data);
}
close() {
this.closed = true;
}
}
describe("SignalingService", () => {
let signalingService: SignalingService;
let clientManager: ClientManager;
let mockWs: MockWebSocket;
beforeEach(() => {
clientManager = new ClientManager();
signalingService = new SignalingService(clientManager);
mockWs = new MockWebSocket();
});
test("should handle publisher connection", () => {
const clientId = signalingService.handleConnection(mockWs, "publisher");
expect(typeof clientId).toBe("string");
expect(clientId.length).toBeGreaterThan(0);
expect(mockWs.sentMessages[0]).toBe(
JSON.stringify({
type: 'join',
data: { clientId, role: 'publisher' }
})
);
expect(clientManager.getPublisher()?.id).toBe(clientId);
});
test("should handle subscriber connection", () => {
const clientId = signalingService.handleConnection(mockWs, "subscriber");
expect(typeof clientId).toBe("string");
expect(clientId.length).toBeGreaterThan(0);
expect(mockWs.sentMessages[0]).toBe(
JSON.stringify({
type: 'join',
data: { clientId, role: 'subscriber' }
})
);
const subscribers = clientManager.getSubscribers();
expect(subscribers).toHaveLength(1);
expect(subscribers[0].id).toBe(clientId);
});
test("should handle disconnection", () => {
const clientId = signalingService.handleConnection(mockWs, "publisher");
expect(clientManager.getPublisher()).not.toBeNull();
signalingService.handleDisconnection(clientId);
expect(clientManager.getPublisher()).toBeNull();
});
test("should handle offer from publisher to subscribers", () => {
// Add publisher
const publisherId = signalingService.handleConnection(mockWs, "publisher");
// Add subscribers
const subscriber1Ws = new MockWebSocket();
const subscriber2Ws = new MockWebSocket();
signalingService.handleConnection(subscriber1Ws, "subscriber");
signalingService.handleConnection(subscriber2Ws, "subscriber");
const offerMessage: ISignalingMessage = {
type: "offer",
data: { sdp: "fake-offer-sdp", type: "offer" }
};
signalingService.handleMessage(publisherId, offerMessage);
expect(subscriber1Ws.sentMessages).toContain(
JSON.stringify({
...offerMessage,
senderId: publisherId
})
);
expect(subscriber2Ws.sentMessages).toContain(
JSON.stringify({
...offerMessage,
senderId: publisherId
})
);
});
test("should handle answer from subscriber to publisher", () => {
// Add publisher
const publisherWs = new MockWebSocket();
const publisherId = signalingService.handleConnection(publisherWs, "publisher");
// Add subscriber
const subscriberWs = new MockWebSocket();
const subscriberId = signalingService.handleConnection(subscriberWs, "subscriber");
const answerMessage: ISignalingMessage = {
type: "answer",
data: { sdp: "fake-answer-sdp", type: "answer" }
};
signalingService.handleMessage(subscriberId, answerMessage);
expect(publisherWs.sentMessages).toContain(
JSON.stringify({
...answerMessage,
senderId: subscriberId
})
);
});
test("should handle ice candidates from publisher to subscribers", () => {
const publisherId = signalingService.handleConnection(mockWs, "publisher");
const subscriberWs = new MockWebSocket();
signalingService.handleConnection(subscriberWs, "subscriber");
const iceCandidateMessage: ISignalingMessage = {
type: "ice-candidate",
data: { candidate: "fake-ice-candidate" }
};
signalingService.handleMessage(publisherId, iceCandidateMessage);
expect(subscriberWs.sentMessages).toContain(
JSON.stringify({
...iceCandidateMessage,
senderId: publisherId
})
);
});
test("should handle ice candidates from subscriber to publisher", () => {
const publisherWs = new MockWebSocket();
const publisherId = signalingService.handleConnection(publisherWs, "publisher");
const subscriberId = signalingService.handleConnection(mockWs, "subscriber");
const iceCandidateMessage: ISignalingMessage = {
type: "ice-candidate",
data: { candidate: "fake-ice-candidate" }
};
signalingService.handleMessage(subscriberId, iceCandidateMessage);
expect(publisherWs.sentMessages).toContain(
JSON.stringify({
...iceCandidateMessage,
senderId: subscriberId
})
);
});
test("should ignore messages from non-existent clients", () => {
const message: ISignalingMessage = {
type: "offer",
data: { sdp: "fake-sdp" }
};
expect(() => {
signalingService.handleMessage("non-existent-id", message);
}).not.toThrow();
});
});