fixed tests

This commit is contained in:
2025-09-05 00:36:54 -04:00
commit a536668a0b
48 changed files with 8187 additions and 0 deletions

233
tests/integration.test.ts Normal file
View File

@@ -0,0 +1,233 @@
import { test, expect, describe, beforeEach, afterEach } from "bun:test";
import { ClientManager } from "../src/services/ClientManager.ts";
import { SignalingService } from "../src/services/SignalingService.ts";
interface MockWebSocketMessage {
type: string;
data?: any;
senderId?: string;
}
class MockWebSocket {
private messageHandler: ((event: { data: string }) => void) | null = null;
private openHandler: (() => void) | null = null;
private closeHandler: (() => void) | null = null;
public sentMessages: string[] = [];
public readyState = WebSocket.OPEN;
public url: string;
constructor(url: string) {
this.url = url;
// Simulate connection opening
setTimeout(() => {
if (this.openHandler) {
this.openHandler();
}
}, 10);
}
send(data: string) {
this.sentMessages.push(data);
}
close() {
this.readyState = WebSocket.CLOSED;
if (this.closeHandler) {
this.closeHandler();
}
}
set onmessage(handler: (event: { data: string }) => void) {
this.messageHandler = handler;
}
set onopen(handler: () => void) {
this.openHandler = handler;
}
set onclose(handler: () => void) {
this.closeHandler = handler;
}
set onerror(handler: (error: any) => void) {
// Mock implementation
}
simulateMessage(message: MockWebSocketMessage) {
if (this.messageHandler) {
this.messageHandler({ data: JSON.stringify(message) });
}
}
getLastMessage(): MockWebSocketMessage | null {
if (this.sentMessages.length === 0) return null;
return JSON.parse(this.sentMessages[this.sentMessages.length - 1]);
}
getAllMessages(): MockWebSocketMessage[] {
return this.sentMessages.map(msg => JSON.parse(msg));
}
}
describe("WebSocket Signaling Integration", () => {
let clientManager: ClientManager;
let signalingService: SignalingService;
beforeEach(() => {
clientManager = new ClientManager();
signalingService = new SignalingService(clientManager);
});
test("should handle complete publisher-subscriber flow", () => {
// Setup subscribers first
const subscriber1Ws = new MockWebSocket("ws://test?role=subscriber");
const subscriber1Id = signalingService.handleConnection(subscriber1Ws, "subscriber");
const subscriber2Ws = new MockWebSocket("ws://test?role=subscriber");
const subscriber2Id = signalingService.handleConnection(subscriber2Ws, "subscriber");
// Setup publisher (this should notify existing subscribers)
const publisherWs = new MockWebSocket("ws://test?role=publisher");
const publisherId = signalingService.handleConnection(publisherWs, "publisher");
// Verify initial connections
expect(publisherWs.getLastMessage()).toEqual({
type: 'join',
data: { clientId: publisherId, role: 'publisher' }
});
// Verify subscribers get notified about publisher joining
const sub1Messages = subscriber1Ws.getAllMessages();
const sub2Messages = subscriber2Ws.getAllMessages();
expect(sub1Messages).toHaveLength(2); // join + publisher-joined
expect(sub1Messages.some(msg => msg.type === 'publisher-joined')).toBe(true);
expect(sub2Messages).toHaveLength(2); // join + publisher-joined
expect(sub2Messages.some(msg => msg.type === 'publisher-joined')).toBe(true);
// Test offer flow
const offerMessage = {
type: "offer" as const,
data: { sdp: "fake-offer-sdp", type: "offer" }
};
signalingService.handleMessage(publisherId, offerMessage);
// Verify subscribers received the offer
const sub1LastMessage = subscriber1Ws.getLastMessage();
const sub2LastMessage = subscriber2Ws.getLastMessage();
expect(sub1LastMessage).toEqual({
...offerMessage,
senderId: publisherId
});
expect(sub2LastMessage).toEqual({
...offerMessage,
senderId: publisherId
});
// Test answer flow
const answerMessage = {
type: "answer" as const,
data: { sdp: "fake-answer-sdp", type: "answer" }
};
signalingService.handleMessage(subscriber1Id, answerMessage);
// Verify publisher received the answer
const publisherLastMessage = publisherWs.getLastMessage();
expect(publisherLastMessage).toEqual({
...answerMessage,
senderId: subscriber1Id
});
// Test ICE candidate exchange
const iceCandidateMessage = {
type: "ice-candidate" as const,
data: { candidate: "fake-ice-candidate" }
};
// Publisher to subscribers
signalingService.handleMessage(publisherId, iceCandidateMessage);
expect(subscriber1Ws.getLastMessage()).toEqual({
...iceCandidateMessage,
senderId: publisherId
});
expect(subscriber2Ws.getLastMessage()).toEqual({
...iceCandidateMessage,
senderId: publisherId
});
// Subscriber to publisher
signalingService.handleMessage(subscriber1Id, iceCandidateMessage);
expect(publisherWs.getLastMessage()).toEqual({
...iceCandidateMessage,
senderId: subscriber1Id
});
});
test("should handle publisher disconnect gracefully", () => {
// Setup
const publisherWs = new MockWebSocket("ws://test?role=publisher");
const publisherId = signalingService.handleConnection(publisherWs, "publisher");
const subscriberWs = new MockWebSocket("ws://test?role=subscriber");
signalingService.handleConnection(subscriberWs, "subscriber");
// Disconnect publisher
signalingService.handleDisconnection(publisherId);
// Verify subscriber gets publisher-left notification
const subscriberMessages = subscriberWs.getAllMessages();
expect(subscriberMessages).toHaveLength(2); // join + publisher-left
expect(subscriberMessages.some(msg => msg.type === 'publisher-left')).toBe(true);
// Verify publisher is removed
expect(clientManager.getPublisher()).toBeNull();
});
test("should handle subscriber disconnect gracefully", () => {
const publisherWs = new MockWebSocket("ws://test?role=publisher");
signalingService.handleConnection(publisherWs, "publisher");
const subscriberWs = new MockWebSocket("ws://test?role=subscriber");
const subscriberId = signalingService.handleConnection(subscriberWs, "subscriber");
// Verify subscriber was added
expect(clientManager.getSubscribers()).toHaveLength(1);
// Disconnect subscriber
signalingService.handleDisconnection(subscriberId);
// Verify subscriber was removed
expect(clientManager.getSubscribers()).toHaveLength(0);
expect(clientManager.getClient(subscriberId)).toBeUndefined();
});
test("should handle multiple subscribers connecting and disconnecting", () => {
const publisherWs = new MockWebSocket("ws://test?role=publisher");
signalingService.handleConnection(publisherWs, "publisher");
// Add 3 subscribers
const subscribers = [];
for (let i = 0; i < 3; i++) {
const ws = new MockWebSocket(`ws://test?role=subscriber&id=${i}`);
const id = signalingService.handleConnection(ws, "subscriber");
subscribers.push({ ws, id });
}
expect(clientManager.getSubscribers()).toHaveLength(3);
// Disconnect middle subscriber
signalingService.handleDisconnection(subscribers[1].id);
expect(clientManager.getSubscribers()).toHaveLength(2);
// Verify remaining subscribers are still connected
expect(clientManager.getClient(subscribers[0].id)).toBeDefined();
expect(clientManager.getClient(subscribers[2].id)).toBeDefined();
expect(clientManager.getClient(subscribers[1].id)).toBeUndefined();
});
});