fixed tests
This commit is contained in:
205
tests/frontend/WebSocketClient.test.ts
Normal file
205
tests/frontend/WebSocketClient.test.ts
Normal file
@@ -0,0 +1,205 @@
|
||||
import { test, expect, describe, beforeEach, afterEach } from "bun:test";
|
||||
|
||||
// Mock WebSocket for testing
|
||||
class MockWebSocket {
|
||||
public readyState = WebSocket.CONNECTING;
|
||||
public url: string;
|
||||
public sentMessages: string[] = [];
|
||||
|
||||
public onopen: (() => void) | null = null;
|
||||
public onclose: (() => void) | null = null;
|
||||
public onmessage: ((event: { data: string }) => void) | null = null;
|
||||
public onerror: ((error: any) => void) | null = null;
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url;
|
||||
// Simulate successful connection
|
||||
setTimeout(() => {
|
||||
this.readyState = WebSocket.OPEN;
|
||||
if (this.onopen) {
|
||||
this.onopen();
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
send(data: string) {
|
||||
if (this.readyState === WebSocket.OPEN) {
|
||||
this.sentMessages.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this.readyState = WebSocket.CLOSED;
|
||||
if (this.onclose) {
|
||||
this.onclose();
|
||||
}
|
||||
}
|
||||
|
||||
simulateMessage(data: any) {
|
||||
if (this.onmessage) {
|
||||
this.onmessage({ data: JSON.stringify(data) });
|
||||
}
|
||||
}
|
||||
|
||||
simulateError(error: any) {
|
||||
if (this.onerror) {
|
||||
this.onerror(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mock the global WebSocket
|
||||
(global as any).WebSocket = MockWebSocket;
|
||||
|
||||
// Import after mocking
|
||||
import { WebSocketClient } from "../../public/js/services/WebSocketClient.ts";
|
||||
import type { ISignalingMessage } from "../../public/js/interfaces/IWebRTCClient.ts";
|
||||
|
||||
describe("WebSocketClient", () => {
|
||||
let wsClient: WebSocketClient;
|
||||
let mockWs: MockWebSocket;
|
||||
|
||||
beforeEach(() => {
|
||||
wsClient = new WebSocketClient('publisher');
|
||||
// Access the internal WebSocket instance for testing
|
||||
});
|
||||
|
||||
test("should connect as publisher", async () => {
|
||||
const connectPromise = wsClient.connect();
|
||||
|
||||
// Wait for connection
|
||||
await connectPromise;
|
||||
|
||||
expect(wsClient.isConnected()).toBe(true);
|
||||
});
|
||||
|
||||
test("should connect as subscriber", async () => {
|
||||
const subscriberClient = new WebSocketClient('subscriber');
|
||||
await subscriberClient.connect();
|
||||
|
||||
expect(subscriberClient.isConnected()).toBe(true);
|
||||
});
|
||||
|
||||
test("should handle connection error", async () => {
|
||||
const errorClient = new WebSocketClient('publisher');
|
||||
|
||||
// Start connection but simulate error before it completes
|
||||
const connectPromise = errorClient.connect();
|
||||
|
||||
// Simulate error during connection
|
||||
setTimeout(() => {
|
||||
// Access the internal WebSocket and trigger error
|
||||
const ws = (errorClient as any).ws;
|
||||
if (ws && ws.onerror) {
|
||||
ws.onerror(new Error('Connection failed'));
|
||||
}
|
||||
}, 5);
|
||||
|
||||
await expect(connectPromise).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("should send messages when connected", async () => {
|
||||
await wsClient.connect();
|
||||
|
||||
const message: ISignalingMessage = {
|
||||
type: 'offer',
|
||||
data: { sdp: 'test-sdp' }
|
||||
};
|
||||
|
||||
wsClient.sendMessage(message);
|
||||
|
||||
const ws = (wsClient as any).ws as MockWebSocket;
|
||||
expect(ws.sentMessages).toHaveLength(1);
|
||||
expect(JSON.parse(ws.sentMessages[0])).toEqual(message);
|
||||
});
|
||||
|
||||
test("should not send messages when disconnected", () => {
|
||||
const message: ISignalingMessage = {
|
||||
type: 'offer',
|
||||
data: { sdp: 'test-sdp' }
|
||||
};
|
||||
|
||||
wsClient.sendMessage(message);
|
||||
|
||||
// Should not have sent anything since not connected
|
||||
const ws = (wsClient as any).ws;
|
||||
expect(ws).toBeNull();
|
||||
});
|
||||
|
||||
test("should handle incoming messages", async () => {
|
||||
await wsClient.connect();
|
||||
|
||||
const receivedMessages: ISignalingMessage[] = [];
|
||||
wsClient.onMessage('join', (message) => {
|
||||
receivedMessages.push(message);
|
||||
});
|
||||
|
||||
const testMessage: ISignalingMessage = {
|
||||
type: 'join',
|
||||
data: { clientId: 'test-id', role: 'publisher' }
|
||||
};
|
||||
|
||||
const ws = (wsClient as any).ws as MockWebSocket;
|
||||
ws.simulateMessage(testMessage);
|
||||
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual(testMessage);
|
||||
});
|
||||
|
||||
test("should handle multiple message types", async () => {
|
||||
await wsClient.connect();
|
||||
|
||||
const joinMessages: ISignalingMessage[] = [];
|
||||
const offerMessages: ISignalingMessage[] = [];
|
||||
|
||||
wsClient.onMessage('join', (message) => joinMessages.push(message));
|
||||
wsClient.onMessage('offer', (message) => offerMessages.push(message));
|
||||
|
||||
const ws = (wsClient as any).ws as MockWebSocket;
|
||||
|
||||
ws.simulateMessage({ type: 'join', data: { clientId: 'test' } });
|
||||
ws.simulateMessage({ type: 'offer', data: { sdp: 'test-sdp' } });
|
||||
ws.simulateMessage({ type: 'join', data: { clientId: 'test2' } });
|
||||
|
||||
expect(joinMessages).toHaveLength(2);
|
||||
expect(offerMessages).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("should disconnect properly", async () => {
|
||||
await wsClient.connect();
|
||||
expect(wsClient.isConnected()).toBe(true);
|
||||
|
||||
wsClient.disconnect();
|
||||
expect(wsClient.isConnected()).toBe(false);
|
||||
});
|
||||
|
||||
test("should handle malformed JSON messages gracefully", async () => {
|
||||
await wsClient.connect();
|
||||
|
||||
// Mock console.error to verify error logging
|
||||
const originalConsoleError = console.error;
|
||||
const errorLogs: any[] = [];
|
||||
console.error = (...args: any[]) => errorLogs.push(args);
|
||||
|
||||
const ws = (wsClient as any).ws as MockWebSocket;
|
||||
if (ws.onmessage) {
|
||||
ws.onmessage({ data: 'invalid-json' });
|
||||
}
|
||||
|
||||
expect(errorLogs.length).toBeGreaterThan(0);
|
||||
expect(errorLogs[0][0]).toBe('Failed to parse WebSocket message:');
|
||||
|
||||
// Restore console.error
|
||||
console.error = originalConsoleError;
|
||||
});
|
||||
|
||||
test("should handle close event", async () => {
|
||||
await wsClient.connect();
|
||||
expect(wsClient.isConnected()).toBe(true);
|
||||
|
||||
const ws = (wsClient as any).ws as MockWebSocket;
|
||||
ws.close();
|
||||
|
||||
expect(wsClient.isConnected()).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user