tests: refactor API tests to reflect backend code changes

- Updated the `generateRoomMemberToken` function to use `joinMeeting` instead of `grantJoinMeetingPermission` for clarity.
- Changed test descriptions to reflect the new parameter names and improved readability.
- Removed unnecessary imports and cleaned up tests related to recording access configurations.
- Updated validation error messages for better clarity in the API responses.
- Refactored security configuration tests to align with the new authentication structure.
- Removed deprecated tests for room member roles.
- Adjusted user profile tests to reflect changes in the response structure.
This commit is contained in:
juancarmore 2026-01-21 19:42:18 +01:00
parent 2bc1d02620
commit b2488544e3
20 changed files with 220 additions and 537 deletions

View File

@ -1,18 +1,17 @@
import { expect } from '@jest/globals';
import {
LiveKitPermissions,
MeetingEndAction,
MeetRecordingAccess,
MeetRecordingInfo,
MeetRecordingLayout,
MeetRecordingStatus,
MeetRoom,
MeetRoomAutoDeletionPolicy,
MeetRoomConfig,
MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings,
MeetRoomMemberPermissions,
MeetRoomMemberRole,
MeetRoomStatus
MeetRoomStatus,
TrackSource
} from '@openvidu-meet/typings';
import { Response } from 'supertest';
import { container } from '../../src/config/dependency-injector.config';
@ -136,16 +135,12 @@ export const expectValidRoom = (
expect(room.autoDeletionDate).toBe(autoDeletionDate);
} else {
expect(room.autoDeletionDate).toBeUndefined();
expect(room.autoDeletionPolicy).toBeUndefined();
}
if (autoDeletionPolicy !== undefined) {
expect(room.autoDeletionPolicy).toBeDefined();
expect(room.autoDeletionPolicy).toEqual(autoDeletionPolicy);
} else {
expect(room.autoDeletionPolicy).toEqual({
withMeeting: MeetRoomDeletionPolicyWithMeeting.WHEN_MEETING_ENDS,
withRecordings: MeetRoomDeletionPolicyWithRecordings.CLOSE
});
}
expect(room.config).toBeDefined();
@ -156,8 +151,7 @@ export const expectValidRoom = (
expect(room.config).toEqual({
recording: {
enabled: true,
layout: MeetRecordingLayout.GRID,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.GRID
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -165,10 +159,21 @@ export const expectValidRoom = (
});
}
expect(room.moderatorUrl).toBeDefined();
expect(room.speakerUrl).toBeDefined();
expect(room.moderatorUrl).toContain(room.roomId);
expect(room.speakerUrl).toContain(room.roomId);
expect(room.owner).toBeDefined();
expect(room.roles).toBeDefined();
expect(room.anonymous).toBeDefined();
expect(room.anonymous.moderator).toBeDefined();
expect(room.anonymous.speaker).toBeDefined();
expect(room.anonymous.moderator.enabled).toBeDefined();
expect(room.anonymous.speaker.enabled).toBeDefined();
expect(room.anonymous.moderator.accessUrl).toBeDefined();
expect(room.anonymous.speaker.accessUrl).toBeDefined();
expect(room.anonymous.moderator.accessUrl).toContain(room.roomId);
expect(room.anonymous.speaker.accessUrl).toContain(room.roomId);
expect(room.accessUrl).toBeDefined();
expect(room.accessUrl).toContain(room.roomId);
expect(room.status).toBeDefined();
expect(room.status).toEqual(status || MeetRoomStatus.OPEN);
@ -518,90 +523,13 @@ export const expectValidGetRecordingUrlResponse = (response: Response, recording
expect(parsedUrl.searchParams.get('secret')).toBeDefined();
};
export const expectValidRoomMemberRolesAndPermissionsResponse = (response: Response, roomId: string) => {
expect(response.status).toBe(200);
expect(response.body).toEqual(
expect.arrayContaining([
{
role: MeetRoomMemberRole.MODERATOR,
permissions: getPermissions(roomId, MeetRoomMemberRole.MODERATOR, true, true)
},
{
role: MeetRoomMemberRole.SPEAKER,
permissions: getPermissions(roomId, MeetRoomMemberRole.SPEAKER, true, false)
}
])
);
};
export const expectValidRoomMemberRoleAndPermissionsResponse = (
response: Response,
roomId: string,
role: MeetRoomMemberRole
) => {
expect(response.status).toBe(200);
expect(response.body).toEqual({
role: role,
permissions: getPermissions(roomId, role, true, role === MeetRoomMemberRole.MODERATOR)
});
};
export const getPermissions = (
roomId: string,
role: MeetRoomMemberRole,
canRetrieveRecordings: boolean,
canDeleteRecordings: boolean,
addJoinPermission = true
): MeetRoomMemberPermissions => {
switch (role) {
case MeetRoomMemberRole.MODERATOR:
return {
livekit: {
roomJoin: addJoinPermission,
room: roomId,
canPublish: true,
canSubscribe: true,
canPublishData: true,
canUpdateOwnMetadata: true
},
meet: {
canRecord: true,
canRetrieveRecordings,
canDeleteRecordings,
canChat: true,
canChangeVirtualBackground: true
}
};
case MeetRoomMemberRole.SPEAKER:
return {
livekit: {
roomJoin: addJoinPermission,
room: roomId,
canPublish: true,
canSubscribe: true,
canPublishData: true,
canUpdateOwnMetadata: true
},
meet: {
canRecord: false,
canRetrieveRecordings,
canDeleteRecordings,
canChat: true,
canChangeVirtualBackground: true
}
};
}
};
export const expectValidRoomMemberTokenResponse = (
response: Response,
roomId: string,
role: MeetRoomMemberRole,
addJoinPermission = false,
baseRole: MeetRoomMemberRole,
joinMeeting = false,
participantName?: string,
participantIdentityPrefix?: string,
canRetrieveRecordings?: boolean,
canDeleteRecordings?: boolean
participantIdentityPrefix?: string
) => {
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('token');
@ -609,11 +537,7 @@ export const expectValidRoomMemberTokenResponse = (
const token = response.body.token;
const decodedToken = decodeJWTToken(token);
canRetrieveRecordings = canRetrieveRecordings ?? true;
canDeleteRecordings = canDeleteRecordings ?? role === MeetRoomMemberRole.MODERATOR;
const permissions = getPermissions(roomId, role, canRetrieveRecordings, canDeleteRecordings, addJoinPermission);
if (addJoinPermission) {
if (joinMeeting) {
expect(participantName).toBeDefined();
expect(decodedToken).toHaveProperty('name', participantName);
expect(decodedToken).toHaveProperty('sub');
@ -621,17 +545,88 @@ export const expectValidRoomMemberTokenResponse = (
if (participantIdentityPrefix) {
expect(decodedToken.sub?.startsWith(participantIdentityPrefix)).toBe(true);
}
// const livekitPermissions = getLiveKitPermissions(roomId, getPermissions(baseRole));
expect(decodedToken).toHaveProperty('video');
} else {
expect(decodedToken).not.toHaveProperty('name');
expect(decodedToken).not.toHaveProperty('sub');
expect(decodedToken).not.toHaveProperty('video');
}
expect(decodedToken).toHaveProperty('video', permissions.livekit);
expect(decodedToken).toHaveProperty('metadata');
const metadata = JSON.parse(decodedToken.metadata || '{}');
expect(metadata).toHaveProperty('livekitUrl');
expect(metadata).toHaveProperty('role', role);
expect(metadata).toHaveProperty('permissions', permissions.meet);
expect(metadata).toHaveProperty('baseRole', baseRole);
const permissions = getPermissions(baseRole);
expect(metadata).toHaveProperty('effectivePermissions', permissions);
};
export const getPermissions = (role: MeetRoomMemberRole): MeetRoomMemberPermissions => {
switch (role) {
case MeetRoomMemberRole.MODERATOR:
return {
canRecord: true,
canRetrieveRecordings: true,
canDeleteRecordings: true,
canJoinMeeting: true,
canShareAccessLinks: true,
canMakeModerator: true,
canKickParticipants: true,
canEndMeeting: true,
canPublishVideo: true,
canPublishAudio: true,
canShareScreen: true,
canReadChat: true,
canWriteChat: true,
canChangeVirtualBackground: true
};
case MeetRoomMemberRole.SPEAKER:
return {
canRecord: false,
canRetrieveRecordings: true,
canDeleteRecordings: false,
canJoinMeeting: true,
canShareAccessLinks: false,
canMakeModerator: false,
canKickParticipants: false,
canEndMeeting: false,
canPublishVideo: true,
canPublishAudio: true,
canShareScreen: true,
canReadChat: true,
canWriteChat: true,
canChangeVirtualBackground: true
};
}
};
const getLiveKitPermissions = (roomId: string, permissions: MeetRoomMemberPermissions): LiveKitPermissions => {
const canPublishSources: TrackSource[] = [];
if (permissions.canPublishAudio) {
canPublishSources.push(TrackSource.MICROPHONE);
}
if (permissions.canPublishVideo) {
canPublishSources.push(TrackSource.CAMERA);
}
if (permissions.canShareScreen) {
canPublishSources.push(TrackSource.SCREEN_SHARE);
canPublishSources.push(TrackSource.SCREEN_SHARE_AUDIO);
}
const livekitPermissions: LiveKitPermissions = {
room: roomId,
roomJoin: true,
canPublish: permissions.canPublishAudio || permissions.canPublishVideo || permissions.canShareScreen,
canPublishSources,
canSubscribe: true,
canPublishData: true,
canUpdateOwnMetadata: true
};
return livekitPermissions;
};
const decodeJWTToken = (token: string) => {

View File

@ -1,8 +1,6 @@
import { expect } from '@jest/globals';
import {
AuthMode,
MeetAppearanceConfig,
MeetRecordingAccess,
MeetRecordingInfo,
MeetRecordingStatus,
MeetRoom,
@ -30,13 +28,6 @@ import { GlobalConfigService } from '../../src/services/global-config.service.js
import { RecordingService } from '../../src/services/recording.service.js';
import { RoomScheduledTasksService } from '../../src/services/room-scheduled-tasks.service.js';
const CREDENTIALS = {
admin: {
username: MEET_ENV.INITIAL_ADMIN_USER,
password: MEET_ENV.INITIAL_ADMIN_PASSWORD
}
};
let app: Express;
const fakeParticipantsProcesses = new Map<string, ChildProcess>();
@ -58,7 +49,7 @@ export const startTestServer = async (): Promise<Express> => {
export const generateApiKey = async (): Promise<string> => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
@ -71,7 +62,7 @@ export const generateApiKey = async (): Promise<string> => {
export const getApiKeys = async () => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
@ -82,7 +73,7 @@ export const getApiKeys = async () => {
export const deleteApiKeys = async () => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.delete(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/api-keys`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
@ -115,7 +106,7 @@ export const getRoomsAppearanceConfig = async () => {
export const updateRoomsAppearanceConfig = async (config: { appearance: MeetAppearanceConfig }) => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/rooms/appearance`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
@ -126,7 +117,7 @@ export const updateRoomsAppearanceConfig = async (config: { appearance: MeetAppe
export const getWebbhookConfig = async () => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/webhooks`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
@ -137,7 +128,7 @@ export const getWebbhookConfig = async () => {
export const updateWebbhookConfig = async (config: WebhookConfig) => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/webhooks`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
@ -165,7 +156,7 @@ export const getSecurityConfig = async () => {
export const updateSecurityConfig = async (config: SecurityConfig) => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.put(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/security`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
@ -173,17 +164,6 @@ export const updateSecurityConfig = async (config: SecurityConfig) => {
return response;
};
export const changeSecurityConfig = async (authMode: AuthMode) => {
// Get current config to avoid overwriting other properties
let response = await getSecurityConfig();
expect(response.status).toBe(200);
const currentConfig = response.body;
currentConfig.authentication.authModeToAccessRoom = authMode;
response = await updateSecurityConfig(currentConfig);
expect(response.status).toBe(200);
};
export const restoreDefaultGlobalConfig = async () => {
const configService = container.get(GlobalConfigService);
const defaultGlobalConfig = configService['getDefaultConfig']();
@ -191,25 +171,28 @@ export const restoreDefaultGlobalConfig = async () => {
};
/**
* Logs in a user and returns the access token in the format "Bearer <token>"
* Logs in admin user and returns the access token in the format "Bearer <token>"
*/
export const loginUser = async (): Promise<string> => {
export const loginAdminUser = async (): Promise<string> => {
checkAppIsRunning();
const response = await request(app)
.post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/auth/login`)
.send(CREDENTIALS.admin)
.send({
username: MEET_ENV.INITIAL_ADMIN_USER,
password: MEET_ENV.INITIAL_ADMIN_PASSWORD
})
.expect(200);
expect(response.body).toHaveProperty('accessToken');
return `Bearer ${response.body.accessToken}`;
};
export const getProfile = async (accessToken: string) => {
export const getMe = async (accessToken: string) => {
checkAppIsRunning();
return await request(app)
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/profile`)
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/users/me`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)
.send();
};
@ -284,16 +267,6 @@ export const updateRoomConfig = async (roomId: string, config: Partial<MeetRoomC
.send({ config });
};
export const updateRecordingAccessConfigInRoom = async (roomId: string, recordingAccess: MeetRecordingAccess) => {
const response = await updateRoomConfig(roomId, {
recording: {
enabled: true,
allowAccessTo: recordingAccess
}
});
expect(response.status).toBe(200);
};
export const updateRoomStatus = async (roomId: string, status: MeetRoomStatus) => {
checkAppIsRunning();
@ -368,14 +341,14 @@ export const runExpiredRoomsGC = async () => {
* Runs the inconsistent rooms garbage collector.
*
* This function retrieves the RoomScheduledTasksService from the dependency injection container
* and calls its checkInconsistentRooms method to clean up inconsistent rooms.
* and calls its validateRoomsStatusGC method to clean up inconsistent rooms.
* It then waits for 1 second before completing.
*/
export const executeRoomStatusValidationGC = async () => {
checkAppIsRunning();
const roomTaskScheduler = container.get(RoomScheduledTasksService);
await (roomTaskScheduler as any)['validateRoomsStatusGC']();
await (roomTaskScheduler)['validateRoomsStatusGC']();
await sleep('1s');
};
@ -386,33 +359,11 @@ export const runReleaseActiveRecordingLock = async (roomId: string) => {
await recordingService.releaseRecordingLockIfNoEgress(roomId);
};
export const getRoomMemberRoles = async (roomId: string) => {
checkAppIsRunning();
const response = await request(app)
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/roles`)
.send();
return response;
};
export const getRoomMemberRoleBySecret = async (roomId: string, secret: string) => {
checkAppIsRunning();
const response = await request(app)
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/roles/${secret}`)
.send();
return response;
};
export const generateRoomMemberTokenRequest = async (roomId: string, tokenOptions: MeetRoomMemberTokenOptions) => {
checkAppIsRunning();
// Disable authentication to generate the token
await changeSecurityConfig(AuthMode.NONE);
// Generate the room member token
const response = await request(app)
.post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/token`)
.post(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/rooms/${roomId}/members/token`)
.send(tokenOptions);
return response;
};
@ -760,7 +711,7 @@ export const deleteAllRecordings = async () => {
export const getAnalytics = async () => {
checkAppIsRunning();
const accessToken = await loginUser();
const accessToken = await loginAdminUser();
const response = await request(app)
.get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/analytics`)
.set(INTERNAL_CONFIG.ACCESS_TOKEN_HEADER, accessToken)

View File

@ -37,8 +37,8 @@ export const setupSingleRoom = async (
// Extract the room secrets and generate room member tokens
const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(room);
const [moderatorToken, speakerToken] = await Promise.all([
generateRoomMemberToken(room.roomId, { secret: moderatorSecret, grantJoinMeetingPermission: false }),
generateRoomMemberToken(room.roomId, { secret: speakerSecret, grantJoinMeetingPermission: false })
generateRoomMemberToken(room.roomId, { secret: moderatorSecret, joinMeeting: false }),
generateRoomMemberToken(room.roomId, { secret: speakerSecret, joinMeeting: false })
]);
// Join participant if needed

View File

@ -5,7 +5,7 @@ import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js';
import {
generateApiKey,
getApiKeys,
loginUser,
loginAdminUser,
restoreDefaultApiKeys,
startTestServer
} from '../../../helpers/request-helpers.js';
@ -18,7 +18,7 @@ describe('API Keys API Tests', () => {
beforeAll(async () => {
app = await startTestServer();
adminAccessToken = await loginUser();
adminAccessToken = await loginAdminUser();
});
afterAll(async () => {

View File

@ -15,7 +15,7 @@ describe('Authentication API Tests', () => {
});
describe('Login Tests', () => {
it('should successfully login with valid credentials', async () => {
it('should successfully login with valid root admin credentials', async () => {
const response = await request(app)
.post(`${AUTH_PATH}/login`)
.send({

View File

@ -14,7 +14,7 @@ describe('Authentication API Tests', () => {
});
describe('Refresh Token Tests', () => {
it('should successfully refresh token with valid refresh token', async () => {
it('should successfully refresh access token with valid refresh token', async () => {
// First, login to get a valid refresh token
const loginResponse = await request(app)
.post(`${AUTH_PATH}/login`)

View File

@ -1,5 +1,5 @@
import { afterEach, beforeAll, describe, expect, it } from '@jest/globals';
import { AuthMode, AuthType, SecurityConfig } from '@openvidu-meet/typings';
import { SecurityConfig } from '@openvidu-meet/typings';
import { expectValidationError } from '../../../helpers/assertion-helpers.js';
import {
getSecurityConfig,
@ -19,12 +19,10 @@ describe('Security Config API Tests', () => {
describe('Update security config', () => {
it('should update security config with valid complete data', async () => {
const validConfig = {
const validConfig: SecurityConfig = {
authentication: {
authMethod: {
type: AuthType.SINGLE_USER
},
authModeToAccessRoom: AuthMode.ALL_USERS
allowUserCreation: true,
oauthProviders: []
}
};
let response = await updateSecurityConfig(validConfig);
@ -39,75 +37,57 @@ describe('Security Config API Tests', () => {
});
describe('Update security config validation', () => {
it('should reject when authModeToAccessRoom is not a valid enum value', async () => {
it('should reject when allowUserCreation is not a boolean', async () => {
const response = await updateSecurityConfig({
authentication: {
authMethod: {
type: AuthType.SINGLE_USER
},
authModeToAccessRoom: 'invalid'
allowUserCreation: 'invalid'
}
} as unknown as SecurityConfig);
expectValidationError(
response,
'authentication.authModeToAccessRoom',
"Invalid enum value. Expected 'none' | 'moderators_only' | 'all_users', received 'invalid'"
);
expectValidationError(response, 'authentication.allowUserCreation', 'Expected boolean, received string');
});
it('should reject when authType is not a valid enum value', async () => {
it('should reject when oauthProviders is not an array', async () => {
const response = await updateSecurityConfig({
authentication: {
authMethod: {
type: 'invalid'
},
authModeToAccessRoom: AuthMode.ALL_USERS
allowUserCreation: true,
oauthProviders: 'invalid'
}
} as unknown as SecurityConfig);
expectValidationError(
response,
'authentication.authMethod.type',
"Invalid enum value. Expected 'single_user', received 'invalid'"
);
expectValidationError(response, 'authentication.oauthProviders', 'Expected array, received string');
});
it('should reject when authModeToAccessRoom or authMethod are not provided', async () => {
let response = await updateSecurityConfig({
it('should reject when allowUserCreation is not provided', async () => {
const response = await updateSecurityConfig({
authentication: {
authModeToAccessRoom: AuthMode.NONE
oauthProviders: []
}
} as unknown as SecurityConfig);
expectValidationError(response, 'authentication.authMethod', 'Required');
expectValidationError(response, 'authentication.allowUserCreation', 'Required');
});
response = await updateSecurityConfig({
it('should reject when oauthProviders is not provided', async () => {
const response = await updateSecurityConfig({
authentication: {
authMethod: {
type: AuthType.SINGLE_USER
}
allowUserCreation: true
}
} as unknown as SecurityConfig);
expectValidationError(response, 'authentication.authModeToAccessRoom', 'Required');
} as SecurityConfig);
expectValidationError(response, 'authentication.oauthProviders', 'Required');
});
it('should reject when authentication is not an object', async () => {
const response = await updateSecurityConfig({
authentication: 'invalid'
} as unknown as SecurityConfig);
expectValidationError(response, 'authentication', 'Expected object, received string');
});
});
describe('Get security config', () => {
it('should return security config when authenticated as admin', async () => {
const defaultConfig = {
const defaultConfig: SecurityConfig = {
authentication: {
authMethod: {
type: AuthType.SINGLE_USER
},
authModeToAccessRoom: AuthMode.NONE
allowUserCreation: true,
oauthProviders: []
}
};

View File

@ -33,11 +33,12 @@ describe('Meetings API Tests', () => {
});
describe('Update Participant Tests', () => {
const setParticipantMetadata = async (roomId: string, role: MeetRoomMemberRole) => {
const setParticipantMetadata = async (roomId: string, baseRole: MeetRoomMemberRole) => {
const metadata: MeetRoomMemberTokenMetadata = {
livekitUrl: MEET_ENV.LIVEKIT_URL,
role,
permissions: getPermissions(roomId, role, true, true).meet
roomId,
baseRole,
effectivePermissions: getPermissions(baseRole)
};
await updateParticipantMetadata(roomId, participantIdentity, metadata);
};
@ -65,7 +66,10 @@ describe('Meetings API Tests', () => {
expect(participant).toBeDefined();
expect(participant).toHaveProperty('metadata');
const metadata = JSON.parse(participant.metadata || '{}');
expect(metadata).toHaveProperty('role', MeetRoomMemberRole.MODERATOR);
expect(metadata).toHaveProperty('roomId', roomData.room.roomId);
expect(metadata).toHaveProperty('baseRole', MeetRoomMemberRole.MODERATOR);
const permissions = getPermissions(MeetRoomMemberRole.MODERATOR);
expect(metadata).toHaveProperty('effectivePermissions', permissions);
// Verify sendSignal method has been called twice
expect(sendSignalSpy).toHaveBeenCalledTimes(2);
@ -119,7 +123,10 @@ describe('Meetings API Tests', () => {
expect(participant).toBeDefined();
expect(participant).toHaveProperty('metadata');
const metadata = JSON.parse(participant.metadata || '{}');
expect(metadata).toHaveProperty('role', MeetRoomMemberRole.SPEAKER);
expect(metadata).toHaveProperty('roomId', roomData.room.roomId);
expect(metadata).toHaveProperty('baseRole', MeetRoomMemberRole.SPEAKER);
const permissions = getPermissions(MeetRoomMemberRole.SPEAKER);
expect(metadata).toHaveProperty('effectivePermissions', permissions);
});
it('should fail with 404 if participant does not exist', async () => {

View File

@ -164,7 +164,7 @@ describe('Recording API Tests', () => {
it('should handle empty recordingIds array gracefully', async () => {
const response = await bulkDeleteRecordings([]);
expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item');
expectValidationError(response, 'recordingIds', 'At least one recordingId is required');
});
it('should reject a CSV string with invalid format', async () => {
@ -178,7 +178,7 @@ describe('Recording API Tests', () => {
const invalidRecordingIds = ['', ' '];
const response = await bulkDeleteRecordings(invalidRecordingIds);
expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item');
expectValidationError(response, 'recordingIds', 'At least one recordingId is required');
});
it('should reject an array with mixed valid and totally invalid IDs', async () => {

View File

@ -92,7 +92,7 @@ describe('Recording API Tests', () => {
it('should handle empty recordingIds array gracefully', async () => {
const response = await downloadRecordings([], false);
expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item');
expectValidationError(response, 'recordingIds', 'At least one recordingId is required');
});
it('should reject an array with mixed valid and totally invalid IDs', async () => {
@ -106,7 +106,7 @@ describe('Recording API Tests', () => {
const invalidRecordingIds = ['', ' '];
const response = await downloadRecordings(invalidRecordingIds, false);
expectValidationError(response, 'recordingIds', 'recordingIds must contain at least one item');
expectValidationError(response, 'recordingIds', 'At least one recordingId is required');
});
});
});

View File

@ -1,6 +1,5 @@
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';
import {
MeetRecordingAccess,
MeetRecordingLayout,
MeetRoomDeletionPolicyWithMeeting,
MeetRoomDeletionPolicyWithRecordings
@ -61,8 +60,7 @@ describe('Room API Tests', () => {
config: {
recording: {
enabled: false,
layout: MeetRecordingLayout.GRID,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.GRID
},
chat: { enabled: false },
virtualBackground: { enabled: true },
@ -98,8 +96,7 @@ describe('Room API Tests', () => {
const expectedConfig = {
recording: {
enabled: false,
layout: MeetRecordingLayout.GRID, // Default value
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER // Default value
layout: MeetRecordingLayout.GRID // Default value
},
chat: { enabled: true }, // Default value
virtualBackground: { enabled: true }, // Default value
@ -127,8 +124,7 @@ describe('Room API Tests', () => {
const expectedConfig = {
recording: {
enabled: true, // Default value
layout: MeetRecordingLayout.GRID, // Default value
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER // Default value
layout: MeetRecordingLayout.GRID // Default value
},
chat: { enabled: false },
virtualBackground: { enabled: false },
@ -492,8 +488,7 @@ describe('Room API Tests', () => {
autoDeletionDate: validAutoDeletionDate,
config: {
recording: {
enabled: 'yes', // invalid boolean
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: 'yes' // invalid boolean
},
chat: { enabled: true },
virtualBackground: { enabled: true }

View File

@ -1,5 +1,5 @@
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';
import { MeetRecordingAccess, MeetRoom } from '@openvidu-meet/typings';
import { MeetRoom } from '@openvidu-meet/typings';
import { Express } from 'express';
import request from 'supertest';
import { INTERNAL_CONFIG } from '../../../../src/config/internal-config.js';
@ -48,8 +48,7 @@ describe('E2EE Room Configuration Tests', () => {
roomName: 'Test E2EE Enabled',
config: {
recording: {
enabled: true, // This should be automatically disabled
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: true // This should be automatically disabled
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -87,8 +86,7 @@ describe('E2EE Room Configuration Tests', () => {
roomName: 'Test E2EE Update',
config: {
recording: {
enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: true
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -122,8 +120,7 @@ describe('E2EE Room Configuration Tests', () => {
roomName: 'Test Invalid E2EE',
config: {
recording: {
enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: true
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -145,8 +142,7 @@ describe('E2EE Room Configuration Tests', () => {
roomName: 'Test Invalid E2EE Enabled',
config: {
recording: {
enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: true
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -174,8 +170,7 @@ describe('E2EE Room Configuration Tests', () => {
const { status, body } = await updateRoomConfig(room.roomId, {
recording: {
enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: false
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -201,8 +196,7 @@ describe('E2EE Room Configuration Tests', () => {
roomName: 'E2EE Enabled Room',
config: {
recording: {
enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: false
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -214,8 +208,7 @@ describe('E2EE Room Configuration Tests', () => {
roomName: 'E2EE Disabled Room',
config: {
recording: {
enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: true
},
chat: { enabled: true },
virtualBackground: { enabled: true },

View File

@ -1,10 +1,5 @@
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';
import {
MeetRecordingAccess,
MeetRoomMemberRole,
MeetRoomMemberTokenOptions,
MeetRoomStatus
} from '@openvidu-meet/typings';
import { MeetRoomMemberRole, MeetRoomStatus } from '@openvidu-meet/typings';
import { expectValidationError, expectValidRoomMemberTokenResponse } from '../../../helpers/assertion-helpers.js';
import {
deleteAllRooms,
@ -12,7 +7,6 @@ import {
endMeeting,
generateRoomMemberTokenRequest,
startTestServer,
updateRecordingAccessConfigInRoom,
updateRoomStatus
} from '../../../helpers/request-helpers.js';
import { setupSingleRoom } from '../../../helpers/test-scenarios.js';
@ -48,18 +42,18 @@ describe('Room API Tests', () => {
expectValidRoomMemberTokenResponse(response, roomId, MeetRoomMemberRole.SPEAKER);
});
it('should generate a room member token without join meeting permission when not specifying grantJoinMeetingPermission', async () => {
it('should generate a room member token without join meeting permission when not specifying joinMeeting', async () => {
const response = await generateRoomMemberTokenRequest(roomId, {
secret: roomData.moderatorSecret
});
expectValidRoomMemberTokenResponse(response, roomId, MeetRoomMemberRole.MODERATOR, false);
});
it('should generate a room member token with join meeting permission when specifying grantJoinMeetingPermission true and participantName', async () => {
it('should generate a room member token to join meeting when specifying joinMeeting true and participantName', async () => {
const participantName = 'TEST_PARTICIPANT';
const response = await generateRoomMemberTokenRequest(roomId, {
secret: roomData.moderatorSecret,
grantJoinMeetingPermission: true,
joinMeeting: true,
participantName
});
expectValidRoomMemberTokenResponse(
@ -75,13 +69,13 @@ describe('Room API Tests', () => {
await endMeeting(roomId, roomData.moderatorToken);
});
it('should success when when specifying grantJoinMeetingPermission true and participant already exists in the room', async () => {
it('should success when specifying joinMeeting true and participant already exists in the room', async () => {
const participantName = 'TEST_PARTICIPANT';
// Create token for the first participant
let response = await generateRoomMemberTokenRequest(roomId, {
secret: roomData.moderatorSecret,
grantJoinMeetingPermission: true,
joinMeeting: true,
participantName
});
expectValidRoomMemberTokenResponse(
@ -96,7 +90,7 @@ describe('Room API Tests', () => {
// Create token for the second participant with the same name
response = await generateRoomMemberTokenRequest(roomId, {
secret: roomData.moderatorSecret,
grantJoinMeetingPermission: true,
joinMeeting: true,
participantName
});
expectValidRoomMemberTokenResponse(
@ -112,7 +106,7 @@ describe('Room API Tests', () => {
await endMeeting(roomId, roomData.moderatorToken);
});
it('should refresh a room member token with join meeting permission for an existing participant', async () => {
it('should refresh a room member token to join meeting for an existing participant', async () => {
const participantName = 'TEST_PARTICIPANT';
// Create room with initial participant
@ -121,7 +115,7 @@ describe('Room API Tests', () => {
// Refresh token for the participant by specifying participantIdentity
const response = await generateRoomMemberTokenRequest(roomWithParticipant.room.roomId, {
secret: roomWithParticipant.moderatorSecret,
grantJoinMeetingPermission: true,
joinMeeting: true,
participantName,
participantIdentity: participantName
});
@ -135,13 +129,13 @@ describe('Room API Tests', () => {
);
});
it('should fail with 409 when generating a room member token with join meeting permission and room is closed', async () => {
it('should fail with 409 when generating a room member token to join meeting and room is closed', async () => {
// Close the room
await updateRoomStatus(roomId, MeetRoomStatus.CLOSED);
const response = await generateRoomMemberTokenRequest(roomId, {
secret: roomData.moderatorSecret,
grantJoinMeetingPermission: true,
joinMeeting: true,
participantName: 'TEST_PARTICIPANT'
});
expect(response.status).toBe(409);
@ -161,7 +155,7 @@ describe('Room API Tests', () => {
const participantName = 'NON_EXISTENT_PARTICIPANT';
const response = await generateRoomMemberTokenRequest(roomId, {
secret: roomData.moderatorSecret,
grantJoinMeetingPermission: true,
joinMeeting: true,
participantName,
participantIdentity: participantName
});
@ -176,149 +170,21 @@ describe('Room API Tests', () => {
});
});
describe('Generate Room Member Token Recording Permissions Tests', () => {
afterAll(async () => {
// Reset recording access to default for other tests
await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER);
});
it(`should generate a room member token with canRetrieve and canDelete permissions
when using the moderator secret and recording access is admin_moderator_speaker`, async () => {
await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER);
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret });
expectValidRoomMemberTokenResponse(
response,
roomId,
MeetRoomMemberRole.MODERATOR,
false,
undefined,
undefined,
true, // canRetrieveRecordings
true // canDeleteRecordings
);
});
it(`should generate a room member token with canRetrieve permission but not canDelete
when using the speaker secret and recording access is admin_moderator_speaker`, async () => {
await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER);
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret });
expectValidRoomMemberTokenResponse(
response,
roomId,
MeetRoomMemberRole.SPEAKER,
false,
undefined,
undefined,
true, // canRetrieveRecordings
false // canDeleteRecordings
);
});
it(`should generate a room member token with canRetrieve and canDelete permissions
when using the moderator secret and recording access is admin_moderator`, async () => {
await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret });
expectValidRoomMemberTokenResponse(
response,
roomId,
MeetRoomMemberRole.MODERATOR,
false,
undefined,
undefined,
true, // canRetrieveRecordings
true // canDeleteRecordings
);
});
it(`should generate a room member token without any permissions
when using the speaker secret and recording access is admin_moderator`, async () => {
await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN_MODERATOR);
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret });
expectValidRoomMemberTokenResponse(
response,
roomId,
MeetRoomMemberRole.SPEAKER,
false,
undefined,
undefined,
false, // canRetrieveRecordings
false // canDeleteRecordings
);
});
it(`should generate a room member token without any permissions
when using the moderator secret and recording access is admin`, async () => {
await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN);
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.moderatorSecret });
expectValidRoomMemberTokenResponse(
response,
roomId,
MeetRoomMemberRole.MODERATOR,
false,
undefined,
undefined,
false, // canRetrieveRecordings
false // canDeleteRecordings
);
});
it(`should generate a room member token without any permissions
when using the speaker secret and recording access is admin`, async () => {
await updateRecordingAccessConfigInRoom(roomId, MeetRecordingAccess.ADMIN);
const response = await generateRoomMemberTokenRequest(roomId, { secret: roomData.speakerSecret });
expectValidRoomMemberTokenResponse(
response,
roomId,
MeetRoomMemberRole.SPEAKER,
false,
undefined,
undefined,
false, // canRetrieveRecordings
false // canDeleteRecordings
);
});
});
describe('Generate Room Member Token Validation Tests', () => {
it('should fail when secret is not provided', async () => {
const response = await generateRoomMemberTokenRequest(
roomData.room.roomId,
{} as unknown as MeetRoomMemberTokenOptions
);
expectValidationError(response, 'secret', 'Required');
});
it('should fail when secret is empty', async () => {
const response = await generateRoomMemberTokenRequest(roomData.room.roomId, {
secret: ''
});
expectValidationError(response, 'secret', 'Secret is required');
});
it('should fail when grantJoinMeetingPermission is not a boolean', async () => {
it('should fail when joinMeeting is not a boolean', async () => {
const response = await generateRoomMemberTokenRequest(roomData.room.roomId, {
secret: roomData.moderatorSecret,
grantJoinMeetingPermission: 'not-a-boolean' as unknown as boolean
joinMeeting: 'not-a-boolean' as unknown as boolean
});
expectValidationError(response, 'grantJoinMeetingPermission', 'Expected boolean');
expectValidationError(response, 'joinMeeting', 'Expected boolean');
});
it('should fail when grantJoinMeetingPermission is true but participantName is not provided', async () => {
it('should fail when joinMeeting is true but participantName is not provided', async () => {
const response = await generateRoomMemberTokenRequest(roomData.room.roomId, {
secret: roomData.moderatorSecret,
grantJoinMeetingPermission: true
joinMeeting: true
});
expectValidationError(
response,
'participantName',
'participantName is required when grantJoinMeetingPermission is true'
);
expectValidationError(response, 'participantName', 'participantName is required when joinMeeting is true');
});
});
});

View File

@ -1,5 +1,5 @@
import { afterEach, beforeAll, describe, it } from '@jest/globals';
import { MeetRecordingAccess, MeetRecordingLayout } from '@openvidu-meet/typings';
import { MeetRecordingLayout } from '@openvidu-meet/typings';
import { Response } from 'supertest';
import { expectSuccessRoomConfigResponse } from '../../../helpers/assertion-helpers.js';
import { deleteAllRooms, getRoomConfig, startTestServer } from '../../../helpers/request-helpers.js';
@ -9,8 +9,7 @@ describe('Room API Tests', () => {
const DEFAULT_CONFIG = {
recording: {
enabled: true,
layout: MeetRecordingLayout.GRID,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.GRID
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -41,8 +40,7 @@ describe('Room API Tests', () => {
config: {
recording: {
enabled: true,
layout: MeetRecordingLayout.SPEAKER,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.SPEAKER
},
chat: { enabled: true },
virtualBackground: { enabled: false },

View File

@ -1,65 +0,0 @@
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals';
import { MeetRoomMemberRole } from '@openvidu-meet/typings';
import {
expectValidRoomMemberRoleAndPermissionsResponse,
expectValidRoomMemberRolesAndPermissionsResponse
} from '../../../helpers/assertion-helpers.js';
import {
deleteAllRooms,
getRoomMemberRoleBySecret,
getRoomMemberRoles,
startTestServer
} from '../../../helpers/request-helpers.js';
import { setupSingleRoom } from '../../../helpers/test-scenarios.js';
import { RoomData } from '../../../interfaces/scenarios.js';
describe('Room API Tests', () => {
let roomData: RoomData;
beforeAll(async () => {
await startTestServer();
roomData = await setupSingleRoom();
});
afterAll(async () => {
await deleteAllRooms();
});
describe('Get Room Member Roles Tests', () => {
it('should retrieve all roles and associated permissions for a room', async () => {
const response = await getRoomMemberRoles(roomData.room.roomId);
expectValidRoomMemberRolesAndPermissionsResponse(response, roomData.room.roomId);
});
it('should return a 404 error if the room does not exist', async () => {
const response = await getRoomMemberRoles('non-existent-room-id');
expect(response.status).toBe(404);
});
});
describe('Get Room Member Role Tests', () => {
it('should retrieve moderator role and associated permissions for a room with a valid moderator secret', async () => {
const response = await getRoomMemberRoleBySecret(roomData.room.roomId, roomData.moderatorSecret);
expectValidRoomMemberRoleAndPermissionsResponse(
response,
roomData.room.roomId,
MeetRoomMemberRole.MODERATOR
);
});
it('should retrieve speaker role and associated permissions for a room with a valid speaker secret', async () => {
const response = await getRoomMemberRoleBySecret(roomData.room.roomId, roomData.speakerSecret);
expectValidRoomMemberRoleAndPermissionsResponse(response, roomData.room.roomId, MeetRoomMemberRole.SPEAKER);
});
it('should return a 404 error if the room does not exist', async () => {
const response = await getRoomMemberRoleBySecret('non-existent-room-id', roomData.moderatorSecret);
expect(response.status).toBe(404);
});
it('should return a 400 error if the secret is invalid', async () => {
const response = await getRoomMemberRoleBySecret(roomData.room.roomId, 'invalid-secret');
expect(response.status).toBe(400);
});
});
});

View File

@ -1,5 +1,5 @@
import { afterEach, beforeAll, describe, expect, it } from '@jest/globals';
import { MeetRecordingAccess, MeetRecordingLayout } from '@openvidu-meet/typings';
import { MeetRecordingLayout } from '@openvidu-meet/typings';
import ms from 'ms';
import {
expectSuccessRoomResponse,
@ -38,8 +38,7 @@ describe('Room API Tests', () => {
config: {
recording: {
enabled: true,
layout: MeetRecordingLayout.SPEAKER,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.SPEAKER
},
chat: { enabled: true },
virtualBackground: { enabled: false },

View File

@ -1,5 +1,5 @@
import { afterAll, beforeAll, describe, it } from '@jest/globals';
import { MeetRecordingAccess, MeetRecordingLayout } from '@openvidu-meet/typings';
import { MeetRecordingLayout } from '@openvidu-meet/typings';
import { expectValidRoom } from '../../../helpers/assertion-helpers.js';
import { createRoom, deleteAllRooms, startTestServer } from '../../../helpers/request-helpers.js';
@ -27,8 +27,7 @@ describe('Room API Tests', () => {
const expectedConfig = {
recording: {
enabled: true,
layout: MeetRecordingLayout.GRID, // Default value
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.GRID // Default value
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -43,8 +42,7 @@ describe('Room API Tests', () => {
config: {
recording: {
enabled: true,
layout: MeetRecordingLayout.SPEAKER,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.SPEAKER
}
}
};
@ -54,8 +52,7 @@ describe('Room API Tests', () => {
const expectedConfig = {
recording: {
enabled: true,
layout: MeetRecordingLayout.SPEAKER,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.SPEAKER
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -70,8 +67,7 @@ describe('Room API Tests', () => {
config: {
recording: {
enabled: true,
layout: MeetRecordingLayout.SINGLE_SPEAKER,
allowAccessTo: MeetRecordingAccess.ADMIN
layout: MeetRecordingLayout.SINGLE_SPEAKER
}
}
};
@ -81,8 +77,7 @@ describe('Room API Tests', () => {
const expectedConfig = {
recording: {
enabled: true,
layout: MeetRecordingLayout.SINGLE_SPEAKER,
allowAccessTo: MeetRecordingAccess.ADMIN
layout: MeetRecordingLayout.SINGLE_SPEAKER
},
chat: { enabled: true },
virtualBackground: { enabled: true },

View File

@ -1,7 +1,5 @@
import { afterEach, beforeAll, describe, expect, it, jest } from '@jest/globals';
import { MeetRecordingAccess, MeetRecordingLayout, MeetRoomConfig, MeetSignalType } from '@openvidu-meet/typings';
import { container } from '../../../../src/config/dependency-injector.config.js';
import { FrontendEventService } from '../../../../src/services/frontend-event.service.js';
import { afterEach, beforeAll, describe, expect, it } from '@jest/globals';
import { MeetRecordingLayout, MeetRoomConfig } from '@openvidu-meet/typings';
import {
createRoom,
deleteAllRooms,
@ -22,21 +20,12 @@ describe('Room API Tests', () => {
});
describe('Update Room Config Tests', () => {
let frontendEventService: FrontendEventService;
beforeAll(() => {
// Ensure the FrontendEventService is registered
frontendEventService = container.get(FrontendEventService);
});
it('should successfully update room config', async () => {
const sendSignalSpy = jest.spyOn(frontendEventService as any, 'sendSignal');
const createdRoom = await createRoom({
roomName: 'update-test',
config: {
recording: {
enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: true
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -47,8 +36,7 @@ describe('Room API Tests', () => {
// Update the room config
const updatedConfig = {
recording: {
enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN
enabled: false
},
chat: { enabled: false },
virtualBackground: { enabled: false },
@ -56,22 +44,6 @@ describe('Room API Tests', () => {
};
const updateResponse = await updateRoomConfig(createdRoom.roomId, updatedConfig);
// Verify a method of frontend event service is called
expect(sendSignalSpy).toHaveBeenCalledWith(
createdRoom.roomId,
{
roomId: createdRoom.roomId,
config: {
...updatedConfig,
recording: { ...updatedConfig.recording, layout: MeetRecordingLayout.GRID }
},
timestamp: expect.any(Number)
},
{
topic: MeetSignalType.MEET_ROOM_CONFIG_UPDATED
}
);
// Verify update response
expect(updateResponse.status).toBe(200);
expect(updateResponse.body).toHaveProperty('message');
@ -120,8 +92,7 @@ describe('Room API Tests', () => {
const expectedConfig: MeetRoomConfig = {
recording: {
enabled: false,
layout: MeetRecordingLayout.SPEAKER,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
layout: MeetRecordingLayout.SPEAKER
},
chat: { enabled: true },
virtualBackground: { enabled: true },
@ -161,8 +132,7 @@ describe('Room API Tests', () => {
const config = {
recording: {
enabled: false,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: false
},
chat: { enabled: false },
virtualBackground: { enabled: false }
@ -183,8 +153,7 @@ describe('Room API Tests', () => {
// Invalid config (wrong types)
const invalidConfig = {
recording: {
enabled: 'true', // String instead of boolean
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_SPEAKER
enabled: 'true' // String instead of boolean
},
chat: { enabled: false },
virtualBackground: { enabled: false }

View File

@ -1,14 +1,14 @@
import { beforeAll, describe, expect, it } from '@jest/globals';
import { MEET_ENV } from '../../../../src/environment.js';
import { expectValidationError } from '../../../helpers/assertion-helpers.js';
import { changePassword, loginUser, startTestServer } from '../../../helpers/request-helpers.js';
import { changePassword, loginAdminUser, startTestServer } from '../../../helpers/request-helpers.js';
describe('Users API Tests', () => {
let adminAccessToken: string;
beforeAll(async () => {
await startTestServer();
adminAccessToken = await loginUser();
adminAccessToken = await loginAdminUser();
});
describe('Change Password Tests', () => {

View File

@ -1,22 +1,22 @@
import { beforeAll, describe, expect, it } from '@jest/globals';
import { getProfile, loginUser, startTestServer } from '../../../helpers/request-helpers.js';
import { getMe, loginAdminUser, startTestServer } from '../../../helpers/request-helpers.js';
describe('Users API Tests', () => {
let adminAccessToken: string;
beforeAll(async () => {
await startTestServer();
adminAccessToken = await loginUser();
adminAccessToken = await loginAdminUser();
});
describe('Profile Tests', () => {
it('should return 200 and admin profile', async () => {
const response = await getProfile(adminAccessToken);
const response = await getMe(adminAccessToken);
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('username');
expect(response.body.username).toBe('admin');
expect(response.body).toHaveProperty('roles');
expect(response.body.roles).toEqual(expect.arrayContaining(['admin', 'user']));
expect(response.body).toHaveProperty('userId', 'admin');
expect(response.body).toHaveProperty('name', 'Admin');
expect(response.body).toHaveProperty('role', 'admin');
expect(response.body).toHaveProperty('registrationDate');
});
});
});