backend: update recording handling to include roomName and adjust related logic
This commit is contained in:
parent
bdc3f599f0
commit
42db1b7bb6
@ -141,7 +141,6 @@ export const deleteRecording = async (req: Request, res: Response) => {
|
||||
logger.info(`Deleting recording '${recordingId}'`);
|
||||
|
||||
try {
|
||||
// TODO: Check role to determine if the request is from an admin or a participant
|
||||
await recordingService.deleteRecording(recordingId);
|
||||
return res.status(204).send();
|
||||
} catch (error) {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { MeetRecordingInfo, MeetRecordingStatus } from '@typings-ce';
|
||||
import { EgressInfo, EgressStatus, SendDataOptions } from 'livekit-server-sdk';
|
||||
import { RecordingHelper } from './recording.helper.js';
|
||||
import { SendDataOptions } from 'livekit-server-sdk';
|
||||
|
||||
const enum OpenViduComponentsDataTopic {
|
||||
CHAT = 'chat',
|
||||
|
||||
@ -2,13 +2,15 @@ import { EgressStatus } from '@livekit/protocol';
|
||||
import { MeetRecordingInfo, MeetRecordingStatus } from '@typings-ce';
|
||||
import { EgressInfo } from 'livekit-server-sdk';
|
||||
import { uid as secureUid } from 'uid/secure';
|
||||
import { container } from '../config/index.js';
|
||||
import { RoomService } from '../services/index.js';
|
||||
|
||||
export class RecordingHelper {
|
||||
private constructor() {
|
||||
// Prevent instantiation of this utility class
|
||||
}
|
||||
|
||||
static toRecordingInfo(egressInfo: EgressInfo): MeetRecordingInfo {
|
||||
static async toRecordingInfo(egressInfo: EgressInfo): Promise<MeetRecordingInfo> {
|
||||
const status = RecordingHelper.extractOpenViduStatus(egressInfo.status);
|
||||
const size = RecordingHelper.extractSize(egressInfo);
|
||||
// const outputMode = RecordingHelper.extractOutputMode(egressInfo);
|
||||
@ -17,10 +19,15 @@ export class RecordingHelper {
|
||||
const endDateMs = RecordingHelper.extractEndDate(egressInfo);
|
||||
const filename = RecordingHelper.extractFilename(egressInfo);
|
||||
const uid = RecordingHelper.extractUidFromFilename(filename);
|
||||
const { egressId, roomName, errorCode, error, details } = egressInfo;
|
||||
const { egressId, roomName: roomId, errorCode, error, details } = egressInfo;
|
||||
|
||||
const roomService = container.get(RoomService);
|
||||
const { roomName } = await roomService.getMeetRoom(roomId);
|
||||
|
||||
return {
|
||||
recordingId: `${roomName}--${egressId}--${uid}`,
|
||||
roomId: roomName,
|
||||
recordingId: `${roomId}--${egressId}--${uid}`,
|
||||
roomId,
|
||||
roomName,
|
||||
// outputMode,
|
||||
status,
|
||||
filename,
|
||||
@ -186,7 +193,6 @@ export class RecordingHelper {
|
||||
return size !== 0 ? size : undefined;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the secrets for public and private access to recordings.
|
||||
* @returns An object containing public and private access secrets.
|
||||
|
||||
@ -234,7 +234,7 @@ export class LivekitWebhookService {
|
||||
this.logger.debug(`Processing recording_${webhookAction} webhook for egress: ${egressInfo.egressId}.`);
|
||||
|
||||
try {
|
||||
const recordingInfo: MeetRecordingInfo = RecordingHelper.toRecordingInfo(egressInfo);
|
||||
const recordingInfo: MeetRecordingInfo = await RecordingHelper.toRecordingInfo(egressInfo);
|
||||
const { roomId, recordingId, status } = recordingInfo;
|
||||
|
||||
this.logger.debug(`Recording '${recordingId}' in room '${roomId}' status: '${status}'`);
|
||||
|
||||
@ -77,6 +77,7 @@ export class RecordingService {
|
||||
await this.frontendEventService.sendRecordingSignalToOpenViduComponents(roomId, {
|
||||
recordingId: '',
|
||||
roomId,
|
||||
roomName: roomId,
|
||||
status: MeetRecordingStatus.STARTING
|
||||
});
|
||||
|
||||
@ -121,7 +122,7 @@ export class RecordingService {
|
||||
throw errorRecordingStartTimeout(roomId);
|
||||
}
|
||||
|
||||
const recordingInfo = RecordingHelper.toRecordingInfo(egressInfo);
|
||||
const recordingInfo = await RecordingHelper.toRecordingInfo(egressInfo);
|
||||
recordingId = recordingInfo.recordingId;
|
||||
|
||||
// If the recording is already active, we can resolve the promise immediately.
|
||||
@ -199,7 +200,7 @@ export class RecordingService {
|
||||
const egressInfo = await this.livekitService.stopEgress(egressId);
|
||||
|
||||
this.logger.info(`Recording stopped successfully for room '${roomId}'.`);
|
||||
return RecordingHelper.toRecordingInfo(egressInfo);
|
||||
return await RecordingHelper.toRecordingInfo(egressInfo);
|
||||
} catch (error) {
|
||||
this.logger.error(`Error stopping recording '${recordingId}': ${error}`);
|
||||
throw error;
|
||||
@ -585,6 +586,7 @@ export class RecordingService {
|
||||
const recordingInfo: MeetRecordingInfo = {
|
||||
recordingId,
|
||||
roomId,
|
||||
roomName: roomId,
|
||||
status: MeetRecordingStatus.FAILED,
|
||||
error: `No egress service was able to register a request. Check your CPU usage or if there's any Media Node with enough CPU. Remember that by default, composite recording uses 4 CPUs for each room.`
|
||||
};
|
||||
|
||||
@ -154,13 +154,16 @@ export const expectValidRecording = (
|
||||
recording: MeetRecordingInfo,
|
||||
recordingId: string,
|
||||
roomId: string,
|
||||
roomName: string,
|
||||
status: MeetRecordingStatus
|
||||
) => {
|
||||
expect(recording).toBeDefined();
|
||||
expect(recording.recordingId).toBeDefined();
|
||||
expect(recording.roomId).toBeDefined();
|
||||
expect(recording.roomName).toBeDefined();
|
||||
expect(recording.recordingId).toBe(recordingId);
|
||||
expect(recording.roomId).toBe(roomId);
|
||||
expect(recording.roomName).toBe(roomName);
|
||||
expect(recording.startDate).toBeDefined();
|
||||
expect(recording.status).toBeDefined();
|
||||
expect(recording.status).toBe(status);
|
||||
@ -329,7 +332,7 @@ export const expectSuccessRecordingMediaResponse = (
|
||||
}
|
||||
};
|
||||
|
||||
export const expectValidStartRecordingResponse = (response: any, roomId: string) => {
|
||||
export const expectValidStartRecordingResponse = (response: any, roomId: string, roomName: string) => {
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body).toHaveProperty('recordingId');
|
||||
|
||||
@ -340,6 +343,7 @@ export const expectValidStartRecordingResponse = (response: any, roomId: string)
|
||||
|
||||
expect(recordingId).toContain(roomId);
|
||||
expect(response.body).toHaveProperty('roomId', roomId);
|
||||
expect(response.body).toHaveProperty('roomName', roomName);
|
||||
expect(response.body).toHaveProperty('startDate');
|
||||
expect(response.body).toHaveProperty('status', 'ACTIVE');
|
||||
expect(response.body).toHaveProperty('filename');
|
||||
@ -348,12 +352,18 @@ export const expectValidStartRecordingResponse = (response: any, roomId: string)
|
||||
expect(response.body).not.toHaveProperty('size');
|
||||
};
|
||||
|
||||
export const expectValidStopRecordingResponse = (response: any, recordingId: string, roomId: string) => {
|
||||
export const expectValidStopRecordingResponse = (
|
||||
response: any,
|
||||
recordingId: string,
|
||||
roomId: string,
|
||||
roomName: string
|
||||
) => {
|
||||
expect(response.status).toBe(202);
|
||||
expect(response.body).toBeDefined();
|
||||
expect(response.body).toHaveProperty('recordingId', recordingId);
|
||||
expect([MeetRecordingStatus.COMPLETE, MeetRecordingStatus.ENDING]).toContain(response.body.status);
|
||||
expect(response.body).toHaveProperty('roomId', roomId);
|
||||
expect(response.body).toHaveProperty('roomName', roomName);
|
||||
expect(response.body).toHaveProperty('filename');
|
||||
expect(response.body).toHaveProperty('startDate');
|
||||
expect(response.body).toHaveProperty('duration', expect.any(Number));
|
||||
@ -365,6 +375,7 @@ export const expectValidGetRecordingResponse = (
|
||||
response: any,
|
||||
recordingId: string,
|
||||
roomId: string,
|
||||
roomName: string,
|
||||
status?: MeetRecordingStatus,
|
||||
maxSecDuration?: number
|
||||
) => {
|
||||
@ -372,7 +383,7 @@ export const expectValidGetRecordingResponse = (
|
||||
expect(response.body).toBeDefined();
|
||||
const body = response.body;
|
||||
|
||||
expect(body).toMatchObject({ recordingId, roomId });
|
||||
expect(body).toMatchObject({ recordingId, roomId, roomName });
|
||||
|
||||
const isRecFinished =
|
||||
status &&
|
||||
@ -384,6 +395,7 @@ export const expectValidGetRecordingResponse = (
|
||||
expect.objectContaining({
|
||||
recordingId: expect.stringMatching(new RegExp(`^${recordingId}$`)),
|
||||
roomId: expect.stringMatching(new RegExp(`^${roomId}$`)),
|
||||
roomName: expect.stringMatching(new RegExp(`^${roomName}$`)),
|
||||
...(isRecFinished ? { status: expect.any(String) } : {}),
|
||||
...(isRecFinished ? { duration: expect.any(Number) } : {}),
|
||||
...(isRecFinished ? { startDate: expect.any(Number) } : {}),
|
||||
|
||||
@ -110,7 +110,7 @@ export const setupSingleRoomWithRecording = async (
|
||||
): Promise<RoomData> => {
|
||||
const roomData = await setupSingleRoom(true, 'TEST_ROOM');
|
||||
const response = await startRecording(roomData.room.roomId, roomData.moderatorCookie);
|
||||
expectValidStartRecordingResponse(response, roomData.room.roomId);
|
||||
expectValidStartRecordingResponse(response, roomData.room.roomId, roomData.room.roomName);
|
||||
roomData.recordingId = response.body.recordingId;
|
||||
|
||||
// Wait for the configured delay before stopping the recording
|
||||
@ -155,7 +155,7 @@ export const setupMultiRecordingsTestContext = async (
|
||||
|
||||
// Send start recording request
|
||||
const response = await startRecording(roomData.room.roomId, roomData.moderatorCookie);
|
||||
expectValidStartRecordingResponse(response, roomData.room.roomId);
|
||||
expectValidStartRecordingResponse(response, roomData.room.roomId, roomData.room.roomName);
|
||||
|
||||
// Store the recordingId in context
|
||||
roomData.recordingId = response.body.recordingId;
|
||||
|
||||
@ -191,7 +191,7 @@ describe('Recording API Tests', () => {
|
||||
expect(roomMetadata!.publisherRoomUrl).toContain(room.roomId);
|
||||
|
||||
const response = await startRecording(room.roomId, moderatorCookie);
|
||||
expectValidStartRecordingResponse(response, room.roomId);
|
||||
expectValidStartRecordingResponse(response, room.roomId, room.roomName);
|
||||
const secondRecordingId = response.body.recordingId;
|
||||
|
||||
await stopRecording(secondRecordingId, moderatorCookie);
|
||||
@ -207,6 +207,7 @@ describe('Recording API Tests', () => {
|
||||
// secondRecordingResponse,
|
||||
// secondRecordingId,
|
||||
// room.roomId,
|
||||
// room.roomName,
|
||||
// MeetRecordingStatus.COMPLETE,
|
||||
// 3
|
||||
// );
|
||||
|
||||
@ -79,7 +79,7 @@ describe('Recording API Tests', () => {
|
||||
// Generate a new recording
|
||||
const response = await startRecording(room.roomId, moderatorCookie);
|
||||
console.log('Start recording response:', response.body);
|
||||
expectValidStartRecordingResponse(response, room.roomId);
|
||||
expectValidStartRecordingResponse(response, room.roomId, room.roomName);
|
||||
const secondRecordingId = response.body.recordingId;
|
||||
await stopRecording(secondRecordingId, moderatorCookie);
|
||||
|
||||
|
||||
@ -35,7 +35,14 @@ describe('Recording API Tests', () => {
|
||||
it('should return 200 when recording exists', async () => {
|
||||
const response = await getRecording(recordingId);
|
||||
|
||||
expectValidGetRecordingResponse(response, recordingId, room.roomId, MeetRecordingStatus.COMPLETE, 1);
|
||||
expectValidGetRecordingResponse(
|
||||
response,
|
||||
recordingId,
|
||||
room.roomId,
|
||||
room.roomName,
|
||||
MeetRecordingStatus.COMPLETE,
|
||||
1
|
||||
);
|
||||
});
|
||||
|
||||
it('should get an ACTIVE recording status', async () => {
|
||||
@ -47,7 +54,13 @@ describe('Recording API Tests', () => {
|
||||
} = contextAux.getRoomByIndex(0)!;
|
||||
const response = await getRecording(recordingIdAux);
|
||||
|
||||
expectValidGetRecordingResponse(response, recordingIdAux, roomAux.roomId, MeetRecordingStatus.ACTIVE);
|
||||
expectValidGetRecordingResponse(
|
||||
response,
|
||||
recordingIdAux,
|
||||
roomAux.roomId,
|
||||
roomAux.roomName,
|
||||
MeetRecordingStatus.ACTIVE
|
||||
);
|
||||
|
||||
await stopAllRecordings(moderatorCookieAux);
|
||||
});
|
||||
|
||||
@ -112,6 +112,7 @@ describe('Recordings API Tests', () => {
|
||||
recording,
|
||||
associatedRoom!.recordingId!,
|
||||
associatedRoom!.room.roomId,
|
||||
associatedRoom!.room.roomName,
|
||||
MeetRecordingStatus.COMPLETE
|
||||
);
|
||||
});
|
||||
@ -127,6 +128,7 @@ describe('Recordings API Tests', () => {
|
||||
recording,
|
||||
associatedRoom!.recordingId!,
|
||||
associatedRoom!.room.roomId,
|
||||
associatedRoom!.room.roomName,
|
||||
MeetRecordingStatus.COMPLETE
|
||||
);
|
||||
});
|
||||
|
||||
@ -192,17 +192,17 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
// Recording in different room should work normally
|
||||
const rec2 = await startRecording(room2.room.roomId, room2.moderatorCookie);
|
||||
expect(rec2.status).toBe(201);
|
||||
expectValidStartRecordingResponse(rec2, room2.room.roomId);
|
||||
expectValidStartRecordingResponse(rec2, room2.room.roomId, room2.room.roomName);
|
||||
|
||||
let response = await stopRecording(rec2.body.recordingId!, room2.moderatorCookie);
|
||||
expectValidStopRecordingResponse(response, rec2.body.recordingId!, room2.room.roomId);
|
||||
expectValidStopRecordingResponse(response, rec2.body.recordingId!, room2.room.roomId, room2.room.roomName);
|
||||
|
||||
// ✅ EXPECTED BEHAVIOR: After timeout cleanup, room1 should be available again
|
||||
const rec3 = await startRecording(room1.room.roomId, room1.moderatorCookie);
|
||||
expect(rec3.status).toBe(201);
|
||||
expectValidStartRecordingResponse(rec3, room1.room.roomId);
|
||||
expectValidStartRecordingResponse(rec3, room1.room.roomId, room1.room.roomName);
|
||||
response = await stopRecording(rec3.body.recordingId!, room1.moderatorCookie);
|
||||
expectValidStopRecordingResponse(response, rec3.body.recordingId!, room1.room.roomId);
|
||||
expectValidStopRecordingResponse(response, rec3.body.recordingId!, room1.room.roomId, room1.room.roomName);
|
||||
} finally {
|
||||
startRoomCompositeSpy.mockRestore();
|
||||
}
|
||||
@ -246,18 +246,14 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
|
||||
for (const startResult of retryResults) {
|
||||
expect(startResult.status).toBe(201);
|
||||
expectValidStartRecordingResponse(
|
||||
startResult,
|
||||
rooms.find((r) => r.room.roomId === startResult.body.roomId)!.room.roomId
|
||||
);
|
||||
const stopResult = await stopRecording(
|
||||
startResult.body.recordingId!,
|
||||
rooms.find((r) => r.room.roomId === startResult.body.roomId)!.moderatorCookie
|
||||
);
|
||||
const room = rooms.find((r) => r.room.roomId === startResult.body.roomId)!;
|
||||
expectValidStartRecordingResponse(startResult, room.room.roomId, room.room.roomName);
|
||||
const stopResult = await stopRecording(startResult.body.recordingId!, room.moderatorCookie);
|
||||
expectValidStopRecordingResponse(
|
||||
stopResult,
|
||||
startResult.body.recordingId!,
|
||||
rooms.find((r) => r.room.roomId === startResult.body.roomId)!.room.roomId
|
||||
room.room.roomId,
|
||||
room.room.roomName
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
@ -283,12 +279,12 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
|
||||
// Step 2: Start recording in roomB (this will complete quickly)
|
||||
const recordingResponseB = await startRecording(roomDataB!.room.roomId, roomDataB!.moderatorCookie);
|
||||
expectValidStartRecordingResponse(recordingResponseB, roomDataB!.room.roomId);
|
||||
expectValidStartRecordingResponse(recordingResponseB, roomDataB!.room.roomId, roomDataB!.room.roomName);
|
||||
const recordingIdB = recordingResponseB.body.recordingId;
|
||||
|
||||
// Step 3: Stop recording in roomB while roomA is still waiting for its event
|
||||
const stopResponseB = await stopRecording(recordingIdB, roomDataB!.moderatorCookie);
|
||||
expectValidStopRecordingResponse(stopResponseB, recordingIdB, roomDataB!.room.roomId);
|
||||
expectValidStopRecordingResponse(stopResponseB, recordingIdB, roomDataB!.room.roomId, roomDataB!.room.roomName);
|
||||
|
||||
eventController.releaseEventsForRoom(roomDataA!.room.roomId);
|
||||
|
||||
@ -311,7 +307,11 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
);
|
||||
|
||||
startResponses.forEach((response, index) => {
|
||||
expectValidStartRecordingResponse(response, roomDataList[index].room.roomId);
|
||||
expectValidStartRecordingResponse(
|
||||
response,
|
||||
roomDataList[index].room.roomId,
|
||||
roomDataList[index].room.roomName
|
||||
);
|
||||
});
|
||||
|
||||
const recordingIds = startResponses.map((res) => res.body.recordingId);
|
||||
@ -321,7 +321,12 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
);
|
||||
|
||||
stopResponses.forEach((response, index) => {
|
||||
expectValidStopRecordingResponse(response, recordingIds[index], roomDataList[index].room.roomId);
|
||||
expectValidStopRecordingResponse(
|
||||
response,
|
||||
recordingIds[index],
|
||||
roomDataList[index].room.roomId,
|
||||
roomDataList[index].room.roomName
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -338,8 +343,8 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
stopRecording(recordingIdA, roomDataA!.moderatorCookie),
|
||||
stopRecording(recordingIdB, roomDataB!.moderatorCookie)
|
||||
]);
|
||||
expectValidStopRecordingResponse(stopResponseA, recordingIdA, roomDataA!.room.roomId);
|
||||
expectValidStopRecordingResponse(stopResponseB, recordingIdB, roomDataB!.room.roomId);
|
||||
expectValidStopRecordingResponse(stopResponseA, recordingIdA, roomDataA!.room.roomId, roomDataA!.room.roomName);
|
||||
expectValidStopRecordingResponse(stopResponseB, recordingIdB, roomDataB!.room.roomId, roomDataB!.room.roomName);
|
||||
});
|
||||
|
||||
it('should prevent multiple recording starts in the same room', async () => {
|
||||
@ -361,16 +366,17 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
expect(oneShouldBeFailed).toBe(true);
|
||||
|
||||
if (firstRecordingResponse.status === 201) {
|
||||
expectValidStartRecordingResponse(firstRecordingResponse, roomData.room.roomId);
|
||||
expectValidStartRecordingResponse(firstRecordingResponse, roomData.room.roomId, roomData.room.roomName);
|
||||
// stop the first recording
|
||||
const stopResponse = await stopRecording(firstRecordingResponse.body.recordingId, roomData.moderatorCookie);
|
||||
expectValidStopRecordingResponse(
|
||||
stopResponse,
|
||||
firstRecordingResponse.body.recordingId,
|
||||
roomData.room.roomId
|
||||
roomData.room.roomId,
|
||||
roomData.room.roomName
|
||||
);
|
||||
} else {
|
||||
expectValidStartRecordingResponse(secondRecordingResponse, roomData.room.roomId);
|
||||
expectValidStartRecordingResponse(secondRecordingResponse, roomData.room.roomId, roomData.room.roomName);
|
||||
// stop the second recording
|
||||
const stopResponse = await stopRecording(
|
||||
secondRecordingResponse.body.recordingId,
|
||||
@ -379,7 +385,8 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
expectValidStopRecordingResponse(
|
||||
stopResponse,
|
||||
secondRecordingResponse.body.recordingId,
|
||||
roomData.room.roomId
|
||||
roomData.room.roomId,
|
||||
roomData.room.roomName
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -391,7 +398,7 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
const gcSpy = jest.spyOn(recordingService as any, 'performRecordingLocksGarbageCollection');
|
||||
|
||||
const startResponse = await startRecording(roomData.room.roomId, roomData.moderatorCookie);
|
||||
expectValidStartRecordingResponse(startResponse, roomData.room.roomId);
|
||||
expectValidStartRecordingResponse(startResponse, roomData.room.roomId, roomData.room.roomName);
|
||||
const recordingId = startResponse.body.recordingId;
|
||||
|
||||
// Execute garbage collection while stopping the recording
|
||||
@ -404,7 +411,7 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
|
||||
// Check that the recording was stopped successfully
|
||||
const stopResponse = await stopPromise;
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, roomData.room.roomId);
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, roomData.room.roomId, roomData.room.roomName);
|
||||
|
||||
// Check that garbage collection was called
|
||||
expect(gcSpy).toHaveBeenCalled();
|
||||
@ -482,9 +489,14 @@ describe('Recording API Race Conditions Tests', () => {
|
||||
expect(bulkDeleteResult.body).toEqual({});
|
||||
|
||||
// Check that the new recording started successfully
|
||||
expectValidStartRecordingResponse(newRecordingResult, room3.room.roomId);
|
||||
expectValidStartRecordingResponse(newRecordingResult, room3.room.roomId, room3.room.roomName);
|
||||
|
||||
const newStopResponse = await stopRecording(newRecordingResult.body.recordingId, room3.moderatorCookie);
|
||||
expectValidStopRecordingResponse(newStopResponse, newRecordingResult.body.recordingId, room3.room.roomId);
|
||||
expectValidStopRecordingResponse(
|
||||
newStopResponse,
|
||||
newRecordingResult.body.recordingId,
|
||||
room3.room.roomId,
|
||||
room3.room.roomName
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -51,16 +51,16 @@ describe('Recording API Tests', () => {
|
||||
it('should return 201 with proper response and location header when recording starts successfully', async () => {
|
||||
const response = await startRecording(room.roomId, moderatorCookie);
|
||||
const recordingId = response.body.recordingId;
|
||||
expectValidStartRecordingResponse(response, room.roomId);
|
||||
expectValidStartRecordingResponse(response, room.roomId, room.roomName);
|
||||
|
||||
const stopResponse = await stopRecording(recordingId, moderatorCookie);
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, room.roomId);
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, room.roomId, room.roomName);
|
||||
});
|
||||
|
||||
it('should secrets and archived room files be created when recording starts', async () => {
|
||||
const response = await startRecording(room.roomId, moderatorCookie);
|
||||
const recordingId = response.body.recordingId;
|
||||
expectValidStartRecordingResponse(response, room.roomId);
|
||||
expectValidStartRecordingResponse(response, room.roomId, room.roomName);
|
||||
|
||||
const storageService = container.get(MeetStorageService);
|
||||
|
||||
@ -76,24 +76,24 @@ describe('Recording API Tests', () => {
|
||||
expect(archivedRoom?.preferences).toBeDefined();
|
||||
|
||||
const secretsResponse = await stopRecording(recordingId, moderatorCookie);
|
||||
expectValidStopRecordingResponse(secretsResponse, recordingId, room.roomId);
|
||||
expectValidStopRecordingResponse(secretsResponse, recordingId, room.roomId, room.roomName);
|
||||
});
|
||||
|
||||
it('should successfully start recording, stop it, and start again (sequential operations)', async () => {
|
||||
const firstStartResponse = await startRecording(room.roomId, moderatorCookie);
|
||||
const firstRecordingId = firstStartResponse.body.recordingId;
|
||||
|
||||
expectValidStartRecordingResponse(firstStartResponse, room.roomId);
|
||||
expectValidStartRecordingResponse(firstStartResponse, room.roomId, room.roomName);
|
||||
|
||||
const firstStopResponse = await stopRecording(firstRecordingId, moderatorCookie);
|
||||
expectValidStopRecordingResponse(firstStopResponse, firstRecordingId, room.roomId);
|
||||
expectValidStopRecordingResponse(firstStopResponse, firstRecordingId, room.roomId, room.roomName);
|
||||
|
||||
const secondStartResponse = await startRecording(room.roomId, moderatorCookie);
|
||||
expectValidStartRecordingResponse(secondStartResponse, room.roomId);
|
||||
expectValidStartRecordingResponse(secondStartResponse, room.roomId, room.roomName);
|
||||
const secondRecordingId = secondStartResponse.body.recordingId;
|
||||
|
||||
const secondStopResponse = await stopRecording(secondRecordingId, moderatorCookie);
|
||||
expectValidStopRecordingResponse(secondStopResponse, secondRecordingId, room.roomId);
|
||||
expectValidStopRecordingResponse(secondStopResponse, secondRecordingId, room.roomId, room.roomName);
|
||||
});
|
||||
|
||||
it('should handle simultaneous recordings in different rooms correctly', async () => {
|
||||
@ -105,8 +105,8 @@ describe('Recording API Tests', () => {
|
||||
const firstResponse = await startRecording(roomDataA.room.roomId, roomDataA.moderatorCookie);
|
||||
const secondResponse = await startRecording(roomDataB.room.roomId, roomDataB.moderatorCookie);
|
||||
|
||||
expectValidStartRecordingResponse(firstResponse, roomDataA.room.roomId);
|
||||
expectValidStartRecordingResponse(secondResponse, roomDataB.room.roomId);
|
||||
expectValidStartRecordingResponse(firstResponse, roomDataA.room.roomId, roomDataA.room.roomName);
|
||||
expectValidStartRecordingResponse(secondResponse, roomDataB.room.roomId, roomDataB.room.roomName);
|
||||
|
||||
const firstRecordingId = firstResponse.body.recordingId;
|
||||
const secondRecordingId = secondResponse.body.recordingId;
|
||||
@ -115,8 +115,18 @@ describe('Recording API Tests', () => {
|
||||
stopRecording(firstRecordingId, roomDataA.moderatorCookie),
|
||||
stopRecording(secondRecordingId, roomDataB.moderatorCookie)
|
||||
]);
|
||||
expectValidStopRecordingResponse(firstStopResponse, firstRecordingId, roomDataA.room.roomId);
|
||||
expectValidStopRecordingResponse(secondStopResponse, secondRecordingId, roomDataB.room.roomId);
|
||||
expectValidStopRecordingResponse(
|
||||
firstStopResponse,
|
||||
firstRecordingId,
|
||||
roomDataA.room.roomId,
|
||||
roomDataA.room.roomName
|
||||
);
|
||||
expectValidStopRecordingResponse(
|
||||
secondStopResponse,
|
||||
secondRecordingId,
|
||||
roomDataB.room.roomId,
|
||||
roomDataB.room.roomName
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -180,13 +190,13 @@ describe('Recording API Tests', () => {
|
||||
await joinFakeParticipant(room.roomId, 'fakeParticipantId');
|
||||
const firstResponse = await startRecording(room.roomId, moderatorCookie);
|
||||
const recordingId = firstResponse.body.recordingId;
|
||||
expectValidStartRecordingResponse(firstResponse, room.roomId);
|
||||
expectValidStartRecordingResponse(firstResponse, room.roomId, room.roomName);
|
||||
|
||||
const secondResponse = await startRecording(room!.roomId, moderatorCookie);
|
||||
expect(secondResponse.status).toBe(409);
|
||||
expect(secondResponse.body.message).toContain('already');
|
||||
const stopResponse = await stopRecording(recordingId, moderatorCookie);
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, room.roomId);
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, room.roomId, room.roomName);
|
||||
});
|
||||
|
||||
it('should return 503 when recording start times out', async () => {
|
||||
|
||||
@ -39,7 +39,7 @@ describe('Recording API Tests', () => {
|
||||
|
||||
it('should stop an active recording and return 202', async () => {
|
||||
const response = await stopRecording(recordingId, moderatorCookie);
|
||||
expectValidStopRecordingResponse(response, recordingId, room.roomId);
|
||||
expectValidStopRecordingResponse(response, recordingId, room.roomId, room.roomName);
|
||||
});
|
||||
|
||||
it('should stop multiple recordings in parallel', async () => {
|
||||
@ -51,9 +51,19 @@ describe('Recording API Tests', () => {
|
||||
const recordingIdA = responseA.body.recordingId;
|
||||
const recordingIdB = responseB.body.recordingId;
|
||||
const stopResponseA = await stopRecording(recordingIdA, roomDataA?.moderatorCookie);
|
||||
expectValidStopRecordingResponse(stopResponseA, recordingIdA, roomDataA!.room.roomId);
|
||||
expectValidStopRecordingResponse(
|
||||
stopResponseA,
|
||||
recordingIdA,
|
||||
roomDataA!.room.roomId,
|
||||
roomDataA!.room.roomName
|
||||
);
|
||||
const stopResponseB = await stopRecording(recordingIdB, roomDataB?.moderatorCookie);
|
||||
expectValidStopRecordingResponse(stopResponseB, recordingIdB, roomDataB!.room.roomId);
|
||||
expectValidStopRecordingResponse(
|
||||
stopResponseB,
|
||||
recordingIdB,
|
||||
roomDataB!.room.roomId,
|
||||
roomDataB!.room.roomName
|
||||
);
|
||||
});
|
||||
|
||||
describe('Stop Recording Validation failures', () => {
|
||||
|
||||
@ -70,7 +70,7 @@ describe('Recording API Security Tests', () => {
|
||||
// Stop recording to clean up
|
||||
const recordingId = response.body.recordingId;
|
||||
const stopResponse = await stopRecording(recordingId, roomData.moderatorCookie);
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, roomData.room.roomId);
|
||||
expectValidStopRecordingResponse(stopResponse, recordingId, roomData.room.roomId, roomData.room.roomName);
|
||||
});
|
||||
|
||||
it('should fail when participant is moderator of a different room', async () => {
|
||||
|
||||
@ -18,6 +18,7 @@ export const enum MeetRecordingStatus {
|
||||
export interface MeetRecordingInfo {
|
||||
recordingId: string;
|
||||
roomId: string;
|
||||
roomName: string;
|
||||
// outputMode: MeetRecordingOutputMode;
|
||||
status: MeetRecordingStatus;
|
||||
filename?: string;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user