fixed tests
This commit is contained in:
344
tests/sfu/SFUClientManager.test.ts
Normal file
344
tests/sfu/SFUClientManager.test.ts
Normal file
@@ -0,0 +1,344 @@
|
||||
import { test, expect, describe, beforeEach } from "bun:test";
|
||||
import { SFUClientManager } from "../../src/services/SFUClientManager.ts";
|
||||
import type { ISFUClient } from "../../src/interfaces/ISFUTypes.ts";
|
||||
|
||||
// Mock WebRTC Transport
|
||||
class MockWebRtcTransport {
|
||||
id: string;
|
||||
closed = false;
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Mock Producer
|
||||
class MockProducer {
|
||||
id: string;
|
||||
closed = false;
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Mock Consumer
|
||||
class MockConsumer {
|
||||
id: string;
|
||||
closed = false;
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Mock WebSocket
|
||||
class MockWebSocket {
|
||||
sentMessages: string[] = [];
|
||||
|
||||
send(data: string) {
|
||||
this.sentMessages.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
describe("SFUClientManager", () => {
|
||||
let clientManager: SFUClientManager;
|
||||
|
||||
beforeEach(() => {
|
||||
clientManager = new SFUClientManager();
|
||||
});
|
||||
|
||||
test("should add and retrieve clients", () => {
|
||||
const mockWs = new MockWebSocket();
|
||||
const client: ISFUClient = {
|
||||
id: "client-1",
|
||||
role: "publisher",
|
||||
ws: mockWs,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(client);
|
||||
|
||||
const retrievedClient = clientManager.getClient("client-1");
|
||||
expect(retrievedClient).toBe(client);
|
||||
});
|
||||
|
||||
test("should set and manage client transport", () => {
|
||||
const mockWs = new MockWebSocket();
|
||||
const client: ISFUClient = {
|
||||
id: "client-1",
|
||||
role: "publisher",
|
||||
ws: mockWs,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(client);
|
||||
|
||||
const transport = new MockWebRtcTransport("transport-1") as any;
|
||||
clientManager.setClientTransport("client-1", transport);
|
||||
|
||||
const retrievedClient = clientManager.getClient("client-1");
|
||||
expect(retrievedClient?.transport).toBe(transport);
|
||||
});
|
||||
|
||||
test("should manage client producer", () => {
|
||||
const mockWs = new MockWebSocket();
|
||||
const client: ISFUClient = {
|
||||
id: "publisher-1",
|
||||
role: "publisher",
|
||||
ws: mockWs,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(client);
|
||||
|
||||
const producer = new MockProducer("producer-1") as any;
|
||||
clientManager.setClientProducer("publisher-1", producer);
|
||||
|
||||
const retrievedClient = clientManager.getClient("publisher-1");
|
||||
expect(retrievedClient?.producer).toBe(producer);
|
||||
|
||||
const retrievedProducer = clientManager.getProducer("producer-1");
|
||||
expect(retrievedProducer).toBe(producer);
|
||||
});
|
||||
|
||||
test("should manage client consumers", () => {
|
||||
const mockWs = new MockWebSocket();
|
||||
const client: ISFUClient = {
|
||||
id: "subscriber-1",
|
||||
role: "subscriber",
|
||||
ws: mockWs,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(client);
|
||||
|
||||
const consumer = new MockConsumer("consumer-1") as any;
|
||||
clientManager.addClientConsumer("subscriber-1", consumer);
|
||||
|
||||
const retrievedClient = clientManager.getClient("subscriber-1");
|
||||
expect(retrievedClient?.consumers.has("consumer-1")).toBe(true);
|
||||
expect(retrievedClient?.consumers.get("consumer-1")).toBe(consumer);
|
||||
|
||||
const retrievedConsumer = clientManager.getConsumer("consumer-1");
|
||||
expect(retrievedConsumer).toBe(consumer);
|
||||
});
|
||||
|
||||
test("should remove client consumer", () => {
|
||||
const mockWs = new MockWebSocket();
|
||||
const client: ISFUClient = {
|
||||
id: "subscriber-1",
|
||||
role: "subscriber",
|
||||
ws: mockWs,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(client);
|
||||
|
||||
const consumer = new MockConsumer("consumer-1") as any;
|
||||
clientManager.addClientConsumer("subscriber-1", consumer);
|
||||
|
||||
// Verify consumer is added
|
||||
expect(clientManager.getConsumer("consumer-1")).toBe(consumer);
|
||||
|
||||
// Remove consumer
|
||||
clientManager.removeClientConsumer("subscriber-1", "consumer-1");
|
||||
|
||||
// Verify consumer is removed and closed
|
||||
expect(clientManager.getConsumer("consumer-1")).toBeUndefined();
|
||||
expect(consumer.closed).toBe(true);
|
||||
|
||||
const retrievedClient = clientManager.getClient("subscriber-1");
|
||||
expect(retrievedClient?.consumers.has("consumer-1")).toBe(false);
|
||||
});
|
||||
|
||||
test("should get publishers and subscribers separately", () => {
|
||||
const publisherWs = new MockWebSocket();
|
||||
const subscriberWs1 = new MockWebSocket();
|
||||
const subscriberWs2 = new MockWebSocket();
|
||||
|
||||
const publisher: ISFUClient = {
|
||||
id: "publisher-1",
|
||||
role: "publisher",
|
||||
ws: publisherWs,
|
||||
consumers: new Map(),
|
||||
producer: new MockProducer("producer-1") as any
|
||||
};
|
||||
|
||||
const subscriber1: ISFUClient = {
|
||||
id: "subscriber-1",
|
||||
role: "subscriber",
|
||||
ws: subscriberWs1,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
const subscriber2: ISFUClient = {
|
||||
id: "subscriber-2",
|
||||
role: "subscriber",
|
||||
ws: subscriberWs2,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(publisher);
|
||||
clientManager.addClient(subscriber1);
|
||||
clientManager.addClient(subscriber2);
|
||||
|
||||
const publishers = clientManager.getPublishers();
|
||||
const subscribers = clientManager.getSubscribers();
|
||||
|
||||
expect(publishers).toHaveLength(1);
|
||||
expect(publishers[0]).toBe(publisher);
|
||||
|
||||
expect(subscribers).toHaveLength(2);
|
||||
expect(subscribers).toContain(subscriber1);
|
||||
expect(subscribers).toContain(subscriber2);
|
||||
});
|
||||
|
||||
test("should get all producers", () => {
|
||||
const publisherWs1 = new MockWebSocket();
|
||||
const publisherWs2 = new MockWebSocket();
|
||||
|
||||
const publisher1: ISFUClient = {
|
||||
id: "publisher-1",
|
||||
role: "publisher",
|
||||
ws: publisherWs1,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
const publisher2: ISFUClient = {
|
||||
id: "publisher-2",
|
||||
role: "publisher",
|
||||
ws: publisherWs2,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(publisher1);
|
||||
clientManager.addClient(publisher2);
|
||||
|
||||
const producer1 = new MockProducer("producer-1") as any;
|
||||
const producer2 = new MockProducer("producer-2") as any;
|
||||
|
||||
clientManager.setClientProducer("publisher-1", producer1);
|
||||
clientManager.setClientProducer("publisher-2", producer2);
|
||||
|
||||
const allProducers = clientManager.getAllProducers();
|
||||
expect(allProducers).toHaveLength(2);
|
||||
expect(allProducers).toContain(producer1);
|
||||
expect(allProducers).toContain(producer2);
|
||||
});
|
||||
|
||||
test("should remove client and cleanup resources", () => {
|
||||
const mockWs = new MockWebSocket();
|
||||
const client: ISFUClient = {
|
||||
id: "client-1",
|
||||
role: "publisher",
|
||||
ws: mockWs,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(client);
|
||||
|
||||
// Add transport, producer, and consumer
|
||||
const transport = new MockWebRtcTransport("transport-1") as any;
|
||||
const producer = new MockProducer("producer-1") as any;
|
||||
const consumer = new MockConsumer("consumer-1") as any;
|
||||
|
||||
clientManager.setClientTransport("client-1", transport);
|
||||
clientManager.setClientProducer("client-1", producer);
|
||||
clientManager.addClientConsumer("client-1", consumer);
|
||||
|
||||
// Remove client
|
||||
clientManager.removeClient("client-1");
|
||||
|
||||
// Verify client is removed
|
||||
expect(clientManager.getClient("client-1")).toBeUndefined();
|
||||
|
||||
// Verify resources are cleaned up
|
||||
expect(transport.closed).toBe(true);
|
||||
expect(producer.closed).toBe(true);
|
||||
expect(consumer.closed).toBe(true);
|
||||
|
||||
// Verify global maps are cleaned up
|
||||
expect(clientManager.getProducer("producer-1")).toBeUndefined();
|
||||
expect(clientManager.getConsumer("consumer-1")).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should provide correct statistics", () => {
|
||||
const publisherWs = new MockWebSocket();
|
||||
const subscriberWs1 = new MockWebSocket();
|
||||
const subscriberWs2 = new MockWebSocket();
|
||||
|
||||
const publisher: ISFUClient = {
|
||||
id: "publisher-1",
|
||||
role: "publisher",
|
||||
ws: publisherWs,
|
||||
consumers: new Map(),
|
||||
producer: new MockProducer("producer-1") as any
|
||||
};
|
||||
|
||||
const subscriber1: ISFUClient = {
|
||||
id: "subscriber-1",
|
||||
role: "subscriber",
|
||||
ws: subscriberWs1,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
const subscriber2: ISFUClient = {
|
||||
id: "subscriber-2",
|
||||
role: "subscriber",
|
||||
ws: subscriberWs2,
|
||||
consumers: new Map()
|
||||
};
|
||||
|
||||
clientManager.addClient(publisher);
|
||||
clientManager.addClient(subscriber1);
|
||||
clientManager.addClient(subscriber2);
|
||||
|
||||
const producer = new MockProducer("producer-1") as any;
|
||||
const consumer1 = new MockConsumer("consumer-1") as any;
|
||||
const consumer2 = new MockConsumer("consumer-2") as any;
|
||||
|
||||
clientManager.setClientProducer("publisher-1", producer);
|
||||
clientManager.addClientConsumer("subscriber-1", consumer1);
|
||||
clientManager.addClientConsumer("subscriber-2", consumer2);
|
||||
|
||||
const stats = clientManager.getStats();
|
||||
|
||||
expect(stats.clients).toBe(3);
|
||||
expect(stats.publishers).toBe(1);
|
||||
expect(stats.subscribers).toBe(2);
|
||||
expect(stats.producers).toBe(1);
|
||||
expect(stats.consumers).toBe(2);
|
||||
});
|
||||
|
||||
test("should handle removing non-existent client gracefully", () => {
|
||||
expect(() => {
|
||||
clientManager.removeClient("non-existent");
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
test("should handle operations on non-existent clients gracefully", () => {
|
||||
const transport = new MockWebRtcTransport("transport-1") as any;
|
||||
const producer = new MockProducer("producer-1") as any;
|
||||
const consumer = new MockConsumer("consumer-1") as any;
|
||||
|
||||
expect(() => {
|
||||
clientManager.setClientTransport("non-existent", transport);
|
||||
clientManager.setClientProducer("non-existent", producer);
|
||||
clientManager.addClientConsumer("non-existent", consumer);
|
||||
clientManager.removeClientConsumer("non-existent", "consumer-1");
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user