backend: replace roomIdPrefix with roomName
This commit is contained in:
parent
d8e6da5b4b
commit
459537ecfb
@ -8,7 +8,7 @@ content:
|
||||
summary: Full room details response
|
||||
value:
|
||||
roomId: 'room-123'
|
||||
roomIdPrefix: 'room'
|
||||
roomName: 'room'
|
||||
creationDate: 1620000000000
|
||||
autoDeletionDate: 1900000000000
|
||||
preferences:
|
||||
@ -26,11 +26,11 @@ content:
|
||||
value:
|
||||
roomId: 'room-123'
|
||||
|
||||
fields=roomId,roomIdPrefix,creationDate,autoDeletionDate,preferences:
|
||||
summary: Room details with roomId, roomIdPrefix, creationDate, autoDeletionDate, and preferences
|
||||
fields=roomId,roomName,creationDate,autoDeletionDate,preferences:
|
||||
summary: Room details with roomId, roomName, creationDate, autoDeletionDate, and preferences
|
||||
value:
|
||||
roomId: 'room-123'
|
||||
roomIdPrefix: 'room'
|
||||
roomName: 'room'
|
||||
creationDate: 1620000000000
|
||||
autoDeletionDate: 1900000000000
|
||||
preferences:
|
||||
|
||||
@ -17,7 +17,7 @@ content:
|
||||
value:
|
||||
rooms:
|
||||
- roomId: 'room-123'
|
||||
roomIdPrefix: 'room'
|
||||
roomName: 'room'
|
||||
creationDate: 1620000000000
|
||||
autoDeletionDate: 1900000000000
|
||||
preferences:
|
||||
@ -30,7 +30,7 @@ content:
|
||||
moderatorURL: 'http://localhost:6080/room/room-123?secret=123456'
|
||||
publisherURL: 'http://localhost:6080/room/room-123?secret=654321'
|
||||
- roomId: 'room-456'
|
||||
roomIdPrefix: 'room'
|
||||
roomName: 'room'
|
||||
creationDate: 1620001000000
|
||||
autoDeletionDate: 1900000000000
|
||||
preferences:
|
||||
@ -55,12 +55,12 @@ content:
|
||||
isTruncated: false
|
||||
maxItems: 10
|
||||
|
||||
fields=roomId,roomIdPrefix,creationDate,autoDeletionDate,preferences:
|
||||
fields=roomId,roomName,creationDate,autoDeletionDate,preferences:
|
||||
summary: Room details including preferences but no URLs
|
||||
value:
|
||||
rooms:
|
||||
- roomId: 'room-123'
|
||||
roomIdPrefix: 'room'
|
||||
roomName: 'room'
|
||||
creationDate: 1620000000000
|
||||
autoDeletionDate: 1900000000000
|
||||
preferences:
|
||||
@ -71,7 +71,7 @@ content:
|
||||
virtualBackgroundPreferences:
|
||||
enabled: true
|
||||
- roomId: 'room-456'
|
||||
roomIdPrefix: 'room'
|
||||
roomName: 'room'
|
||||
creationDate: 1620001000000
|
||||
autoDeletionDate: 1900000000000
|
||||
preferences:
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
type: object
|
||||
properties:
|
||||
roomName:
|
||||
type: [string, 'null']
|
||||
maxLength: 50
|
||||
example: 'room'
|
||||
default: 'Room'
|
||||
description: |
|
||||
The display name of the room, used to identify it in a user-friendly way. This value does not need to be unique.
|
||||
|
||||
Maximum length: 50 characters. If not provided, the default value "Room" will be used.
|
||||
autoDeletionDate:
|
||||
type: [number, 'null']
|
||||
example: 1900000000000
|
||||
@ -11,12 +20,6 @@ properties:
|
||||
It will be removed after the last participant leaves (graceful deletion).
|
||||
|
||||
If not set, the room remains active until manually deleted.
|
||||
roomIdPrefix:
|
||||
type: string
|
||||
example: 'room'
|
||||
description: >
|
||||
A prefix to be used for the room ID. The room ID will be generated by concatenating this prefix with an unique identifier.
|
||||
The maximum length of the room ID is 50 characters.
|
||||
# maxParticipants:
|
||||
# type: integer
|
||||
# example: 10
|
||||
|
||||
@ -4,12 +4,16 @@ properties:
|
||||
type: string
|
||||
example: 'room-123'
|
||||
description: >
|
||||
The unique identifier of the room. This ID is generated when the room is created.
|
||||
roomIdPrefix:
|
||||
type: string
|
||||
The unique identifier of the room. This ID is generated by combining the room name with a unique identifier.
|
||||
roomName:
|
||||
type: [string, 'null']
|
||||
maxLength: 50
|
||||
example: 'room'
|
||||
description: >
|
||||
The prefix used for the room ID. This prefix is used to generate the room ID.
|
||||
default: 'Room'
|
||||
description: |
|
||||
The display name of the room, used to identify it in a user-friendly way. This value does not need to be unique.
|
||||
|
||||
Maximum length: 50 characters. If not provided, the default value "Room" will be used.
|
||||
creationDate:
|
||||
type: number
|
||||
example: 1620000000000
|
||||
|
||||
@ -14,10 +14,10 @@ export class MeetRoomHelper {
|
||||
*/
|
||||
static toOpenViduOptions(room: MeetRoom): MeetRoomOptions {
|
||||
return {
|
||||
roomName: room.roomName,
|
||||
autoDeletionDate: room.autoDeletionDate,
|
||||
// maxParticipants: room.maxParticipants,
|
||||
preferences: room.preferences,
|
||||
roomIdPrefix: room.roomIdPrefix
|
||||
preferences: room.preferences
|
||||
// maxParticipants: room.maxParticipants
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,25 @@ import { z } from 'zod';
|
||||
import INTERNAL_CONFIG from '../../config/internal-config.js';
|
||||
import { rejectUnprocessableRequest } from '../../models/error.model.js';
|
||||
|
||||
/**
|
||||
* Sanitizes a room name by removing invalid characters and normalizing format.
|
||||
*
|
||||
* @param val The string to sanitize
|
||||
* @returns A sanitized string safe for use as a room name
|
||||
*/
|
||||
const sanitizeRoomName = (val: string): string => {
|
||||
return val
|
||||
.trim() // Remove leading/trailing spaces
|
||||
.replace(/[^a-zA-Z0-9_-\s]/g, '') // Allow alphanumeric, underscores, hyphens and spaces
|
||||
.replace(/\s+/g, ' ') // Replace multiple consecutive spaces with a single space
|
||||
.replace(/-+/g, '-') // Replace multiple consecutive hyphens with a single hyphen
|
||||
.replace(/_+/g, '_') // Replace multiple consecutive underscores with a single underscore
|
||||
.replace(/-+$/, '') // Remove trailing hyphens
|
||||
.replace(/_+$/, '') // Remove trailing underscores
|
||||
.replace(/^-+/, '') // Remove leading hyphens
|
||||
.replace(/^_+/, ''); // Remove leading underscores
|
||||
};
|
||||
|
||||
/**
|
||||
* Sanitizes an identifier by removing/replacing invalid characters
|
||||
* and normalizing format.
|
||||
@ -21,19 +40,7 @@ import { rejectUnprocessableRequest } from '../../models/error.model.js';
|
||||
* @returns A sanitized string safe for use as an identifier
|
||||
*/
|
||||
const sanitizeRoomId = (val: string): string => {
|
||||
let transformed = val
|
||||
.trim() // Remove leading/trailing spaces
|
||||
.replace(/\s+/g, '') // Remove all spaces
|
||||
.replace(/[^a-zA-Z0-9_-]/g, '') // Allow alphanumeric, underscores and hyphens
|
||||
.replace(/-+/g, '-') // Replace multiple consecutive hyphens
|
||||
.replace(/-+$/, ''); // Remove trailing hyphens
|
||||
|
||||
// Remove leading hyphens
|
||||
if (transformed.startsWith('-')) {
|
||||
transformed = transformed.substring(1);
|
||||
}
|
||||
|
||||
return transformed;
|
||||
return sanitizeRoomName(val).replace(/\s+/g, ''); // Remove all spaces
|
||||
};
|
||||
|
||||
export const nonEmptySanitizedRoomId = (fieldName: string) =>
|
||||
@ -94,6 +101,12 @@ const RoomPreferencesSchema: z.ZodType<MeetRoomPreferences> = z.object({
|
||||
});
|
||||
|
||||
const RoomRequestOptionsSchema: z.ZodType<MeetRoomOptions> = z.object({
|
||||
roomName: z
|
||||
.string()
|
||||
.max(50, 'roomName cannot exceed 50 characters')
|
||||
.transform(sanitizeRoomName)
|
||||
.optional()
|
||||
.default('Room'),
|
||||
autoDeletionDate: z
|
||||
.number()
|
||||
.positive('autoDeletionDate must be a positive integer')
|
||||
@ -102,12 +115,6 @@ const RoomRequestOptionsSchema: z.ZodType<MeetRoomOptions> = z.object({
|
||||
`autoDeletionDate must be at least ${INTERNAL_CONFIG.MIN_FUTURE_TIME_FOR_ROOM_AUTODELETION_DATE} in the future`
|
||||
)
|
||||
.optional(),
|
||||
roomIdPrefix: z
|
||||
.string()
|
||||
.max(50, 'roomIdPrefix cannot exceed 50 characters')
|
||||
.transform(sanitizeRoomId)
|
||||
.optional()
|
||||
.default(''),
|
||||
preferences: RoomPreferencesSchema.optional().default({
|
||||
recordingPreferences: { enabled: true, allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER },
|
||||
chatPreferences: { enabled: true },
|
||||
@ -185,6 +192,7 @@ export const withValidRoomOptions = (req: Request, res: Response, next: NextFunc
|
||||
return rejectUnprocessableRequest(res, error);
|
||||
}
|
||||
|
||||
console.log('VALID ROOM OPTIONS', data);
|
||||
req.body = data;
|
||||
next();
|
||||
};
|
||||
|
||||
@ -50,7 +50,6 @@ roomRouter.get(
|
||||
configureRoomAuthorization,
|
||||
roomCtrl.getRoom
|
||||
);
|
||||
|
||||
roomRouter.put(
|
||||
'/:roomId',
|
||||
withAuth(apiKeyValidator, tokenAndRoleValidator(UserRole.ADMIN)),
|
||||
|
||||
@ -69,12 +69,13 @@ export class RoomService {
|
||||
*
|
||||
*/
|
||||
async createMeetRoom(baseUrl: string, roomOptions: MeetRoomOptions): Promise<MeetRoom> {
|
||||
const { preferences, autoDeletionDate, roomIdPrefix } = roomOptions;
|
||||
const roomId = roomIdPrefix ? `${roomIdPrefix}-${uid(15)}` : uid(15);
|
||||
const { roomName, autoDeletionDate, preferences } = roomOptions;
|
||||
const roomIdPrefix = roomName!.replace(/\s+/g, ''); // Remove all spaces
|
||||
const roomId = `${roomIdPrefix}-${uid(15)}`; // Generate a unique room ID based on the room name
|
||||
|
||||
const meetRoom: MeetRoom = {
|
||||
roomId,
|
||||
roomIdPrefix,
|
||||
roomName: roomName!,
|
||||
creationDate: Date.now(),
|
||||
// maxParticipants,
|
||||
autoDeletionDate,
|
||||
|
||||
@ -86,12 +86,12 @@ export const expectSuccessRoomsResponse = (
|
||||
|
||||
export const expectSuccessRoomResponse = (
|
||||
response: any,
|
||||
idPrefix: string,
|
||||
roomName: string,
|
||||
autoDeletionDate?: number,
|
||||
preferences?: MeetRoomPreferences
|
||||
) => {
|
||||
expect(response.status).toBe(200);
|
||||
expectValidRoom(response.body, idPrefix, autoDeletionDate, preferences);
|
||||
expectValidRoom(response.body, roomName, autoDeletionDate, preferences);
|
||||
};
|
||||
|
||||
export const expectSuccessRoomPreferencesResponse = (response: any, preferences: MeetRoomPreferences) => {
|
||||
@ -102,7 +102,7 @@ export const expectSuccessRoomPreferencesResponse = (response: any, preferences:
|
||||
|
||||
export const expectValidRoom = (
|
||||
room: MeetRoom,
|
||||
idPrefix: string,
|
||||
name: string,
|
||||
autoDeletionDate?: number,
|
||||
preferences?: MeetRoomPreferences,
|
||||
markedForDeletion?: boolean
|
||||
@ -110,10 +110,10 @@ export const expectValidRoom = (
|
||||
expect(room).toBeDefined();
|
||||
|
||||
expect(room.roomId).toBeDefined();
|
||||
expect(room.roomIdPrefix).toBeDefined();
|
||||
expect(room.roomIdPrefix).toBe(idPrefix);
|
||||
expect(room.roomName).toBeDefined();
|
||||
expect(room.roomName).toBe(name);
|
||||
expect(room.roomId).not.toBe('');
|
||||
expect(room.roomId).toContain(room.roomIdPrefix);
|
||||
expect(room.roomId).toContain(room.roomName.replace(/\s+/g, '')); // Ensure roomId contains the name without spaces
|
||||
expect(room.creationDate).toBeDefined();
|
||||
|
||||
if (autoDeletionDate !== undefined) {
|
||||
|
||||
@ -34,15 +34,17 @@ export interface TestContext {
|
||||
* Creates a single room with optional participant.
|
||||
*
|
||||
* @param withParticipant Whether to join a fake participant in the room.
|
||||
* @param roomName Name of the room to create.
|
||||
* @param preferences Optional room preferences.
|
||||
* @returns Room data including secrets and cookies.
|
||||
*/
|
||||
export const setupSingleRoom = async (
|
||||
withParticipant = false,
|
||||
roomPrefix = 'TEST_ROOM',
|
||||
roomName = 'TEST_ROOM',
|
||||
preferences?: MeetRoomPreferences
|
||||
): Promise<RoomData> => {
|
||||
const room = await createRoom({
|
||||
roomIdPrefix: roomPrefix,
|
||||
roomName,
|
||||
preferences
|
||||
});
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should delete room (204) with invalid force parameter when no participants exist', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-invalid-force' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-invalid-force' });
|
||||
|
||||
const response = await bulkDeleteRooms([roomId]);
|
||||
|
||||
@ -41,7 +41,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should mark room for deletion (202) with invalid force parameter when participants exist', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-invalid-force' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-invalid-force' });
|
||||
|
||||
await joinFakeParticipant(roomId, 'test-participant-1');
|
||||
|
||||
@ -53,7 +53,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should delete room (204) with force=true parameter when no participants exist', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-force' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-force' });
|
||||
|
||||
const response = await bulkDeleteRooms([roomId], true);
|
||||
|
||||
@ -63,7 +63,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should delete room (204) with force=true parameter when participants exist', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-force' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-force' });
|
||||
|
||||
await joinFakeParticipant(roomId, 'test-participant-1');
|
||||
|
||||
@ -75,7 +75,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should successfully delete the room requesting the same roomId multiple times', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-duplicate' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-duplicate' });
|
||||
|
||||
const response = await bulkDeleteRooms([roomId, roomId, roomId], true);
|
||||
|
||||
@ -84,7 +84,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should successfully delete valid roomIds while ignoring invalid ones', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-invalid-force' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-invalid-force' });
|
||||
|
||||
const response = await bulkDeleteRooms([roomId, '!!@##$']);
|
||||
|
||||
@ -95,8 +95,8 @@ describe('Room API Tests', () => {
|
||||
it('should successfully delete multiple rooms with valid roomIds', async () => {
|
||||
// Create test rooms
|
||||
const [room1, room2] = await Promise.all([
|
||||
createRoom({ roomIdPrefix: 'test-bulk-1' }),
|
||||
createRoom({ roomIdPrefix: 'test-bulk-2' })
|
||||
createRoom({ roomName: 'test-bulk-1' }),
|
||||
createRoom({ roomName: 'test-bulk-2' })
|
||||
]);
|
||||
|
||||
// Delete both rooms
|
||||
@ -117,8 +117,8 @@ describe('Room API Tests', () => {
|
||||
it('should successfully marked for deletion multiple rooms with valid roomIds', async () => {
|
||||
// Create test rooms
|
||||
const [room1, room2] = await Promise.all([
|
||||
createRoom({ roomIdPrefix: 'test-bulk-1' }),
|
||||
createRoom({ roomIdPrefix: 'test-bulk-2' })
|
||||
createRoom({ roomName: 'test-bulk-1' }),
|
||||
createRoom({ roomName: 'test-bulk-2' })
|
||||
]);
|
||||
|
||||
await Promise.all([
|
||||
@ -147,7 +147,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should sanitize roomIds before deleting', async () => {
|
||||
// Create a test room
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-sanitize' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-sanitize' });
|
||||
|
||||
const response = await bulkDeleteRooms([roomId + '!!@##$']);
|
||||
expect(response.status).toBe(204);
|
||||
@ -160,8 +160,8 @@ describe('Room API Tests', () => {
|
||||
it('should delete rooms when force=true and participants exist', async () => {
|
||||
// Create test rooms
|
||||
const [room1, room2] = await Promise.all([
|
||||
createRoom({ roomIdPrefix: 'test-bulk-1' }),
|
||||
createRoom({ roomIdPrefix: 'test-bulk-2' })
|
||||
createRoom({ roomName: 'test-bulk-1' }),
|
||||
createRoom({ roomName: 'test-bulk-2' })
|
||||
]);
|
||||
|
||||
// Join a participant to the rooms
|
||||
@ -188,8 +188,8 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should return mixed results (200) when some rooms are deleted and others marked for deletion', async () => {
|
||||
// Create rooms
|
||||
const room1 = await createRoom({ roomIdPrefix: 'empty-room' });
|
||||
const room2 = await createRoom({ roomIdPrefix: 'occupied-room' });
|
||||
const room1 = await createRoom({ roomName: 'empty-room' });
|
||||
const room2 = await createRoom({ roomName: 'occupied-room' });
|
||||
|
||||
// Add participant to only one room
|
||||
await joinFakeParticipant(room2.roomId, 'test-participant');
|
||||
@ -214,7 +214,7 @@ describe('Room API Tests', () => {
|
||||
it('should handle a large number of room IDs', async () => {
|
||||
// Create 20+ rooms and test deletion
|
||||
const rooms = await Promise.all(
|
||||
Array.from({ length: 20 }, (_, i) => createRoom({ roomIdPrefix: `bulk-${i}` }))
|
||||
Array.from({ length: 20 }, (_, i) => createRoom({ roomName: `bulk-${i}` }))
|
||||
);
|
||||
|
||||
const response = await bulkDeleteRooms(rooms.map((r) => r.roomId));
|
||||
@ -230,7 +230,7 @@ describe('Room API Tests', () => {
|
||||
it('should handle a large number of room IDs with mixed valid and invalid IDs', async () => {
|
||||
// Create 20+ rooms and test deletion
|
||||
const rooms = await Promise.all(
|
||||
Array.from({ length: 20 }, (_, i) => createRoom({ roomIdPrefix: `bulk-${i}` }))
|
||||
Array.from({ length: 20 }, (_, i) => createRoom({ roomName: `bulk-${i}` }))
|
||||
);
|
||||
|
||||
await joinFakeParticipant(rooms[0].roomId, 'test-participant-1');
|
||||
|
||||
@ -27,23 +27,23 @@ describe('Room API Tests', () => {
|
||||
describe('Room Creation Tests', () => {
|
||||
it('Should create a room without autoDeletionDate (default behavior)', async () => {
|
||||
const room = await createRoom({
|
||||
roomIdPrefix: ' Test Room '
|
||||
roomName: ' Test Room '
|
||||
});
|
||||
expectValidRoom(room, 'TestRoom');
|
||||
expectValidRoom(room, 'Test Room');
|
||||
});
|
||||
|
||||
it('Should create a room with a valid autoDeletionDate', async () => {
|
||||
const room = await createRoom({
|
||||
autoDeletionDate: validAutoDeletionDate,
|
||||
roomIdPrefix: ' .,-------}{¡$#<+My Room *123 '
|
||||
roomName: ' .,-------}{¡$#<+My Room *123 '
|
||||
});
|
||||
|
||||
expectValidRoom(room, 'MyRoom123', validAutoDeletionDate);
|
||||
expectValidRoom(room, 'My Room 123', validAutoDeletionDate);
|
||||
});
|
||||
|
||||
it('Should create a room when sending full valid payload', async () => {
|
||||
const payload = {
|
||||
roomIdPrefix: ' =Example Room&/ ',
|
||||
roomName: ' =Example Room&/ ',
|
||||
autoDeletionDate: validAutoDeletionDate,
|
||||
preferences: {
|
||||
recordingPreferences: {
|
||||
@ -57,7 +57,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
const room = await createRoom(payload);
|
||||
|
||||
expectValidRoom(room, 'ExampleRoom', validAutoDeletionDate, payload.preferences);
|
||||
expectValidRoom(room, 'Example Room', validAutoDeletionDate, payload.preferences);
|
||||
});
|
||||
});
|
||||
|
||||
@ -65,7 +65,7 @@ describe('Room API Tests', () => {
|
||||
it('should fail when autoDeletionDate is negative', async () => {
|
||||
const payload = {
|
||||
autoDeletionDate: -5000,
|
||||
roomIdPrefix: 'TestRoom'
|
||||
roomName: 'TestRoom'
|
||||
};
|
||||
|
||||
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
|
||||
@ -78,7 +78,7 @@ describe('Room API Tests', () => {
|
||||
it('should fail when autoDeletionDate is less than 1 hour in the future', async () => {
|
||||
const payload = {
|
||||
autoDeletionDate: Date.now() + ms('30m'),
|
||||
roomIdPrefix: 'TestRoom'
|
||||
roomName: 'TestRoom'
|
||||
};
|
||||
|
||||
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
|
||||
@ -92,7 +92,7 @@ describe('Room API Tests', () => {
|
||||
it('should fail when autoDeletionDate is not a number (string provided)', async () => {
|
||||
const payload = {
|
||||
autoDeletionDate: 'not-a-number',
|
||||
roomIdPrefix: 'TestRoom'
|
||||
roomName: 'TestRoom'
|
||||
};
|
||||
|
||||
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
|
||||
@ -103,7 +103,7 @@ describe('Room API Tests', () => {
|
||||
it('should fail when autoDeletionDate is a boolean', async () => {
|
||||
const payload = {
|
||||
autoDeletionDate: true,
|
||||
roomIdPrefix: 'TestRoom'
|
||||
roomName: 'TestRoom'
|
||||
};
|
||||
|
||||
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
|
||||
@ -114,7 +114,7 @@ describe('Room API Tests', () => {
|
||||
it('should fail when autoDeletionDate is omitted but provided as null', async () => {
|
||||
const payload = {
|
||||
autoDeletionDate: null,
|
||||
roomIdPrefix: 'TestRoom'
|
||||
roomName: 'TestRoom'
|
||||
};
|
||||
|
||||
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
|
||||
@ -122,9 +122,9 @@ describe('Room API Tests', () => {
|
||||
expect(JSON.stringify(response.body.details)).toContain('Expected number');
|
||||
});
|
||||
|
||||
it('should fail when roomIdPrefix is not a string (number provided)', async () => {
|
||||
it('should fail when roomName is not a string (number provided)', async () => {
|
||||
const payload = {
|
||||
roomIdPrefix: 12345,
|
||||
roomName: 12345,
|
||||
autoDeletionDate: validAutoDeletionDate
|
||||
};
|
||||
|
||||
@ -133,9 +133,9 @@ describe('Room API Tests', () => {
|
||||
expect(JSON.stringify(response.body.details)).toContain('Expected string');
|
||||
});
|
||||
|
||||
it('should fail when roomIdPrefix is a boolean', async () => {
|
||||
it('should fail when roomName is a boolean', async () => {
|
||||
const payload = {
|
||||
roomIdPrefix: false,
|
||||
roomName: false,
|
||||
autoDeletionDate: validAutoDeletionDate
|
||||
};
|
||||
|
||||
@ -146,7 +146,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should fail when preferences is not an object (string provided)', async () => {
|
||||
const payload = {
|
||||
roomIdPrefix: 'TestRoom',
|
||||
roomName: 'TestRoom',
|
||||
autoDeletionDate: validAutoDeletionDate,
|
||||
preferences: 'invalid-preferences'
|
||||
};
|
||||
@ -160,7 +160,7 @@ describe('Room API Tests', () => {
|
||||
// Assuming preferences expects each sub-property to be an object with a boolean "enabled",
|
||||
// here we deliberately use an invalid structure.
|
||||
const payload = {
|
||||
roomIdPrefix: 'TestRoom',
|
||||
roomName: 'TestRoom',
|
||||
autoDeletionDate: validAutoDeletionDate,
|
||||
preferences: {
|
||||
recordingPreferences: {
|
||||
@ -183,23 +183,23 @@ describe('Room API Tests', () => {
|
||||
.post(ROOMS_PATH)
|
||||
.set('Cookie', adminCookie)
|
||||
.set('Content-Type', 'application/json')
|
||||
.send('{"roomIdPrefix": "TestRoom",') // invalid JSON syntax
|
||||
.send('{"roomName": "TestRoom",') // invalid JSON syntax
|
||||
.expect(400);
|
||||
|
||||
expect(response.body.error).toContain('Bad Request');
|
||||
expect(response.body.message).toContain('Malformed body');
|
||||
});
|
||||
|
||||
it('should fail when roomIdPrefix is too long', async () => {
|
||||
it('should fail when roomName is too long', async () => {
|
||||
const longRoomId = 'a'.repeat(51);
|
||||
const payload = {
|
||||
roomIdPrefix: longRoomId,
|
||||
roomName: longRoomId,
|
||||
autoDeletionDate: validAutoDeletionDate
|
||||
};
|
||||
|
||||
const response = await request(app).post(ROOMS_PATH).set('Cookie', adminCookie).send(payload).expect(422);
|
||||
|
||||
expect(JSON.stringify(response.body.details)).toContain('roomIdPrefix cannot exceed 50 characters');
|
||||
expect(JSON.stringify(response.body.details)).toContain('roomName cannot exceed 50 characters');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -36,7 +36,7 @@ describe('Room API Tests', () => {
|
||||
it('should default to force=false when force parameter is invalid', async () => {
|
||||
// Create a room first
|
||||
const { roomId } = await createRoom({
|
||||
roomIdPrefix: 'test-room'
|
||||
roomName: 'test-room'
|
||||
});
|
||||
const response = await deleteRoom(roomId, { force: 'not-a-boolean' });
|
||||
|
||||
@ -49,7 +49,7 @@ describe('Room API Tests', () => {
|
||||
it('should mark room for deletion when participants exist and force parameter is invalid', async () => {
|
||||
// Create a room first
|
||||
const { roomId } = await createRoom({
|
||||
roomIdPrefix: 'test-room'
|
||||
roomName: 'test-room'
|
||||
});
|
||||
|
||||
await joinFakeParticipant(roomId, 'test-participant');
|
||||
@ -70,7 +70,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should delete an empty room completely (204)', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-room' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-room' });
|
||||
|
||||
const response = await deleteRoom(roomId);
|
||||
|
||||
@ -84,7 +84,7 @@ describe('Room API Tests', () => {
|
||||
it('should sanitize roomId with spaces and special characters before deletion', async () => {
|
||||
// Create a room first
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-mixed'
|
||||
roomName: 'test-mixed'
|
||||
});
|
||||
|
||||
// Add some spaces and special chars to the valid roomId
|
||||
@ -101,7 +101,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should handle explicit force=true for room with no participants', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-room'
|
||||
roomName: 'test-room'
|
||||
});
|
||||
|
||||
const response = await deleteRoom(createdRoom.roomId, { force: true });
|
||||
@ -116,7 +116,7 @@ describe('Room API Tests', () => {
|
||||
it('should mark room for deletion (202) when participants exist and force=false', async () => {
|
||||
const autoDeletionDate = Date.now() + ms('5h');
|
||||
const { roomId } = await createRoom({
|
||||
roomIdPrefix: 'test-room',
|
||||
roomName: 'test-room',
|
||||
autoDeletionDate
|
||||
});
|
||||
|
||||
@ -133,7 +133,7 @@ describe('Room API Tests', () => {
|
||||
it('should delete a room marked for deletion when the webhook room_finished is received', async () => {
|
||||
const autoDeletionDate = Date.now() + ms('5h');
|
||||
const { roomId } = await createRoom({
|
||||
roomIdPrefix: 'test-room',
|
||||
roomName: 'test-room',
|
||||
autoDeletionDate
|
||||
});
|
||||
|
||||
@ -166,7 +166,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should force delete (204) room with active participants when force=true', async () => {
|
||||
const { roomId } = await createRoom({
|
||||
roomIdPrefix: 'test-room'
|
||||
roomName: 'test-room'
|
||||
});
|
||||
|
||||
await joinFakeParticipant(roomId, 'test-participant');
|
||||
@ -182,7 +182,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should successfully delete a room already marked for deletion', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-marked' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-marked' });
|
||||
|
||||
// First mark it for deletion
|
||||
await joinFakeParticipant(roomId, 'test-participant');
|
||||
@ -195,7 +195,7 @@ describe('Room API Tests', () => {
|
||||
});
|
||||
|
||||
it('should handle repeated deletion of the same room gracefully', async () => {
|
||||
const { roomId } = await createRoom({ roomIdPrefix: 'test-idempotent' });
|
||||
const { roomId } = await createRoom({ roomName: 'test-idempotent' });
|
||||
|
||||
// Delete first time
|
||||
const response1 = await deleteRoom(roomId);
|
||||
|
||||
@ -31,7 +31,7 @@ describe('Room Garbage Collector Tests', () => {
|
||||
|
||||
it('should delete a room with a past auto-deletion date if no participant is present', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-gc',
|
||||
roomName: 'test-gc',
|
||||
autoDeletionDate: Date.now() + ms('1s')
|
||||
});
|
||||
|
||||
@ -50,7 +50,7 @@ describe('Room Garbage Collector Tests', () => {
|
||||
|
||||
it('should mark room for deletion but not delete when expiration date has passed and participants exist', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-gc-participants',
|
||||
roomName: 'test-gc-participants',
|
||||
autoDeletionDate: Date.now() + ms('1s')
|
||||
});
|
||||
|
||||
@ -66,7 +66,7 @@ describe('Room Garbage Collector Tests', () => {
|
||||
|
||||
it('should not touch a room with a future auto-deletion date', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-gc-future',
|
||||
roomName: 'test-gc-future',
|
||||
autoDeletionDate: Date.now() + ms('1h')
|
||||
});
|
||||
|
||||
@ -79,7 +79,7 @@ describe('Room Garbage Collector Tests', () => {
|
||||
|
||||
it('should delete a room after the last participant leaves when it was marked for deletion', async () => {
|
||||
const { roomId } = await createRoom({
|
||||
roomIdPrefix: 'test-gc-lifecycle',
|
||||
roomName: 'test-gc-lifecycle',
|
||||
autoDeletionDate: Date.now() + ms('1s')
|
||||
});
|
||||
|
||||
@ -118,7 +118,7 @@ describe('Room Garbage Collector Tests', () => {
|
||||
|
||||
it('should never delete a room without an auto-deletion date', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-gc-no-date'
|
||||
roomName: 'test-gc-no-date'
|
||||
});
|
||||
|
||||
await runRoomGarbageCollector();
|
||||
@ -135,16 +135,16 @@ describe('Room Garbage Collector Tests', () => {
|
||||
|
||||
it('should handle multiple expired rooms in one batch', async () => {
|
||||
const rooms = await Promise.all([
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-1', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-2', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-3', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-4', autoDeletionDate: Date.now() + ms('1h') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-5', autoDeletionDate: Date.now() + ms('1h') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-6', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-7', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-8', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-9', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomIdPrefix: 'test-gc-multi-10', autoDeletionDate: Date.now() + ms('1s') })
|
||||
createRoom({ roomName: 'test-gc-multi-1', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomName: 'test-gc-multi-2', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomName: 'test-gc-multi-3', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomName: 'test-gc-multi-4', autoDeletionDate: Date.now() + ms('1h') }),
|
||||
createRoom({ roomName: 'test-gc-multi-5', autoDeletionDate: Date.now() + ms('1h') }),
|
||||
createRoom({ roomName: 'test-gc-multi-6', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomName: 'test-gc-multi-7', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomName: 'test-gc-multi-8', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomName: 'test-gc-multi-9', autoDeletionDate: Date.now() + ms('1s') }),
|
||||
createRoom({ roomName: 'test-gc-multi-10', autoDeletionDate: Date.now() + ms('1s') })
|
||||
]);
|
||||
|
||||
// Make sure all rooms are expired
|
||||
|
||||
@ -35,7 +35,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should retrieve custom room preferences', async () => {
|
||||
const payload = {
|
||||
roomIdPrefix: 'custom-prefs',
|
||||
roomName: 'custom-prefs',
|
||||
preferences: {
|
||||
recordingPreferences: {
|
||||
enabled: true,
|
||||
@ -46,7 +46,7 @@ describe('Room API Tests', () => {
|
||||
}
|
||||
};
|
||||
|
||||
const roomData = await setupSingleRoom(false, payload.roomIdPrefix, payload.preferences);
|
||||
const roomData = await setupSingleRoom(false, payload.roomName, payload.preferences);
|
||||
const roomId = roomData.room.roomId;
|
||||
const cookie = roomData.moderatorCookie;
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ describe('Room API Tests', () => {
|
||||
describe('Get Room Tests', () => {
|
||||
it('should successfully retrieve a room by its ID', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-room'
|
||||
roomName: 'test-room'
|
||||
});
|
||||
|
||||
expectValidRoom(createdRoom, 'test-room');
|
||||
@ -33,7 +33,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should retrieve a room with custom preferences', async () => {
|
||||
const payload = {
|
||||
roomIdPrefix: 'custom-prefs',
|
||||
roomName: 'custom-prefs',
|
||||
preferences: {
|
||||
recordingPreferences: {
|
||||
enabled: true,
|
||||
@ -55,22 +55,22 @@ describe('Room API Tests', () => {
|
||||
it('should retrieve only specified fields when using fields parameter', async () => {
|
||||
// Create a room
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'field-filtered'
|
||||
roomName: 'field-filtered'
|
||||
});
|
||||
|
||||
// Get the room with field filtering
|
||||
const response = await getRoom(createdRoom.roomId, 'roomId,roomIdPrefix');
|
||||
const response = await getRoom(createdRoom.roomId, 'roomId,roomName');
|
||||
|
||||
// Verify that only the requested fields are returned
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
expectValidRoomWithFields(response.body, ['roomId', 'roomIdPrefix']);
|
||||
expectValidRoomWithFields(response.body, ['roomId', 'roomName']);
|
||||
});
|
||||
|
||||
it('should handle roomId with characters that need sanitization', async () => {
|
||||
// Create a room
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'test-room'
|
||||
roomName: 'test-room'
|
||||
});
|
||||
|
||||
const dirtyRoomId = ' ' + createdRoom.roomId + ' '; // Add spaces that should be trimmed
|
||||
@ -86,7 +86,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
// Create a room with autoDeletionDate
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'deletion-date',
|
||||
roomName: 'deletion-date',
|
||||
autoDeletionDate: validAutoDeletionDate
|
||||
});
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should return a list of rooms', async () => {
|
||||
await createRoom({
|
||||
roomIdPrefix: 'test-room'
|
||||
roomName: 'test-room'
|
||||
});
|
||||
|
||||
const response = await getRooms();
|
||||
@ -41,7 +41,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should return a list of rooms applying fields filter', async () => {
|
||||
await createRoom({
|
||||
roomIdPrefix: 'test-room',
|
||||
roomName: 'test-room',
|
||||
autoDeletionDate: validAutoDeletionDate
|
||||
});
|
||||
|
||||
@ -56,7 +56,7 @@ describe('Room API Tests', () => {
|
||||
it('should return a list of rooms with pagination', async () => {
|
||||
const promises = [0, 1, 2, 3, 4, 5].map((i) => {
|
||||
return createRoom({
|
||||
roomIdPrefix: `test-room-${i}`,
|
||||
roomName: `test-room-${i}`,
|
||||
autoDeletionDate: validAutoDeletionDate
|
||||
});
|
||||
});
|
||||
|
||||
@ -32,7 +32,7 @@ describe('Room API Tests', () => {
|
||||
it('should successfully update room preferences', async () => {
|
||||
const sendSignalSpy = jest.spyOn(frontendEventService as any, 'sendSignal');
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'update-test',
|
||||
roomName: 'update-test',
|
||||
preferences: {
|
||||
recordingPreferences: {
|
||||
enabled: true,
|
||||
@ -81,7 +81,7 @@ describe('Room API Tests', () => {
|
||||
it('should allow partial preference updates', async () => {
|
||||
// Create a room first with all preferences enabled
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'partial-update',
|
||||
roomName: 'partial-update',
|
||||
preferences: {
|
||||
recordingPreferences: {
|
||||
enabled: true,
|
||||
@ -118,7 +118,7 @@ describe('Room API Tests', () => {
|
||||
describe('Update Room Validation failures', () => {
|
||||
it('should fail when preferences have incorrect structure', async () => {
|
||||
const { roomId } = await createRoom({
|
||||
roomIdPrefix: 'validation-test'
|
||||
roomName: 'validation-test'
|
||||
});
|
||||
|
||||
// Invalid preferences (missing required fields)
|
||||
@ -139,7 +139,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should fail when preferences have incorrect types', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'type-test'
|
||||
roomName: 'type-test'
|
||||
});
|
||||
|
||||
// Invalid preferences (wrong types)
|
||||
@ -161,7 +161,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should fail when preferences are missing required properties', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'missing-props'
|
||||
roomName: 'missing-props'
|
||||
});
|
||||
|
||||
const emptyPreferences = {};
|
||||
@ -174,7 +174,7 @@ describe('Room API Tests', () => {
|
||||
|
||||
it('should fail when recording is enabled but allowAccessTo is missing', async () => {
|
||||
const createdRoom = await createRoom({
|
||||
roomIdPrefix: 'missing-access'
|
||||
roomName: 'missing-access'
|
||||
});
|
||||
const invalidPreferences = {
|
||||
recordingPreferences: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user