diff --git a/meet-ce/backend/tests/helpers/test-scenarios.ts b/meet-ce/backend/tests/helpers/test-scenarios.ts index 85d8f302..6d504d36 100644 --- a/meet-ce/backend/tests/helpers/test-scenarios.ts +++ b/meet-ce/backend/tests/helpers/test-scenarios.ts @@ -1,14 +1,26 @@ -import { MeetRoomConfig } from '@openvidu-meet/typings'; +import { + MeetRoomConfig, + MeetRoomMember, + MeetRoomMemberOptions, + MeetRoomMemberRole, + MeetUser, + MeetUserOptions, + MeetUserRole +} from '@openvidu-meet/typings'; import express, { Request, Response } from 'express'; import http from 'http'; import { StringValue } from 'ms'; import { MeetRoomHelper } from '../../src/helpers/room.helper'; -import { RoomData, TestContext } from '../interfaces/scenarios'; +import { RoomData, RoomMemberData, RoomTestUsers, TestContext, TestUsers, UserData } from '../interfaces/scenarios'; import { expectValidStartRecordingResponse } from './assertion-helpers'; import { + changePasswordAfterFirstLogin, createRoom, + createRoomMember, + createUser, generateRoomMemberToken, joinFakeParticipant, + loginUser, sleep, startRecording, stopRecording @@ -27,12 +39,16 @@ let mockWebhookServer: http.Server; export const setupSingleRoom = async ( withParticipant = false, roomName = 'TEST_ROOM', - config?: Partial + config?: Partial, + accessToken?: string ): Promise => { - const room = await createRoom({ - roomName, - config - }); + const room = await createRoom( + { + roomName, + config + }, + accessToken + ); // Extract the room secrets and generate room member tokens const { moderatorSecret, speakerSecret } = MeetRoomHelper.extractSecretsFromRoom(room); @@ -202,3 +218,154 @@ export const stopWebhookServer = async (): Promise => { }); } }; + +/** + * Creates a registered user with the specified role and returns UserData. + * + * @param userOptions Options for creating the user + * @returns UserData with user info and access token + */ +export const setupUser = async (userOptions: MeetUserOptions): Promise => { + // Create the user + const createResponse = await createUser(userOptions); + expect(createResponse.status).toBe(201); + const user = createResponse.body as MeetUser; + + // Login to get temporal access token for changing password + const accessTokenTmp = await loginUser(userOptions.userId, userOptions.password); + + // Change password and get final access token + const newPassword = userOptions.password + '_2'; + const accessToken = await changePasswordAfterFirstLogin(userOptions.password, newPassword, accessTokenTmp); + + return { + user, + password: newPassword, + accessToken + }; +}; + +/** + * Creates a collection of basic test users with different roles. + * + * @returns TestUsers with created users + */ +export const setupTestUsers = async (): Promise => { + const timestamp = String(Date.now()).slice(-6); // Use last 6 digits to keep userId under 20 chars + + const [admin, user, roomMember] = await Promise.all([ + // Create admin user + setupUser({ + userId: `adm_${timestamp}`, + name: 'Admin', + password: 'admin_pass', + role: MeetUserRole.ADMIN + }), + // Create regular user + setupUser({ + userId: `usr_${timestamp}`, + name: 'User', + password: 'user_pass', + role: MeetUserRole.USER + }), + // Create room member user + setupUser({ + userId: `rmb_${timestamp}`, + name: 'Room Member', + password: 'room_member_pass', + role: MeetUserRole.ROOM_MEMBER + }) + ]); + + return { + admin, + user, + roomMember + }; +}; + +/** + * Creates a room member for a specific room and returns RoomMemberData. + * + * @param roomId The ID of the room + * @param memberOptions Options for creating the room member + * @returns RoomMemberData with member info and authentication token + */ +export const setupRoomMember = async ( + roomId: string, + memberOptions: MeetRoomMemberOptions +): Promise => { + // Create the room member + const createResponse = await createRoomMember(roomId, memberOptions); + expect(createResponse.status).toBe(201); + const member = createResponse.body as MeetRoomMember; + + // Generate room member token for this member + const secret = member.memberId.startsWith('ext-') ? member.memberId : undefined; + const memberToken = await generateRoomMemberToken(roomId, { + secret, + joinMeeting: false + }); + + return { + member, + memberToken + }; +}; + +/** + * Sets up a room along with a comprehensive set of test users covering all authentication and permission scenarios. + * + * @returns RoomData including the created room and associated test users. + */ +export const setupRoomWithTestUsers = async (): Promise => { + const timestamp = String(Date.now()).slice(-6); // Use last 6 digits to keep userId under 20 chars + + const [userOwner, userMember, roomMember] = await Promise.all([ + // Create user who is the owner of the room + setupUser({ + userId: `usr_own_${timestamp}`, + name: 'User Owner', + password: 'owner_pass', + role: MeetUserRole.USER + }), + // Create user who is a member of the room + setupUser({ + userId: `usr_mem_${timestamp}`, + name: 'User Member', + password: 'member_pass', + role: MeetUserRole.USER + }), + // Create room member user who is a member of the room + setupUser({ + userId: `rmb_${timestamp}`, + name: 'Room Member', + password: 'room_member_pass', + role: MeetUserRole.ROOM_MEMBER + }) + ]); + + // Create room using the owner user access token + const roomData = await setupSingleRoom(false, `Test Room`, undefined, userOwner.accessToken); + const roomId = roomData.room.roomId; + + // Add userMember and roomMember as room members + await Promise.all([ + createRoomMember(roomId, { + userId: userMember.user.userId, + baseRole: MeetRoomMemberRole.MODERATOR + }), + createRoomMember(roomId, { + userId: roomMember.user.userId, + baseRole: MeetRoomMemberRole.SPEAKER + }) + ]); + + const testUsers: RoomTestUsers = { + userOwner, + userMember, + roomMember + }; + roomData.users = testUsers; + return roomData; +}; diff --git a/meet-ce/backend/tests/interfaces/scenarios.ts b/meet-ce/backend/tests/interfaces/scenarios.ts index 72368bf6..1bc23957 100644 --- a/meet-ce/backend/tests/interfaces/scenarios.ts +++ b/meet-ce/backend/tests/interfaces/scenarios.ts @@ -1,4 +1,4 @@ -import { MeetRoom } from '@openvidu-meet/typings'; +import { MeetRoom, MeetRoomMember, MeetUser } from '@openvidu-meet/typings'; export interface RoomData { room: MeetRoom; @@ -7,10 +7,52 @@ export interface RoomData { speakerSecret: string; speakerToken: string; recordingId?: string; + users?: RoomTestUsers; } export interface TestContext { rooms: RoomData[]; getRoomByIndex(index: number): RoomData | undefined; getLastRoom(): RoomData | undefined; -} \ No newline at end of file +} + +/** + * Represents a registered user with their access token for testing purposes. + */ +export interface UserData { + user: MeetUser; + password: string; + accessToken: string; +} + +/** + * Represents a room member along with their authentication token for testing purposes. + */ +export interface RoomMemberData { + member: MeetRoomMember; + memberToken: string; +} + +/** + * Collection of basic test users with different roles for authentication and permission scenarios. + */ +export interface TestUsers { + admin: UserData; + user: UserData; + roomMember: UserData; +} + +/** + * Collection of test users specific to a room scenario. + * Includes the room owner, a regular member, and a room member. + */ +export interface RoomTestUsers { + /** User with USER role who is the owner of the room */ + userOwner: UserData; + + /** User with USER role who is a member of the room (not owner) */ + userMember: UserData; + + /** User with ROOM_MEMBER role who is a member of the room */ + roomMember: UserData; +}