204 lines
5.9 KiB
TypeScript
204 lines
5.9 KiB
TypeScript
import express, { Request, Response } from 'express';
|
|
import http from 'http';
|
|
import { StringValue } from 'ms';
|
|
import { MeetRoomHelper } from '../../src/helpers';
|
|
import { MeetRoom } from '../../src/typings/ce';
|
|
import { expectValidStartRecordingResponse } from './assertion-helpers';
|
|
import {
|
|
createRoom,
|
|
generateParticipantTokenCookie,
|
|
joinFakeParticipant,
|
|
sleep,
|
|
startRecording,
|
|
stopRecording
|
|
} from './request-helpers';
|
|
|
|
let mockWebhookServer: http.Server;
|
|
|
|
export interface RoomData {
|
|
room: MeetRoom;
|
|
moderatorSecret: string;
|
|
moderatorCookie: string;
|
|
publisherSecret: string;
|
|
publisherCookie: string;
|
|
recordingId?: string;
|
|
}
|
|
|
|
export interface TestContext {
|
|
rooms: RoomData[];
|
|
getRoomByIndex(index: number): RoomData | undefined;
|
|
getLastRoom(): RoomData | undefined;
|
|
}
|
|
|
|
/**
|
|
* Creates a single room with optional participant.
|
|
*
|
|
* @param withParticipant Whether to join a fake participant in the room.
|
|
* @returns Room data including secrets and cookies.
|
|
*/
|
|
export const setupSingleRoom = async (withParticipant = false): Promise<RoomData> => {
|
|
const room = await createRoom({
|
|
roomIdPrefix: 'TEST_ROOM'
|
|
});
|
|
|
|
// Extract the room secrets and generate participant tokens, saved as cookies
|
|
const { moderatorSecret, publisherSecret } = MeetRoomHelper.extractSecretsFromRoom(room);
|
|
const [moderatorCookie, publisherCookie] = await Promise.all([
|
|
generateParticipantTokenCookie(room.roomId, 'MODERATOR', moderatorSecret),
|
|
generateParticipantTokenCookie(room.roomId, 'PUBLISHER', publisherSecret),
|
|
// Join participant if needed
|
|
withParticipant ? joinFakeParticipant(room.roomId, 'TEST_PARTICIPANT') : Promise.resolve()
|
|
]);
|
|
|
|
return {
|
|
room,
|
|
moderatorSecret,
|
|
moderatorCookie,
|
|
publisherSecret,
|
|
publisherCookie
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Creates a test context with multiple rooms and optional participants.
|
|
*
|
|
* @param numRooms Number of rooms to create.
|
|
* @param withParticipants Whether to join fake participants in the rooms.
|
|
* @returns Test context with created rooms and their data.
|
|
*/
|
|
export const setupMultiRoomTestContext = async (numRooms: number, withParticipants: boolean): Promise<TestContext> => {
|
|
const rooms: RoomData[] = [];
|
|
|
|
for (let i = 0; i < numRooms; i++) {
|
|
const roomData = await setupSingleRoom(withParticipants);
|
|
rooms.push(roomData);
|
|
}
|
|
|
|
return {
|
|
rooms,
|
|
getRoomByIndex: (index: number) => {
|
|
if (index < 0 || index >= rooms.length) {
|
|
return undefined;
|
|
}
|
|
|
|
return rooms[index];
|
|
},
|
|
|
|
getLastRoom: () => {
|
|
if (rooms.length === 0) {
|
|
return undefined;
|
|
}
|
|
|
|
return rooms[rooms.length - 1];
|
|
}
|
|
};
|
|
};
|
|
|
|
export const setupSingleRoomWithRecording = async (
|
|
stopRecordingCond = false,
|
|
stopDelay?: StringValue
|
|
): Promise<RoomData> => {
|
|
const roomData = await setupSingleRoom(true);
|
|
const response = await startRecording(roomData.room.roomId, roomData.moderatorCookie);
|
|
expectValidStartRecordingResponse(response, roomData.room.roomId);
|
|
roomData.recordingId = response.body.recordingId;
|
|
|
|
// Wait for the configured delay before stopping the recording
|
|
if (stopRecordingCond && stopDelay) {
|
|
await sleep(stopDelay);
|
|
}
|
|
|
|
if (stopRecordingCond) {
|
|
await stopRecording(roomData.recordingId!, roomData.moderatorCookie);
|
|
}
|
|
|
|
return roomData;
|
|
};
|
|
|
|
/**
|
|
* Quickly creates multiple recordings
|
|
* Allows customizing how many recordings to start and how many to stop after a delay.
|
|
*
|
|
* @param numRooms Number of rooms to use.
|
|
* @param numStarts Number of recordings to start.
|
|
* @param numStops Number of recordings to stop after the delay.
|
|
* @param stopDelay Delay before stopping recordings.
|
|
* @returns Test context with created recordings (some stopped, some still running).
|
|
*/
|
|
export const setupMultiRecordingsTestContext = async (
|
|
numRooms: number,
|
|
numStarts: number,
|
|
numStops: number,
|
|
stopDelay?: StringValue
|
|
): Promise<TestContext> => {
|
|
// Setup rooms with participants
|
|
const testContext = await setupMultiRoomTestContext(numRooms, true);
|
|
|
|
// Start the specified number of recordings in parallel
|
|
const startPromises = Array.from({ length: numStarts }).map(async (_, i) => {
|
|
const roomIndex = i % numRooms;
|
|
const roomData = testContext.getRoomByIndex(roomIndex);
|
|
|
|
if (!roomData) {
|
|
throw new Error(`Room at index ${roomIndex} not found`);
|
|
}
|
|
|
|
// Send start recording request
|
|
const response = await startRecording(roomData.room.roomId, roomData.moderatorCookie);
|
|
expectValidStartRecordingResponse(response, roomData.room.roomId);
|
|
|
|
// Store the recordingId in context
|
|
roomData.recordingId = response.body.recordingId;
|
|
return roomData;
|
|
});
|
|
const startedRooms = await Promise.all(startPromises);
|
|
|
|
// Wait for the configured delay before stopping recordings
|
|
if (stopDelay) {
|
|
await sleep(stopDelay);
|
|
}
|
|
|
|
// Stop recordings for the first numStops rooms
|
|
const stopPromises = startedRooms.slice(0, numStops).map(async (roomData) => {
|
|
if (roomData.recordingId) {
|
|
await stopRecording(roomData.recordingId, roomData.moderatorCookie);
|
|
console.log(`Recording stopped for room ${roomData.room.roomId}`);
|
|
return roomData.recordingId;
|
|
}
|
|
|
|
return null;
|
|
});
|
|
const stoppedIds = (await Promise.all(stopPromises)).filter((id): id is string => Boolean(id));
|
|
console.log(`Stopped ${stoppedIds.length} recordings after ${stopDelay}ms:`, stoppedIds);
|
|
|
|
return testContext;
|
|
};
|
|
|
|
export const startWebhookServer = async (
|
|
port: number,
|
|
webhookReceivedCallback: (event: Request) => void
|
|
): Promise<void> => {
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
app.post('/webhook', (req: Request, res: Response) => {
|
|
webhookReceivedCallback(req);
|
|
res.status(200).send({ success: true });
|
|
});
|
|
|
|
return new Promise<void>((resolve) => {
|
|
mockWebhookServer = app.listen(port, () => {
|
|
console.log(`Webhook server listening on port ${port}`);
|
|
resolve();
|
|
});
|
|
});
|
|
};
|
|
|
|
export const stopWebhookServer = async (): Promise<void> => {
|
|
if (mockWebhookServer) {
|
|
await new Promise<void>((resolve) => {
|
|
mockWebhookServer.close(() => resolve());
|
|
});
|
|
}
|
|
};
|