2024-05-02 19:58:18 +08:00
const { expect } = require ( '@playwright/test' ) ;
2022-11-22 21:44:28 +08:00
const playwright = require ( "playwright" ) ;
2021-11-18 04:07:14 +08:00
const Page = require ( '../core/page' ) ;
const e = require ( '../core/elements' ) ;
2022-06-08 02:52:22 +08:00
const { waitAndClearDefaultPresentationNotification } = require ( '../notifications/util' ) ;
2022-02-04 22:13:42 +08:00
const { sleep } = require ( '../core/helpers' ) ;
2022-09-13 01:10:57 +08:00
const { checkTextContent , checkElementLengthEqualTo } = require ( '../core/util' ) ;
2022-12-08 02:53:56 +08:00
const { checkAvatarIcon , checkIsPresenter , checkMutedUsers } = require ( './util' ) ;
2023-01-11 00:59:08 +08:00
const { getNotesLocator } = require ( '../sharednotes/util' ) ;
2022-03-29 21:53:07 +08:00
const { getSettings } = require ( '../core/settings' ) ;
2023-07-25 05:07:51 +08:00
const { ELEMENT _WAIT _TIME } = require ( '../core/constants' ) ;
2021-11-16 00:42:29 +08:00
class MultiUsers {
2021-12-01 13:35:41 +08:00
constructor ( browser , context ) {
this . browser = browser ;
this . context = context ;
2021-11-16 00:42:29 +08:00
}
2022-06-24 09:38:49 +08:00
async initPages ( page1 , waitAndClearDefaultPresentationNotificationModPage = false ) {
2021-12-01 13:35:41 +08:00
await this . initModPage ( page1 ) ;
2022-06-24 09:38:49 +08:00
if ( waitAndClearDefaultPresentationNotificationModPage ) {
2022-09-13 01:10:57 +08:00
await waitAndClearDefaultPresentationNotification ( this . modPage ) ;
2022-06-24 09:38:49 +08:00
}
2021-12-01 13:35:41 +08:00
await this . initUserPage ( ) ;
}
2021-12-15 01:10:44 +08:00
async initModPage ( page , shouldCloseAudioModal = true , { fullName = 'Moderator' , ... restOptions } = { } ) {
const options = {
... restOptions ,
2022-02-08 02:01:47 +08:00
fullName ,
2021-12-15 01:10:44 +08:00
} ;
2021-12-01 13:35:41 +08:00
this . modPage = new Page ( this . browser , page ) ;
2021-12-15 01:10:44 +08:00
await this . modPage . init ( true , shouldCloseAudioModal , options ) ;
2021-12-01 13:35:41 +08:00
}
2022-02-08 02:01:47 +08:00
async initModPage2 ( shouldCloseAudioModal = true , context = this . context , { fullName = 'Moderator2' , useModMeetingId = true , ... restOptions } = { } ) {
const options = {
... restOptions ,
fullName ,
meetingId : ( useModMeetingId ) ? this . modPage . meetingId : undefined ,
} ;
const page = await context . newPage ( ) ;
this . modPage2 = new Page ( this . browser , page ) ;
await this . modPage2 . init ( true , shouldCloseAudioModal , options ) ;
}
2023-01-13 19:16:49 +08:00
2021-12-15 01:10:44 +08:00
async initUserPage ( shouldCloseAudioModal = true , context = this . context , { fullName = 'Attendee' , useModMeetingId = true , ... restOptions } = { } ) {
const options = {
... restOptions ,
fullName ,
meetingId : ( useModMeetingId ) ? this . modPage . meetingId : undefined ,
} ;
2021-12-10 21:30:29 +08:00
const page = await context . newPage ( ) ;
2021-12-01 13:35:41 +08:00
this . userPage = new Page ( this . browser , page ) ;
2021-12-15 01:10:44 +08:00
await this . userPage . init ( false , shouldCloseAudioModal , options ) ;
2021-11-16 00:42:29 +08:00
}
2022-11-22 21:44:28 +08:00
async initUserPage1 ( shouldCloseAudioModal = true , { fullName = 'Attendee' , useModMeetingId = true , ... restOptions } = { } ) {
const options = {
... restOptions ,
fullName ,
meetingId : ( useModMeetingId ) ? this . modPage . meetingId : undefined ,
} ;
const page = await ( await playwright . chromium . launch ( ) ) . newPage ( ) ;
this . userPage1 = new Page ( this . browser , page ) ;
await this . userPage1 . init ( false , shouldCloseAudioModal , options ) ;
}
2022-01-29 03:52:22 +08:00
async initUserPage2 ( shouldCloseAudioModal = true , context = this . context , { fullName = 'Attendee2' , useModMeetingId = true , ... restOptions } = { } ) {
const options = {
... restOptions ,
fullName ,
meetingId : ( useModMeetingId ) ? this . modPage . meetingId : undefined ,
} ;
const page = await context . newPage ( ) ;
this . userPage2 = new Page ( this . browser , page ) ;
await this . userPage2 . init ( false , shouldCloseAudioModal , options ) ;
}
2021-11-23 05:51:16 +08:00
async userPresence ( ) {
2024-07-31 06:49:02 +08:00
await this . modPage . checkElementCount ( e . currentUser , 1 , 'should contain one current user for the moderator' ) ;
await this . modPage . checkElementCount ( e . userListItem , 1 , 'should contain one user on user list for the moderator' ) ;
await this . userPage . checkElementCount ( e . currentUser , 1 , 'should contain one current user for the attendee' ) ;
await this . userPage . checkElementCount ( e . userListItem , 1 , 'should contain one user on user list for the attendee' ) ;
2021-12-10 21:30:29 +08:00
}
2022-02-08 02:45:42 +08:00
async makePresenter ( ) {
await this . modPage . waitAndClick ( e . userListItem ) ;
await this . modPage . waitAndClick ( e . makePresenter ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . wasRemoved ( e . wbToolbar , 'should not display the whiteboard toolbar for the moderator' ) ;
2022-02-08 02:45:42 +08:00
2024-07-31 06:49:02 +08:00
await this . userPage . hasElement ( e . startScreenSharing , 'should display the start screenshare button for the attendee' ) ;
await this . userPage . hasElement ( e . presentationToolbarWrapper , 'should display the presentation toolbar for the attendee' ) ;
await this . userPage . hasElement ( e . wbToolbar , 'should display the whiteboard toolbar for the attendee' ) ;
await this . userPage . hasElement ( e . actions , 'should display the actions button for the attendee' ) ;
await this . userPage . hasElement ( e . userListItem , 'should display the user list item for the attendee' ) ;
2022-03-02 04:11:45 +08:00
const isPresenter = await checkIsPresenter ( this . userPage ) ;
2024-07-31 06:49:02 +08:00
await expect ( isPresenter , 'should the attende be presenter' ) . toBeTruthy ( ) ;
2022-02-08 02:45:42 +08:00
}
async takePresenter ( ) {
2022-03-02 04:11:45 +08:00
await this . modPage2 . waitAndClick ( e . currentUser ) ;
2022-02-08 02:45:42 +08:00
await this . modPage2 . waitAndClick ( e . takePresenter ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . wasRemoved ( e . wbToolbar , 'should not display the whiteboard toolbar for the moderator' ) ;
2022-02-08 02:45:42 +08:00
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasElement ( e . startScreenSharing , 'should display the start screenshare button for the second moderator' ) ;
await this . modPage2 . hasElement ( e . wbToolbar , 'should display the whiteboard toolbar for the second moderator' ) ;
await this . modPage2 . hasElement ( e . presentationToolbarWrapper , 'should presentation toolbar for the second moderator' ) ;
await this . modPage2 . hasElement ( e . userListItem , 'should display the user list item for the second moderator' ) ;
2022-03-02 04:11:45 +08:00
const isPresenter = await checkIsPresenter ( this . modPage2 ) ;
2024-07-31 06:49:02 +08:00
await expect ( isPresenter , 'should the second moderator to be presenter' ) . toBeTruthy ( ) ;
2022-02-08 02:45:42 +08:00
await this . modPage2 . waitAndClick ( e . actions ) ;
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasElement ( e . managePresentations , 'should display the manage presentations for the second moderator' ) ;
await this . modPage2 . hasElement ( e . polling , 'should display the polling option for the second moderator' ) ;
await this . modPage2 . hasElement ( e . shareExternalVideoBtn , 'should display the share external video button for the second moderator' ) ;
2022-02-08 02:45:42 +08:00
}
2022-02-08 02:01:47 +08:00
async promoteToModerator ( ) {
await checkAvatarIcon ( this . userPage , false ) ;
2024-07-31 06:49:02 +08:00
await this . userPage . wasRemoved ( e . manageUsers , 'should not display the manage users for the attendee' ) ;
2022-02-08 02:01:47 +08:00
await this . modPage . waitAndClick ( e . userListItem ) ;
await this . modPage . waitAndClick ( e . promoteToModerator ) ;
await checkAvatarIcon ( this . userPage ) ;
2024-07-31 06:49:02 +08:00
await this . userPage . hasElement ( e . manageUsers , 'should display the manage users for the attendee' ) ;
2022-02-08 02:01:47 +08:00
}
async demoteToViewer ( ) {
await checkAvatarIcon ( this . modPage2 ) ;
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasElement ( e . manageUsers , 'should display the manage users for the second moderator' ) ;
2022-02-08 02:01:47 +08:00
await this . modPage . waitAndClick ( e . userListItem ) ;
await this . modPage . waitAndClick ( e . demoteToViewer ) ;
await checkAvatarIcon ( this . modPage2 , false ) ;
2024-07-31 06:49:02 +08:00
await this . modPage2 . wasRemoved ( e . manageUsers , 'should not display the manage users for the second moderator' ) ;
2022-02-08 02:01:47 +08:00
}
2022-03-29 21:53:07 +08:00
async raiseAndLowerHand ( ) {
2023-07-25 05:07:51 +08:00
const { reactionsButton } = getSettings ( ) ;
if ( ! reactionsButton ) {
await this . modPage . waitForSelector ( e . whiteboard ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . hasElement ( e . joinAudio , 'should display the join audio button for the moderator' ) ;
await this . modPage . wasRemoved ( e . reactionsButton , 'should not display the reactions button for the moderator' ) ;
2023-07-25 05:07:51 +08:00
return ;
}
2022-03-29 21:53:07 +08:00
2022-07-02 04:55:32 +08:00
await this . initUserPage ( ) ;
2023-07-25 05:07:51 +08:00
await this . userPage . waitAndClick ( e . reactionsButton ) ;
2022-01-20 03:57:13 +08:00
await this . userPage . waitAndClick ( e . raiseHandBtn ) ;
2023-08-23 04:25:50 +08:00
await this . userPage . waitAndClick ( e . reactionsButton ) ;
2022-01-20 03:57:13 +08:00
await this . userPage . hasElement ( e . lowerHandBtn ) ;
2024-07-12 00:59:23 +08:00
await this . modPage . comparingSelectorsBackgroundColor ( e . avatarsWrapperAvatar , ` ${ e . userListItem } div:first-child ` ) ;
2023-07-25 05:07:51 +08:00
await sleep ( 1000 ) ;
2022-01-20 03:57:13 +08:00
await this . userPage . waitAndClick ( e . lowerHandBtn ) ;
2023-08-23 04:25:50 +08:00
await this . userPage . waitAndClick ( e . reactionsButton ) ;
2024-07-31 06:49:02 +08:00
await this . userPage . hasElement ( e . raiseHandBtn , 'should display the raise hand button for the attendee' ) ;
2021-12-10 21:30:29 +08:00
}
2022-02-08 03:22:48 +08:00
2023-02-04 04:04:45 +08:00
async raiseHandRejected ( ) {
2023-07-25 05:07:51 +08:00
const { reactionsButton } = getSettings ( ) ;
if ( ! reactionsButton ) {
await this . modPage . waitForSelector ( e . whiteboard ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . hasElement ( e . joinAudio , 'should display the join audio button for the moderator' ) ;
await this . modPage . wasRemoved ( e . reactionsButton , 'should not display the reactions button for the moderator' ) ;
2023-07-25 05:07:51 +08:00
return
}
2023-02-04 04:04:45 +08:00
await waitAndClearDefaultPresentationNotification ( this . modPage ) ;
await this . initUserPage ( ) ;
2023-07-25 05:07:51 +08:00
await this . userPage . waitAndClick ( e . reactionsButton ) ;
2023-02-04 04:04:45 +08:00
await this . userPage . waitAndClick ( e . raiseHandBtn ) ;
2023-08-23 04:25:50 +08:00
await this . userPage . waitAndClick ( e . reactionsButton ) ;
2024-07-31 06:49:02 +08:00
await this . userPage . hasElement ( e . lowerHandBtn , 'should display the lower hand button for the attendee' ) ;
2023-07-25 05:07:51 +08:00
await this . userPage . press ( 'Escape' ) ;
2024-07-12 00:59:23 +08:00
await this . modPage . comparingSelectorsBackgroundColor ( e . avatarsWrapperAvatar , ` ${ e . userListItem } div:first-child ` ) ;
2023-02-04 04:04:45 +08:00
await this . modPage . waitAndClick ( e . raiseHandRejection ) ;
2023-07-25 05:07:51 +08:00
await this . userPage . waitAndClick ( e . reactionsButton ) ;
2024-07-31 06:49:02 +08:00
await this . userPage . hasElement ( e . raiseHandBtn , 'should display the raise hand button for the attendee' ) ;
2023-02-04 04:04:45 +08:00
}
2022-02-08 03:22:48 +08:00
async toggleUserList ( ) {
2024-07-31 06:49:02 +08:00
await this . modPage . hasElement ( e . chatWelcomeMessageText , 'should display the public chat welcome message for the moderator ' ) ;
await this . modPage . hasElement ( e . chatBox , 'should display the public chat box for the moderator' ) ;
await this . modPage . hasElement ( e . chatButton , 'should display the public chat button for the moderator' ) ;
2022-02-08 03:22:48 +08:00
await this . modPage . waitAndClick ( e . userListToggleBtn ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . wasRemoved ( e . chatWelcomeMessageText , 'should not display the chat welcome message for the moderator' ) ;
await this . modPage . wasRemoved ( e . chatBox , 'should not display the public chat box for the moderator' ) ;
await this . modPage . wasRemoved ( e . chatButton , 'should not display the public chat button for the moderator' ) ;
2022-02-08 03:22:48 +08:00
await this . modPage . waitAndClick ( e . userListToggleBtn ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . wasRemoved ( e . chatWelcomeMessageText , 'should not display the chat welcome message for the moderator' ) ;
await this . modPage . wasRemoved ( e . chatBox , 'should not display the public chat box for the moderator' ) ;
await this . modPage . hasElement ( e . chatButton , 'should display the public chat button for the moderator' ) ;
2022-02-08 03:22:48 +08:00
}
2022-03-21 23:04:43 +08:00
async saveUserNames ( testInfo ) {
await this . modPage . waitAndClick ( e . manageUsers ) ;
2023-02-16 02:41:21 +08:00
const downloadUserNamesListLocator = this . modPage . getLocator ( e . downloadUserNamesList ) ;
const { content } = await this . modPage . handleDownload ( downloadUserNamesListLocator , testInfo ) ;
2022-03-21 23:04:43 +08:00
const dataToCheck = [
this . modPage . username ,
this . userPage . username ,
this . modPage . meetingId ,
] ;
2024-07-31 06:49:02 +08:00
await checkTextContent ( content , dataToCheck , 'should the downloaded content match the user names' ) ;
2022-03-21 23:04:43 +08:00
}
2021-12-10 21:30:29 +08:00
2022-09-13 01:10:57 +08:00
async pinningWebcams ( ) {
await this . modPage . shareWebcam ( ) ;
await this . modPage2 . shareWebcam ( ) ;
await this . userPage . shareWebcam ( ) ;
await this . modPage . page . waitForFunction (
checkElementLengthEqualTo ,
[ e . webcamVideoItem , 3 ] ,
{ timeout : ELEMENT _WAIT _TIME } ,
) ;
// Pin first webcam (Mod2)
await this . modPage . waitAndClick ( ` :nth-match( ${ e . dropdownWebcamButton } , 3) ` ) ;
await this . modPage . waitAndClick ( ` :nth-match( ${ e . pinWebcamBtn } , 2) ` ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 1) ` , this . modPage2 . username , 'should the first webcam display the second moderator username for the first moderator' ) ;
await this . modPage2 . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 1) ` , this . modPage2 . username , 'should the first webcam display the second moderator username for the second moderator' ) ;
await this . userPage . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 1) ` , this . modPage2 . username , 'should the first webcam display the second moderator username for the attendee' ) ;
2022-09-13 01:10:57 +08:00
// Pin second webcam (user)
await this . modPage . waitAndClick ( ` :nth-match( ${ e . dropdownWebcamButton } , 3) ` ) ;
await this . modPage . waitAndClick ( ` :nth-match( ${ e . pinWebcamBtn } , 3) ` ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 1) ` , this . userPage . username , 'should the first webcam display the attendee username for the first moderator' ) ;
await this . modPage . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 2) ` , this . modPage2 . username , 'should the second webcam display the second moderator username for the first moderator' ) ;
await this . userPage . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 1) ` , this . modPage2 . username , 'should the first webcam display the second moderator username for the first attendee' ) ;
await this . userPage . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 2) ` , this . userPage . username , 'should the second webcam display the attendee username for the attendee' ) ;
await this . modPage2 . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 1) ` , this . userPage . username , 'should the first webcam display the attendee username for the second moderator' ) ;
await this . modPage2 . hasText ( ` :nth-match( ${ e . dropdownWebcamButton } , 2) ` , this . modPage2 . username , 'should the second webcam display the second moderator username for the second moderator' ) ;
2022-09-13 01:10:57 +08:00
}
2024-07-01 21:29:47 +08:00
async giveAndRemoveWhiteboardAccess ( ) {
2021-12-02 12:12:14 +08:00
await this . modPage . waitForSelector ( e . whiteboard ) ;
await this . modPage . waitAndClick ( e . userListItem ) ;
await this . modPage . waitAndClick ( e . changeWhiteboardAccess ) ;
2024-07-01 21:29:47 +08:00
await this . modPage . hasElement ( e . multiUsersWhiteboardOff ) ;
await this . modPage . waitAndClick ( e . userListItem ) ;
await this . modPage . waitAndClick ( e . changeWhiteboardAccess ) ;
await this . modPage . hasElement ( e . multiUsersWhiteboardOn ) ;
2021-11-23 05:51:16 +08:00
}
2022-12-08 02:53:56 +08:00
async muteAllUsers ( ) {
await this . modPage . joinMicrophone ( ) ;
await this . modPage2 . joinMicrophone ( ) ;
await this . userPage . joinMicrophone ( ) ;
await this . modPage . waitAndClick ( e . manageUsers ) ;
await this . modPage . waitAndClick ( e . muteAll ) ;
await checkMutedUsers ( this . modPage ) ;
await checkMutedUsers ( this . modPage2 ) ;
await checkMutedUsers ( this . userPage ) ;
}
async muteAllUsersExceptPresenter ( ) {
await this . modPage . joinMicrophone ( ) ;
await this . modPage2 . joinMicrophone ( ) ;
await this . userPage . joinMicrophone ( ) ;
await this . modPage . waitAndClick ( e . manageUsers ) ;
await this . modPage . waitAndClick ( e . muteAllExceptPresenter ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . hasElement ( e . isTalking , 'should display the is talking element for the moderator' ) ;
2022-12-08 02:53:56 +08:00
await checkMutedUsers ( this . modPage2 ) ;
await checkMutedUsers ( this . userPage ) ;
}
2022-12-22 02:30:08 +08:00
2023-01-13 19:16:49 +08:00
async removeUser ( ) {
await this . modPage . waitAndClick ( e . userListItem ) ;
await this . modPage . waitAndClick ( e . removeUser ) ;
await this . modPage . waitAndClick ( e . removeUserConfirmationBtn ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . wasRemoved ( e . userListItem , 'should not display a user on the user list for the moderator' ) ;
2023-01-13 19:16:49 +08:00
2023-01-13 22:33:16 +08:00
//Will be modified when the issue is fixed and accept just one of both screens
//https://github.com/bigbluebutton/bigbluebutton/issues/16463
try {
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasElement ( e . errorScreenMessage , 'should display the error screen message for the second moderator' ) ;
2023-01-13 22:33:16 +08:00
} catch ( err ) {
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasElement ( e . meetingEndedModalTitle , 'should display the meeting ended modal for the second moderator' ) ;
2023-01-13 22:33:16 +08:00
}
2023-01-13 19:16:49 +08:00
}
async removeUserAndPreventRejoining ( context ) {
await this . modPage . waitAndClick ( e . userListItem ) ;
await this . modPage . waitAndClick ( e . removeUser ) ;
await this . modPage . waitAndClick ( e . confirmationCheckbox ) ;
await this . modPage . waitAndClick ( e . removeUserConfirmationBtn ) ;
2024-07-31 06:49:02 +08:00
await this . modPage . wasRemoved ( e . userListItem , 'should not display the user on the user list for the moderator' ) ;
2023-01-13 19:16:49 +08:00
2023-08-23 04:25:50 +08:00
// Will be modified when the issue is fixed and accept just one of both screens
// https://github.com/bigbluebutton/bigbluebutton/issues/16463
2023-01-13 22:33:16 +08:00
try {
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasElement ( e . errorScreenMessage , 'should display the error screen message for the second moderator' ) ;
2023-08-23 04:25:50 +08:00
} catch {
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasElement ( e . meetingEndedModalTitle , 'should display the meeting ended modal for the second moderator' ) ;
2023-01-13 22:33:16 +08:00
}
2023-08-23 04:25:50 +08:00
2024-03-07 01:28:18 +08:00
await this . initModPage2 ( false , context , { meetingId : this . modPage . meetingId , joinParameter : 'userID=Moderator2' , shouldCheckAllInitialSteps : false } ) ;
2023-08-23 04:25:50 +08:00
// Due to same reason above, sometimes it displays different messages
try {
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasText ( e . userBannedMessage2 , /banned/ , 'should display the banned message for the second moderator' ) ;
2023-08-23 04:25:50 +08:00
} catch {
2024-07-31 06:49:02 +08:00
await this . modPage2 . hasText ( e . userBannedMessage1 , /removed/ , 'should display the removed message for the second moderator' ) ;
2023-08-23 04:25:50 +08:00
}
2023-01-13 19:16:49 +08:00
}
2021-11-16 00:42:29 +08:00
}
exports . MultiUsers = MultiUsers ;