test: Add integration tests for GET Recording API and validation

This commit is contained in:
Carlos Santos 2025-04-24 14:05:06 +02:00
parent 0250d00f7b
commit 2c1657a58d
3 changed files with 134 additions and 1 deletions

View File

@ -0,0 +1,88 @@
import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
import {
deleteAllRecordings,
deleteAllRooms,
disconnectFakeParticipants,
getRecording,
startTestServer,
stopAllRecordings
} from '../../../utils/helpers.js';
import { errorRecordingNotFound } from '../../../../src/models/error.model.js';
import { expectValidationError, expectValidGetRecordingResponse } from '../../../utils/assertion-helpers.js';
import { setupMultiRecordingsTestContext, TestContext } from '../../../utils/test-scenarios.js';
import { MeetRoom } from '../../../../src/typings/ce/room.js';
import { MeetRecordingStatus } from '../../../../src/typings/ce/recording.model.js';
describe('Recording API Tests', () => {
let context: TestContext | null = null;
let room: MeetRoom, moderatorCookie: string, recordingId: string;
beforeAll(async () => {
startTestServer();
// Create a room and join a participant
context = await setupMultiRecordingsTestContext(1, 1, 1, '0s');
({ room, moderatorCookie, recordingId = '' } = context.getRoomByIndex(0)!);
});
afterAll(async () => {
await stopAllRecordings(moderatorCookie);
await disconnectFakeParticipants();
await deleteAllRooms();
await deleteAllRecordings();
context = null;
});
describe('Get Recording Tests', () => {
it('should return 200 when recording exists', async () => {
const response = await getRecording(recordingId);
console.log(response.body);
expectValidGetRecordingResponse(response, recordingId, room.roomId, MeetRecordingStatus.COMPLETE, 1);
});
it('should return 404 when recording does not exist', async () => {
const response = await getRecording('nonexistent--EG_222--4s444');
expect(response.status).toBe(404);
expect(response.body.message).toBe(errorRecordingNotFound('nonexistent--EG_222--4s444').message);
});
});
describe('Get Recording Validation', () => {
it('should fail when recordingId has incorrect format', async () => {
const response = await getRecording('incorrect-format');
expectValidationError(response, 'recordingId', 'does not follow the expected format');
});
it('should fail when recordingId has less than 3 parts', async () => {
const response = await getRecording('part1--part2');
expectValidationError(response, 'recordingId', 'does not follow the expected format');
});
it('should fail when recordingId first part is empty', async () => {
const response = await getRecording('--EG_12345--uid');
expectValidationError(response, 'recordingId', 'does not follow the expected format');
});
it('should fail when recordingId second part does not start with EG_', async () => {
const response = await getRecording(`${room.roomId}--INVALID--uid`);
expectValidationError(response, 'recordingId', 'does not follow the expected format');
});
it('should fail when recordingId second part is too short', async () => {
const response = await getRecording(`${room.roomId}--EG_--uid`);
expectValidationError(response, 'recordingId', 'does not follow the expected format');
});
it('should fail when recordingId third part is empty', async () => {
const response = await getRecording(`${room.roomId}--EG_12345--`);
expectValidationError(response, 'recordingId', 'does not follow the expected format');
});
it('should sanitize recordingId before validation', async () => {
const response = await getRecording(` ${recordingId} `);
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('recordingId', recordingId);
});
});
});

View File

@ -1,6 +1,6 @@
import { expect } from '@jest/globals';
import INTERNAL_CONFIG from '../../src/config/internal-config';
import { MeetRoom, MeetRoomPreferences } from '../../src/typings/ce';
import { MeetRecordingStatus, MeetRoom, MeetRoomPreferences } from '../../src/typings/ce';
const RECORDINGS_PATH = `${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/recordings`;
const expectErrorResponse = (
@ -180,3 +180,38 @@ export const expectValidStopRecordingResponse = (response: any, recordingId: str
expect(response.body).toHaveProperty('startDate');
expect(response.body).toHaveProperty('duration', expect.any(Number));
};
export const expectValidGetRecordingResponse = (
response: any,
recordingId: string,
roomId: string,
status: MeetRecordingStatus,
maxSecDuration: number
) => {
expect(response.status).toBe(200);
expect(response.body).toBeDefined();
const body = response.body;
expect(body).toMatchObject({ recordingId, roomId, status });
expect(body).toEqual(
expect.objectContaining({
duration: expect.any(Number),
startDate: expect.any(Number),
endDate: expect.any(Number),
size: expect.any(Number),
filename: expect.any(String),
details: expect.any(String)
})
);
expect(body.duration).toBeGreaterThanOrEqual(0);
expect(body.duration).toBeLessThanOrEqual(maxSecDuration);
expect(body.endDate).toBeGreaterThanOrEqual(body.startDate);
const computedSec = (body.endDate - body.startDate) / 1000;
const diffSec = Math.abs(body.duration - computedSec);
// Estimate 5 seconds of tolerace because of time to start/stop recording
expect(diffSec).toBeLessThanOrEqual(5);
};

View File

@ -356,6 +356,16 @@ export const stopRecording = async (recordingId: string, moderatorCookie = '') =
return response;
};
export const getRecording = async (recordingId: string) => {
if (!app) {
throw new Error('App instance is not defined');
}
return await request(app)
.get(`${INTERNAL_CONFIG.API_BASE_PATH_V1}/recordings/${recordingId}`)
.set(INTERNAL_CONFIG.API_KEY_HEADER, MEET_API_KEY);
}
export const stopAllRecordings = async (moderatorCookie: string) => {
if (!app) {
throw new Error('App instance is not defined');