test: enhance recordings and rooms API tests with filtering and sorting functionality

This commit is contained in:
juancarmore 2025-12-31 00:14:14 +01:00
parent 05980df465
commit 8d685e6ae5
3 changed files with 268 additions and 11 deletions

View File

@ -96,9 +96,10 @@ export const setupMultiRoomTestContext = async (
export const setupSingleRoomWithRecording = async (
stopRecordingCond = false,
stopDelay?: StringValue
stopDelay?: StringValue,
roomName = 'TEST_ROOM'
): Promise<RoomData> => {
const roomData = await setupSingleRoom(true, 'TEST_ROOM');
const roomData = await setupSingleRoom(true, roomName);
const response = await startRecording(roomData.room.roomId, roomData.moderatorToken);
expectValidStartRecordingResponse(response, roomData.room.roomId, roomData.room.roomName);
roomData.recordingId = response.body.recordingId;

View File

@ -13,14 +13,11 @@ import {
generateRoomMemberToken,
getAllRecordings,
getAllRecordingsFromRoom,
startTestServer
startTestServer,
stopRecording
} from '../../../helpers/request-helpers.js';
import {
RoomData,
setupMultiRecordingsTestContext,
setupSingleRoomWithRecording,
TestContext
} from '../../../helpers/test-scenarios.js';
import { setupMultiRecordingsTestContext, setupSingleRoomWithRecording } from '../../../helpers/test-scenarios.js';
import { RoomData, TestContext } from '../../../interfaces/scenarios.js';
describe('Recordings API Tests', () => {
let context: TestContext | null = null;
@ -81,6 +78,23 @@ describe('Recordings API Tests', () => {
expect(response.body.recordings[0].roomId).toBe(room.roomId);
});
it('should filter recordings by status', async () => {
// Create recordings with different statuses
const [roomData] = await Promise.all([
setupSingleRoomWithRecording(false), // Active
setupSingleRoomWithRecording(true) // Complete
]);
const response = await getAllRecordings({ status: MeetRecordingStatus.COMPLETE });
expectSuccessListRecordingResponse(response, 1, false, false);
const recordings = response.body.recordings;
expect(recordings[0].status).toBe(MeetRecordingStatus.COMPLETE);
// Stop the active recording to clean up
await stopRecording(roomData.recordingId!, roomData.moderatorToken);
});
it('should return recordings with fields filter applied', async () => {
context = await setupMultiRecordingsTestContext(2, 2, 2);
({ room } = context.getRoomByIndex(0)!);
@ -147,6 +161,130 @@ describe('Recordings API Tests', () => {
});
});
describe('List Recordings Sorting', () => {
let roomDataA: RoomData;
let roomDataB: RoomData;
let roomDataC: RoomData;
beforeAll(async () => {
// Create a single set of recordings that can be used by all sorting tests
// Created sequentially to ensure known creation order for startDate sorting
// With specific names for roomName sorting
// With different durations for duration/size sorting
roomDataA = await setupSingleRoomWithRecording(true, '1s', 'Room A');
roomDataB = await setupSingleRoomWithRecording(true, '2s', 'Room B');
roomDataC = await setupSingleRoomWithRecording(false, undefined, 'Room C');
});
afterAll(async () => {
// Stop the active recording
await stopRecording(roomDataC.recordingId!, roomDataC.moderatorToken);
// Disconnect participants and clean up
await disconnectFakeParticipants();
await Promise.all([deleteAllRooms(), deleteAllRecordings()]);
});
it('should sort recordings by startDate ascending and descending', async () => {
// Test ascending
let response = await getAllRecordings({ sortField: 'startDate', sortOrder: 'asc' });
let recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
expect(recordings[0].recordingId).toBe(roomDataA.recordingId);
expect(recordings[1].recordingId).toBe(roomDataB.recordingId);
expect(recordings[2].recordingId).toBe(roomDataC.recordingId);
// Test descending
response = await getAllRecordings({ sortField: 'startDate', sortOrder: 'desc' });
recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
expect(recordings).toHaveLength(3);
expect(recordings[0].recordingId).toBe(roomDataC.recordingId);
expect(recordings[1].recordingId).toBe(roomDataB.recordingId);
expect(recordings[2].recordingId).toBe(roomDataA.recordingId);
});
it('should sort recordings by roomName ascending and descending', async () => {
// Test ascending
let response = await getAllRecordings({ sortField: 'roomName', sortOrder: 'asc' });
let recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
expect(recordings).toHaveLength(3);
expect(recordings[0].roomName).toBe(roomDataA.room.roomName);
expect(recordings[1].roomName).toBe(roomDataB.room.roomName);
expect(recordings[2].roomName).toBe(roomDataC.room.roomName);
// Test descending
response = await getAllRecordings({ sortField: 'roomName', sortOrder: 'desc' });
recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
expect(recordings).toHaveLength(3);
expect(recordings[0].roomName).toBe(roomDataC.room.roomName);
expect(recordings[1].roomName).toBe(roomDataB.room.roomName);
expect(recordings[2].roomName).toBe(roomDataA.room.roomName);
});
it('should sort recordings by duration ascending and descending', async () => {
// Test ascending
let response = await getAllRecordings({ sortField: 'duration', sortOrder: 'asc' });
let recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
// The active recording has no duration, so it should appear first
expect(recordings[0].recordingId).toBe(roomDataC.recordingId);
expect(recordings[0].duration).toBeUndefined();
// Then the completed recordings in ascending duration order
expect(recordings[1].recordingId).toBe(roomDataA.recordingId);
expect(recordings[2].recordingId).toBe(roomDataB.recordingId);
// Test descending
response = await getAllRecordings({ sortField: 'duration', sortOrder: 'desc' });
recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
// Completed recordings in descending duration order
expect(recordings[0].recordingId).toBe(roomDataB.recordingId);
expect(recordings[1].recordingId).toBe(roomDataA.recordingId);
// The active recording has no duration, so it should appear last
expect(recordings[2].recordingId).toBe(roomDataC.recordingId);
expect(recordings[2].duration).toBeUndefined();
});
it('should sort recordings by size ascending and descending', async () => {
// Test ascending
let response = await getAllRecordings({ sortField: 'size', sortOrder: 'asc' });
let recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
// The active recording has no size, so it should appear first
expect(recordings[0].recordingId).toBe(roomDataC.recordingId);
expect(recordings[0].size).toBeUndefined();
// Then the completed recordings in ascending size order
expect(recordings[1].recordingId).toBe(roomDataA.recordingId);
expect(recordings[2].recordingId).toBe(roomDataB.recordingId);
// Test descending
response = await getAllRecordings({ sortField: 'size', sortOrder: 'desc' });
recordings = response.body.recordings;
expectSuccessListRecordingResponse(response, 3, false, false);
// Completed recordings in descending size order
expect(recordings[0].recordingId).toBe(roomDataB.recordingId);
expect(recordings[1].recordingId).toBe(roomDataA.recordingId);
// The active recording has no size, so it should appear last
expect(recordings[2].recordingId).toBe(roomDataC.recordingId);
expect(recordings[2].size).toBeUndefined();
});
});
describe('List Recordings Validation', () => {
it('should fail when maxItems is not a number', async () => {
const response = await getAllRecordings({ maxItems: 'not-a-number' });
@ -167,5 +305,20 @@ describe('Recordings API Tests', () => {
const response = await getAllRecordings({ fields: { invalid: 'object' } });
expectValidationError(response, 'fields', 'Expected string');
});
it('should fail when sortField is invalid', async () => {
const response = await getAllRecordings({ sortField: 'invalidField' });
expectValidationError(response, 'sortField', 'Invalid enum value');
});
it('should fail when sortOrder is invalid', async () => {
const response = await getAllRecordings({ sortOrder: 'invalid' });
expectValidationError(response, 'sortOrder', 'Invalid enum value');
});
it('should fail when status is invalid', async () => {
const response = await getAllRecordings({ status: 'invalid_status' });
expectValidationError(response, 'status', 'Invalid enum value');
});
});
});

View File

@ -1,6 +1,6 @@
import { afterEach, beforeAll, describe, it } from '@jest/globals';
import { afterEach, beforeAll, describe, expect, it } from '@jest/globals';
import { MeetRoom, MeetRoomStatus } from '@openvidu-meet/typings';
import ms from 'ms';
import { MeetRoom } from '@openvidu-meet/typings';
import {
expectSuccessRoomsResponse,
expectValidationError,
@ -8,6 +8,7 @@ import {
expectValidRoomWithFields
} from '../../../helpers/assertion-helpers.js';
import { createRoom, deleteAllRooms, getRooms, startTestServer } from '../../../helpers/request-helpers.js';
import { setupSingleRoom } from '../../../helpers/test-scenarios.js';
describe('Room API Tests', () => {
const validAutoDeletionDate = Date.now() + ms('2h');
@ -68,6 +69,17 @@ describe('Room API Tests', () => {
expectValidRoom(rooms[0], 'test-room');
});
it('should return a list of rooms applying status filter', async () => {
await setupSingleRoom(true); // Active meeting
await setupSingleRoom(false); // Open
const response = await getRooms({ status: MeetRoomStatus.ACTIVE_MEETING });
const { rooms } = response.body;
expectSuccessRoomsResponse(response, 1, 10, false, false);
expect(rooms[0].status).toBe(MeetRoomStatus.ACTIVE_MEETING);
});
it('should return a list of rooms with pagination', async () => {
// Create rooms sequentially to ensure different creation dates
for (let i = 0; i < 6; i++) {
@ -106,6 +118,82 @@ describe('Room API Tests', () => {
expectSuccessRoomsResponse(response, 0, 12, false, false);
});
it('should sort rooms by roomName ascending and descending', async () => {
await createRoom({ roomName: 'zebra-room' });
await createRoom({ roomName: 'alpha-room' });
await createRoom({ roomName: 'beta-room' });
// Test ascending
let response = await getRooms({ sortField: 'roomName', sortOrder: 'asc' });
let rooms = response.body.rooms;
expectSuccessRoomsResponse(response, 3, 10, false, false);
expectValidRoom(rooms[0], 'alpha-room');
expectValidRoom(rooms[1], 'beta-room');
expectValidRoom(rooms[2], 'zebra-room');
// Test descending
response = await getRooms({ sortField: 'roomName', sortOrder: 'desc' });
rooms = response.body.rooms;
expectSuccessRoomsResponse(response, 3, 10, false, false);
expectValidRoom(rooms[0], 'zebra-room');
expectValidRoom(rooms[1], 'beta-room');
expectValidRoom(rooms[2], 'alpha-room');
});
it('should sort rooms by creationDate ascending and descending', async () => {
const room1 = await createRoom({ roomName: 'first-room' });
const room2 = await createRoom({ roomName: 'second-room' });
const room3 = await createRoom({ roomName: 'third-room' });
// Test ascending
let response = await getRooms({ sortField: 'creationDate', sortOrder: 'asc' });
let rooms = response.body.rooms;
expectSuccessRoomsResponse(response, 3, 10, false, false);
expectValidRoom(rooms[0], room1.roomName);
expectValidRoom(rooms[1], room2.roomName);
expectValidRoom(rooms[2], room3.roomName);
// Test descending (default)
response = await getRooms({ sortField: 'creationDate', sortOrder: 'desc' });
rooms = response.body.rooms;
expectSuccessRoomsResponse(response, 3, 10, false, false);
expectValidRoom(rooms[0], room3.roomName);
expectValidRoom(rooms[1], room2.roomName);
expectValidRoom(rooms[2], room1.roomName);
});
it('should sort rooms by autoDeletionDate ascending and descending', async () => {
const now = Date.now();
const date1 = now + ms('2h');
const date2 = now + ms('3h');
await createRoom({ roomName: 'room-3h', autoDeletionDate: date2 });
await createRoom({ roomName: 'room-2h', autoDeletionDate: date1 });
await createRoom({ roomName: 'room-without-date' }); // Room without autoDeletionDate
// Test ascending
let response = await getRooms({ sortField: 'autoDeletionDate', sortOrder: 'asc' });
let rooms = response.body.rooms;
expectSuccessRoomsResponse(response, 3, 10, false, false);
expectValidRoom(rooms[0], 'room-without-date', undefined, undefined, undefined);
expectValidRoom(rooms[1], 'room-2h', undefined, undefined, date1);
expectValidRoom(rooms[2], 'room-3h', undefined, undefined, date2);
// Test descending
response = await getRooms({ sortField: 'autoDeletionDate', sortOrder: 'desc' });
rooms = response.body.rooms;
expectSuccessRoomsResponse(response, 3, 10, false, false);
expectValidRoom(rooms[0], 'room-3h', undefined, undefined, date2);
expectValidRoom(rooms[1], 'room-2h', undefined, undefined, date1);
expectValidRoom(rooms[2], 'room-without-date', undefined, undefined, undefined);
});
});
describe('List Room Validation failures', () => {
@ -128,5 +216,20 @@ describe('Room API Tests', () => {
const response = await getRooms({ fields: { invalid: 'data' } });
expectValidationError(response, 'fields', 'Expected string');
});
it('should fail when sortField is invalid', async () => {
const response = await getRooms({ sortField: 'invalidField' });
expectValidationError(response, 'sortField', 'Invalid enum value');
});
it('should fail when sortOrder is invalid', async () => {
const response = await getRooms({ sortOrder: 'invalid' });
expectValidationError(response, 'sortOrder', 'Invalid enum value');
});
it('should fail when status is invalid', async () => {
const response = await getRooms({ status: 'invalid_status' });
expectValidationError(response, 'status', 'Invalid enum value');
});
});
});