diff --git a/bigbluebutton-html5/imports/ui/components/chat/chat-graphql/chat-message-list/page/chat-message/component.tsx b/bigbluebutton-html5/imports/ui/components/chat/chat-graphql/chat-message-list/page/chat-message/component.tsx index 53028d0e8d81..2e141c206e48 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/chat-graphql/chat-message-list/page/chat-message/component.tsx +++ b/bigbluebutton-html5/imports/ui/components/chat/chat-graphql/chat-message-list/page/chat-message/component.tsx @@ -530,6 +530,7 @@ const ChatMessage = React.forwardRef(({ $focused={focused} $keyboardFocused={keyboardFocused} $reactionPopoverIsOpen={isToolbarReactionPopoverOpen} + data-test="chatMessageItem" > + { showBranding && !compact diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx index 3bf0f7278616..87b706a60f7a 100644 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx @@ -1336,6 +1336,7 @@ const Whiteboard = React.memo((props) => { useElement.setAttribute('href', '#redPointer'); } else if (useElement) { useElement.setAttribute('href', '#cursor'); + useElement.setAttribute('data-test', 'whiteboardCursorIndicator'); } const idsToRemove = []; diff --git a/bigbluebutton-tests/playwright/audio/audio.spec.js b/bigbluebutton-tests/playwright/audio/audio.spec.js index 8caccbfce8eb..5a396add1790 100644 --- a/bigbluebutton-tests/playwright/audio/audio.spec.js +++ b/bigbluebutton-tests/playwright/audio/audio.spec.js @@ -3,7 +3,7 @@ const { fullyParallel } = require('../playwright.config'); const { Audio } = require('./audio'); const { initializePages } = require('../core/helpers'); -test.describe('Audio', () => { +test.describe('Audio', { tag: '@ci' }, () => { const audio = new Audio(); test.describe.configure({ mode: fullyParallel ? 'parallel' : 'serial' }); @@ -12,12 +12,12 @@ test.describe('Audio', () => { }); // https://docs.bigbluebutton.org/2.6/release-tests.html#listen-only-mode-automated - test('Join audio with Listen Only', { tag: '@ci' }, async () => { + test('Join audio with Listen Only', async () => { await audio.joinAudio(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#join-audio-automated - test('Join audio with Microphone', { tag: '@ci' }, async () => { + test('Join audio with Microphone', async () => { await audio.joinMicrophone(); }); @@ -26,23 +26,23 @@ test.describe('Audio', () => { }); // https://docs.bigbluebutton.org/2.6/release-tests.html#muteunmute - test('Mute yourself by clicking the mute button', { tag: '@ci' }, async () => { + test('Mute yourself by clicking the mute button', async () => { await audio.muteYourselfByButton(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#choosing-different-sources - test('Keep the last mute state after rejoining audio', { tag: '@ci' }, async () => { + test('Keep the last mute state after rejoining audio', async () => { await audio.keepMuteStateOnRejoin(); }); // Talking Indicator // https://docs.bigbluebutton.org/2.6/release-tests.html#talking-indicator - test('Mute yourself by clicking the talking indicator', { tag: '@ci' }, async () => { + test('Mute yourself by clicking the talking indicator', async () => { await audio.muteYourselfByTalkingIndicator(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#talking-indicator - test('Mute another user by clicking the talking indicator', { tag: '@ci' }, async () => { + test('Mute another user by clicking the talking indicator', async () => { await audio.muteAnotherUser(); }); }); diff --git a/bigbluebutton-tests/playwright/chat/chat.js b/bigbluebutton-tests/playwright/chat/chat.js index ebe73f009fa1..2dc060dfe21e 100644 --- a/bigbluebutton-tests/playwright/chat/chat.js +++ b/bigbluebutton-tests/playwright/chat/chat.js @@ -35,7 +35,7 @@ class Chat extends MultiUsers { await this.userPage.hasElement(e.hidePrivateChat, 'should display the hide private chat element when opening a private chat'); // check sent messages await this.modPage.hasText(e.chatUserMessageText, e.message1, 'should display the message sent by the moderator'); - await this.userPage.hasText(e.chatUserMessageText, e.message1, 'should display the message sent by the moderator for the attende'); + await this.userPage.hasText(e.chatUserMessageText, e.message1, 'should display the message sent by the moderator for the attendee'); // userPage send message await this.userPage.type(e.chatBox, e.message2); await this.modPage.hasElement(e.typingIndicator, 'should display the typing indicator for the moderator'); @@ -261,7 +261,7 @@ class Chat extends MultiUsers { await this.modPage.waitAndClick(e.sendButton); await this.userPage.waitUntilHaveCountSelector(e.chatButton, 2); await this.userPage.waitAndClickElement(e.chatButton, 1); - await this.userPage.hasElement(e.hidePrivateChat, 'should display the hide private chat element when the attende opens the private chat'); + await this.userPage.hasElement(e.hidePrivateChat, 'should display the hide private chat element when the attendee opens the private chat'); // check sent messages await this.modPage.hasText(e.chatUserMessageText, e.frequentlyUsedEmoji, 'should display the emoji sent by the moderator on the private chat'); await this.userPage.hasText(e.chatUserMessageText, e.frequentlyUsedEmoji, 'should display for the user the emoji sent by the moderator on the private chat'); @@ -364,7 +364,7 @@ class Chat extends MultiUsers { } await this.userPage.waitUntilHaveCountSelector(e.chatButton, 2); await this.userPage.waitAndClickElement(e.chatButton, 1); - await this.userPage.hasElement(e.hidePrivateChat, 'should display the hide private chat element for the attende when the private chat is opened'); + await this.userPage.hasElement(e.hidePrivateChat, 'should display the hide private chat element for the attendee when the private chat is opened'); // check sent messages await checkLastMessageSent(this.modPage, e.convertedEmojiMessage); await checkLastMessageSent(this.userPage, e.convertedEmojiMessage); @@ -382,9 +382,9 @@ class Chat extends MultiUsers { await openPrivateChat(this.modPage); await this.modPage.hasElement(e.sendButton, 'should display the send button on the private chat'); await this.userPage.logoutFromMeeting(); - await this.modPage.hasElement(e.partnerDisconnectedMessage, 'should the attende be disconnected', ELEMENT_WAIT_LONGER_TIME); - await this.modPage.wasRemoved(e.sendButton, 'should the send button be removed because the attende left the meeting'); - } + await this.modPage.hasElement(e.partnerDisconnectedMessage, 'should the attendee be disconnected', ELEMENT_WAIT_LONGER_TIME); + await this.modPage.wasRemoved(e.sendButton, 'should the send button be removed because the attendee left the meeting'); + } } exports.Chat = Chat; diff --git a/bigbluebutton-tests/playwright/chat/chat.spec.js b/bigbluebutton-tests/playwright/chat/chat.spec.js index 78b49bc8afa4..8f0101314cb6 100644 --- a/bigbluebutton-tests/playwright/chat/chat.spec.js +++ b/bigbluebutton-tests/playwright/chat/chat.spec.js @@ -1,9 +1,9 @@ const { test } = require('../fixtures'); const { fullyParallel } = require('../playwright.config'); -const { linkIssue, initializePages } = require('../core/helpers'); +const { initializePages } = require('../core/helpers'); const { Chat } = require('./chat'); -test.describe('Chat', () => { +test.describe('Chat', { tag: '@ci' }, () => { const chat = new Chat(); test.describe.configure({ mode: fullyParallel ? 'parallel' : 'serial' }); @@ -12,80 +12,80 @@ test.describe('Chat', () => { }); // https://docs.bigbluebutton.org/2.6/release-tests.html#public-message-automated - test('Send public message', { tag: '@ci' }, async () => { + test('Send public message', async () => { await chat.sendPublicMessage(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#private-message-automated - test('Send private message', { tag: '@ci' }, async () => { + test('Send private message', async () => { await chat.sendPrivateMessage(); }); - test('Clear chat', { tag: '@ci' }, async () => { + test('Clear chat', async () => { await chat.clearChat(); }); - test.skip('Copy chat', async () => { + test('Copy chat', { tag: '@only-headed' }, async ({}, testInfo) => { + test.skip(testInfo.project.use.headless, 'Only works in headed mode'); await chat.copyChat(); }); - test('Save chat', { tag: '@ci' }, async ({}, testInfo) => { + test('Save chat', async ({}, testInfo) => { await chat.saveChat(testInfo); }); - test('Verify character limit', { tag: '@ci' }, async () => { + test('Verify character limit', async () => { await chat.characterLimit(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#sending-empty-chat-message-automated - test('Not able to send an empty message', { tag: '@ci' }, async () => { + test('Not able to send an empty message', async () => { await chat.emptyMessage(); }); test('Copy and paste public message', async () => { - linkIssue('15948'); await chat.copyPastePublicMessage(); }) - test('Send emoji on public chat', { tag: '@ci' }, async () => { + test('Send emoji on public chat using emoji picker', { tag: '@setting-required:chat.emojiPicker' }, async () => { await chat.sendEmoji(); }); - test.skip('Copy chat with emoji', async () => { - // Only works in headed mode + test('Copy chat with emoji', { tag: '@only-headed' }, async () => { await chat.emojiCopyChat(); }); - test('Close private chat', { tag: '@ci' }, async () => { + test('Close private chat', async () => { await chat.closePrivateChat(); }); - test('Save chat with emoji', { tag: '@ci' }, async ({}, testInfo) => { + test('Save chat with emoji', { tag: '@setting-required:chat.emojiPicker' }, async ({}, testInfo) => { await chat.emojiSaveChat(testInfo); }); - test('Send emoji on private chat', async () => { + test('Send emoji on private chat', { tag: '@setting-required:chat.emojiPicker' }, async () => { await chat.emojiSendPrivateChat(); }); - test('Send auto converted emoji on public chat', async () => { + test('Send auto converted emoji on public chat', { tag: '@setting-required:chat.autoConvertEmoji' }, async () => { await chat.autoConvertEmojiPublicChat(); }); - test.skip('Copy chat with auto converted emoji', async () => { + test('Copy chat with auto converted emoji', { tag: '@setting-required:chat.autoConvertEmoji' }, async () => { await chat.autoConvertEmojiCopyChat(); }); - test('Auto convert emoji save chat', async ({}, testInfo) => { + test('Auto convert emoji save chat', { tag: '@setting-required:chat.autoConvertEmoji' }, async ({}, testInfo) => { await chat.autoConvertEmojiSaveChat(testInfo); }); - test('Send auto converted emoji on private chat', async () => { + test('Send auto converted emoji on private chat', { tag: '@setting-required:chat.autoConvertEmoji' }, async () => { await chat.autoConvertEmojiSendPrivateChat(); }); // failure only reproducible in CI (user leaves but keeps shown in the mod user list) - test('Private chat disabled when user leaves meeting', { tag: ['@ci', '@flaky'] }, async () => { + //! flaky flag recently removed in order to see current behavior + test('Private chat disabled when user leaves meeting', { tag: '@ci' }, async () => { await chat.chatDisabledUserLeaves(); }); }); diff --git a/bigbluebutton-tests/playwright/connectionFailure/connectionFailure.spec.js b/bigbluebutton-tests/playwright/connectionFailure/connectionFailure.spec.js index 6c09d4dbdff1..250f320cc909 100644 --- a/bigbluebutton-tests/playwright/connectionFailure/connectionFailure.spec.js +++ b/bigbluebutton-tests/playwright/connectionFailure/connectionFailure.spec.js @@ -5,12 +5,16 @@ const e = require('../core/elements'); const { getCurrentTCPSessions, killTCPSessions } = require('./util'); const deepEqual = require('deep-equal'); +// @ci Note: This entire test suite is skipped in CI because killing TCP connection +// might result in loss of connection with github server, causing the test to fail + test.describe.parallel('Connection failure', () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#sharing-screen-in-full-screen-mode-automated - test('Screen sharer', async ({ browser, browserName, page }) => { + test('Screen share', async ({ browser, browserName, page }) => { await checkRootPermission(); // check sudo permission before starting test - test.skip(browserName === 'firefox' && process.env.DISPLAY === undefined, - "Screenshare tests not able in Firefox browser without desktop"); + test.skip(browserName === 'firefox', + "Screenshare tests not able in Firefox browser without desktop", + ); const screenshare = new ScreenShare(browser, page); await screenshare.init(true, true); await screenshare.startSharing(); @@ -27,8 +31,9 @@ test.describe.parallel('Connection failure', () => { test('Screen share viewer', async ({ browser, browserName, page, context }) => { await checkRootPermission(); // check sudo permission before starting test - test.skip(browserName === 'firefox' && process.env.DISPLAY === undefined, - "Screenshare tests not able in Firefox browser without desktop"); + test.skip(browserName === 'firefox', + "Screenshare tests not able in Firefox browser without desktop", + ); const screenshare = new MultiUserScreenShare(browser, context); await screenshare.initModPage(page); diff --git a/bigbluebutton-tests/playwright/connectionStatus/connectionStatus.spec.js b/bigbluebutton-tests/playwright/connectionStatus/connectionStatus.spec.js index f989f233b524..be45647ab821 100644 --- a/bigbluebutton-tests/playwright/connectionStatus/connectionStatus.spec.js +++ b/bigbluebutton-tests/playwright/connectionStatus/connectionStatus.spec.js @@ -1,20 +1,20 @@ const { test } = require('../fixtures'); const { ConnectionStatus } = require('./connectionStatus'); -test.describe.parallel('Connection Status', () => { - test('Open connection Status Modal', { tag: '@ci' }, async ({ browser, context, page }) => { +test.describe.parallel('Connection Status', { tag: '@ci' } , () => { + test('Open connection Status Modal', async ({ browser, context, page }) => { const connectionStatus = new ConnectionStatus(browser, context); await connectionStatus.initModPage(page); await connectionStatus.connectionStatusModal(); }); - test('Show network data in Connection Status', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Show network data in Connection Status', async ({ browser, context, page }) => { const connectionStatus = new ConnectionStatus(browser, context); await connectionStatus.initModPage(page); await connectionStatus.usersConnectionStatus(); }); - test('Report a User with bad connection in Connection Issues', { tag: ['@ci', '@flaky'] }, async ({ browser, context, page }) => { + test('Report a User with bad connection in Connection Issues', { tag: '@need-update' }, async ({ browser, context, page }) => { // The following test emulates a bad connection with a custom event // PR #19289 changed the way it's measured, not able to do so with a custom event anymore const connectionStatus = new ConnectionStatus(browser, context); @@ -22,7 +22,7 @@ test.describe.parallel('Connection Status', () => { await connectionStatus.reportUserInConnectionIssues(); }); - test('Redirect to data saving settings when a bad connection is detected', { tag: ['@ci', '@flaky'] }, async ({ browser, context, page }) => { + test('Redirect to data saving settings when a bad connection is detected', { tag: '@need-update' }, async ({ browser, context, page }) => { // The following test emulates a bad connection with a custom event // PR #19289 changed the way it's measured, not able to do so with a custom event anymore const connectionStatus = new ConnectionStatus(browser, context); @@ -30,8 +30,8 @@ test.describe.parallel('Connection Status', () => { await connectionStatus.linkToSettingsTest(); }); - test('Copy stats', async ({ browser, context, page }, testInfo) => { - test.fixme(testInfo.project.use.headless, 'Only works in headed mode'); + test('Copy stats', { tag: '@only-headed' }, async ({ browser, context, page }, testInfo) => { + test.skip(testInfo.project.use.headless, 'Only works in headed mode'); const connectionStatus = new ConnectionStatus(browser, context); await connectionStatus.initModPage(page); await connectionStatus.copyStatsTest(context); diff --git a/bigbluebutton-tests/playwright/core/constants.js b/bigbluebutton-tests/playwright/core/constants.js index eae485d136b7..f8f9711636df 100644 --- a/bigbluebutton-tests/playwright/core/constants.js +++ b/bigbluebutton-tests/playwright/core/constants.js @@ -2,12 +2,12 @@ const CI = process.env.CI === 'true'; const TIMEOUT_MULTIPLIER = Number(process.env.TIMEOUT_MULTIPLIER); const MULTIPLIER = CI ? TIMEOUT_MULTIPLIER || 2 : TIMEOUT_MULTIPLIER || 1; +exports.CI = CI; // GLOBAL TESTS VARS exports.ELEMENT_WAIT_TIME = 5000 * MULTIPLIER; exports.ELEMENT_WAIT_LONGER_TIME = 10000 * MULTIPLIER; exports.ELEMENT_WAIT_EXTRA_LONG_TIME = 15000 * MULTIPLIER; exports.LOOP_INTERVAL = 1200; -exports.USER_LIST_VLIST_BOTS_LISTENING = 50; // STRESS TESTS VARS exports.JOIN_AS_MODERATOR_TEST_ROUNDS = 15; @@ -23,4 +23,5 @@ exports.VIDEO_LOADING_WAIT_TIME = 15000; exports.UPLOAD_PDF_WAIT_TIME = 25000 * MULTIPLIER; exports.CUSTOM_MEETING_ID = 'custom-meeting'; +// it only works for snapshot comparisons. playwright assertions will complain about the element (still in the DOM) exports.PARAMETER_HIDE_PRESENTATION_TOAST = 'userdata-bbb_custom_style=.presentationUploaderToast{display: none;}.currentPresentationToast{display:none;}'; diff --git a/bigbluebutton-tests/playwright/core/elements.js b/bigbluebutton-tests/playwright/core/elements.js index 5e8adc8d6c0c..75af8935c6de 100644 --- a/bigbluebutton-tests/playwright/core/elements.js +++ b/bigbluebutton-tests/playwright/core/elements.js @@ -29,7 +29,6 @@ exports.closePopup = 'button[data-test="closePopup"]'; exports.restoreWelcomeMessages = 'li[data-test="restoreWelcomeMessages"]'; // Accesskey -exports.chatButtonKey = 'div[accesskey="P"]'; exports.userListButton = 'button[accesskey="U"]'; // Audio @@ -47,7 +46,6 @@ exports.audioDropdownMenu = 'button[data-test="audioDropdownMenu"]'; exports.defaultInputAudioDevice = 'li[data-test="audioinput-1"]'; exports.secondInputAudioDevice = 'li[data-test="audioinput-2"]'; exports.microphoneButton = 'button[data-test="microphoneBtn"]'; -exports.echoYesButton = 'button[data-test="echoYesBtn"]'; exports.connectingToEchoTest = 'span[data-test="connectingToEchoTest"]'; exports.hasVolumeEchoTest = 'span[data-test="hasVolume"]'; exports.hasNoVolumeEchoTest = 'span[data-test="hasNoVolume"]'; @@ -101,6 +99,7 @@ exports.roomOption = 'option[data-test="roomOption"]'; // Chat exports.chatBox = 'textarea[id="message-input"]'; +exports.chatMessageItem = 'div[data-test="chatMessageItem"]'; exports.partnerDisconnectedMessage = 'span[data-test="partnerDisconnected"]'; exports.chatButton = 'button[data-test="chatButton"]'; exports.sendButton = 'button[data-test="sendMessageButton"]'; @@ -133,7 +132,7 @@ exports.guestMessage = 'p[data-test="guestMessage"]'; exports.privateMessageGuest = 'button[data-test="privateMessageGuest"]'; exports.acceptGuest = 'button[data-test="acceptGuest"]'; exports.denyGuest = 'button[data-test="denyGuest"]'; -exports.inputPrivateLobbyMesssage = 'div[data-test="privateLobbyMessage"] >> textarea'; +exports.inputPrivateLobbyMessage = 'div[data-test="privateLobbyMessage"] >> textarea'; exports.sendPrivateLobbyMessage = 'div[data-test="privateLobbyMessage"] >> button'; exports.rememberCheckboxId = 'input[id="rememberCheckboxId"]'; exports.welcomeMessage = 'h1[id="welcome-message"]'; @@ -155,6 +154,7 @@ exports.uniqueCharacterMessage = 'A'; // CustomParameters exports.audioOptionsButtons = 'span[data-test="audioModalOptions"] > button'; +exports.userListContainer = 'div[data-test="userListContainer"]'; exports.userListContent = 'div[data-test="userListContent"]'; exports.brandingAreaLogo = 'div[data-test="brandingArea"]'; exports.toolbarToolsList = 'div[data-test="toolbarToolsList"]'; @@ -223,7 +223,6 @@ exports.joinAudioToast = 'You have joined the audio conference'; exports.pollPublishedToast = 'Poll results were published'; exports.startScreenshareToast = 'Screenshare has started'; exports.endScreenshareToast = 'Screenshare has ended'; -exports.joiningMessageToast = 'You have joined the audio conference'; exports.attendeeJoinedToast = 'Attendee joined the session'; exports.raisingHandToast = 'You have raised your hand'; exports.loweringHandToast = 'Your hand has been lowered'; @@ -302,6 +301,7 @@ exports.presentationOptionsDownloadBtn = 'button[data-test="presentationOptionsD exports.confirmManagePresentation = 'button[data-test="confirmManagePresentation"]'; exports.toastDownload = 'a[data-test="toastDownload"]'; exports.presentationDownloadBtn = 'button[data-test="presentationDownload"]'; +exports.presentationItem = 'tr[data-test="presentationItem"]'; exports.removePresentation = 'button[data-test="removePresentation"]'; exports.presentationPlaceholder = 'div[data-test="presentationPlaceholder"]'; exports.presentationContainer = 'div[data-test="presentationContainer"]'; @@ -324,7 +324,7 @@ exports.presentationFullscreen = 'li[data-test="presentationFullscreen"]'; exports.presentationSnapshot = 'li[data-test="presentationSnapshot"]'; exports.toolVisibility = 'li[data-test="toolVisibility"]'; // YouTube frame -exports.youtubeLink = 'https://www.youtube.com/watch?v=Hso8yLzkqj8&ab_channel=BigBlueButton'; +exports.youtubeLink = 'https://www.youtube.com/watch?v=Wjx5_IONaNg&t=158s&ab_channel=BigBlueButton'; // The title we match for here is the title of the test video specified by youtubeLink exports.youtubeFrame = 'div[data-test="videoPlayer"]'; exports.ytFrameTitle = 'a[class^="ytp-title-link"]'; @@ -403,7 +403,7 @@ exports.lockEditSharedNotes = 'input[data-test="lockEditSharedNotes"]'; exports.lockUserList = 'input[data-test="lockUserList"]'; exports.hideViewersAnnotation = 'input[data-test="hideViewersAnnotation"]'; exports.hideViewersCursor = 'input[data-test="hideViewersCursor"]'; -exports.whiteboardCursorIndicator = 'div[data-test="whiteboardCursorIndicator"]'; +exports.whiteboardCursorIndicator = 'svg use[data-test="whiteboardCursorIndicator"]'; // Locales exports.locales = ['af', 'ar', 'az', 'bg-BG', 'bn', 'ca', 'cs-CZ', 'da', 'de', @@ -477,10 +477,8 @@ exports.zoomOutButton = 'button[data-test="zoomOutBtn"]'; exports.wbPan = 'button[data-test="panButton"]'; exports.wbEraser = 'button[data-testid="tools.eraser"]'; exports.wbArrowShape = 'button[data-testid="tools.arrow"]'; -exports.wbDelete = 'span[id="TD-Delete"]'; exports.wbUndo = 'button[data-testid="main.undo"]'; exports.wbRedo = 'button[data-testid="main.redo"]'; -exports.wbStyles = 'button[id="TD-Styles"]'; exports.whiteboardStyles = 'button[data-testid="mobile.styles"]'; exports.wbColorRed = 'button[data-id="red"]'; exports.wbFillDrawing = 'button[data-testid="style.fill.solid"]'; @@ -494,7 +492,7 @@ exports.wbMoveForward = 'button[data-testid="menu-item.bring-forward"]'; exports.wbMoveToFront = 'button[data-testid="menu-item.bring-to-front"]'; exports.wbPaste = 'button[data-testid="menu-item.paste"]'; exports.wbTextTrue = 'div[data-hastext="true"]'; -exports.wbDrawnArrow = 'div[data-shape-type="arrow"]';; +exports.wbDrawnArrow = 'div[data-shape-type="arrow"]'; // About modal exports.showAboutModalButton = 'li[data-test="aboutModal"]'; diff --git a/bigbluebutton-tests/playwright/core/page.js b/bigbluebutton-tests/playwright/core/page.js index 5a93eaee4b49..70bf8c61126e 100644 --- a/bigbluebutton-tests/playwright/core/page.js +++ b/bigbluebutton-tests/playwright/core/page.js @@ -305,11 +305,15 @@ class Page { } async closeAllToastNotifications() { - const closeToastBtnLocator = this.page.locator(e.closeToastBtn); - while (await closeToastBtnLocator.count() > 0) { + const closeToastBtnLocator = this.page.locator(e.closeToastBtn); + while (await closeToastBtnLocator.count() > 0) { + try { await this.page.click(e.closeToastBtn, { timeout: ELEMENT_WAIT_TIME }); await helpers.sleep(1500); // expected time to toast notification disappear + } catch (error) { + console.log('not able to close the toast notification'); } + } } async setHeightWidthViewPortSize() { diff --git a/bigbluebutton-tests/playwright/layouts/layouts.spec.js b/bigbluebutton-tests/playwright/layouts/layouts.spec.js index c6075dd8c55a..17f7d98921db 100644 --- a/bigbluebutton-tests/playwright/layouts/layouts.spec.js +++ b/bigbluebutton-tests/playwright/layouts/layouts.spec.js @@ -1,18 +1,14 @@ const { test } = require('../fixtures'); const { fullyParallel } = require('../playwright.config'); -const { encodeCustomParams } = require('../parameters/util'); -const { PARAMETER_HIDE_PRESENTATION_TOAST } = require('../core/constants'); const { Layouts } = require('./layouts'); const { initializePages } = require('../core/helpers'); -const hidePresentationToast = encodeCustomParams(PARAMETER_HIDE_PRESENTATION_TOAST); - test.describe('Layout', { tag: '@ci' }, () => { const layouts = new Layouts(); test.describe.configure({ mode: fullyParallel ? 'parallel' : 'serial' }); test[fullyParallel ? 'beforeEach' : 'beforeAll'](async ({ browser }) => { - await initializePages(layouts, browser, { isMultiUser: true, createParameter: hidePresentationToast }); + await initializePages(layouts, browser, { isMultiUser: true }); await layouts.modPage.shareWebcam(); await layouts.userPage.shareWebcam(); }); diff --git a/bigbluebutton-tests/playwright/learningdashboard/learningdashboard.spec.js b/bigbluebutton-tests/playwright/learningdashboard/learningdashboard.spec.js index 5bcd9b6ccfef..ebb066decf01 100644 --- a/bigbluebutton-tests/playwright/learningdashboard/learningdashboard.spec.js +++ b/bigbluebutton-tests/playwright/learningdashboard/learningdashboard.spec.js @@ -4,7 +4,7 @@ const { LearningDashboard } = require('./learningdashboard'); const c = require('../parameters/constants'); const { initializePages } = require('../core/helpers'); -test.describe('Learning Dashboard', async () => { +test.describe('Learning Dashboard', { tag: '@ci' } , async () => { const learningDashboard = new LearningDashboard(); test.describe.configure({ mode: fullyParallel ? 'parallel' : 'serial' }); @@ -21,20 +21,20 @@ test.describe('Learning Dashboard', async () => { await learningDashboard.userTimeOnMeeting(); }); - test('Polls', { tag: '@ci' }, async () => { + test('Polls', async () => { await learningDashboard.initUserPage(true, learningDashboard.modPage.context, { isRecording: true }); await learningDashboard.polls(); }); - test('Basic Infos', { tag: '@ci' }, async () => { + test('Basic Infos', async () => { await learningDashboard.basicInfos(); }); - - test('Overview', { tag: '@ci' }, async () => { + + test('Overview', async () => { await learningDashboard.overview(); }); - test('Download Session Learning Dashboard', { tag: '@ci' }, async ({}, testInfo) => { + test('Download Session Learning Dashboard', async ({}, testInfo) => { await learningDashboard.downloadSessionLearningDashboard(testInfo); }); }); diff --git a/bigbluebutton-tests/playwright/notifications/notifications.js b/bigbluebutton-tests/playwright/notifications/notifications.js index 8b41d6f175eb..167e08711c54 100644 --- a/bigbluebutton-tests/playwright/notifications/notifications.js +++ b/bigbluebutton-tests/playwright/notifications/notifications.js @@ -13,14 +13,12 @@ class Notifications extends MultiUsers { } async saveSettingsNotification() { - await util.waitAndClearDefaultPresentationNotification(this.modPage); await openSettings(this.modPage); await util.saveSettings(this.modPage); await util.checkNotificationText(this.modPage, e.savedSettingsToast); } async audioNotification() { - await util.waitAndClearDefaultPresentationNotification(this.modPage); await this.modPage.waitAndClick(e.joinAudio); await this.modPage.joinMicrophone(); await util.checkNotificationText(this.modPage, e.joinAudioToast); @@ -30,10 +28,10 @@ class Notifications extends MultiUsers { 'should not complain about loss in connection when joining audio' ).not.toHaveAttribute('color', 'danger'); await this.modPage.checkElementCount(e.smallToastMsg, 1, 'should have only one notification displayed'); - await util.waitAndClearNotification(this.modPage); + await this.modPage.closeAllToastNotifications(); await this.modPage.waitAndClick(e.audioDropdownMenu); await this.modPage.waitAndClick(e.leaveAudio); - await util.waitAndClearNotification(this.modPage); + await this.modPage.closeAllToastNotifications(); await this.modPage.waitAndClick(e.joinAudio); await this.modPage.waitAndClick(e.listenOnlyButton); await this.modPage.wasRemoved(e.establishingAudioLabel, 'should remove establish audio element after joining successfully'); @@ -42,9 +40,9 @@ class Notifications extends MultiUsers { } async getUserJoinPopupResponse() { - await util.waitAndClearDefaultPresentationNotification(this.modPage); + await this.modPage.hasElement(e.whiteboard); await this.userJoinNotification(this.modPage); - await util.waitAndClearNotification(this.modPage); + await this.modPage.closeAllToastNotifications(); await this.initUserPage(); await this.modPage.waitForSelector(e.smallToastMsg, ELEMENT_WAIT_LONGER_TIME); await util.checkNotificationText(this.modPage, e.attendeeJoinedToast); @@ -55,11 +53,9 @@ class Notifications extends MultiUsers { if (!reactionsButton) { await this.modPage.waitForSelector(e.whiteboard); await this.modPage.hasElement(e.joinAudio); - await this.modPage.wasRemoved(e.reactionsButton); - return + return this.modPage.wasRemoved(e.reactionsButton); } - await util.waitAndClearDefaultPresentationNotification(this.modPage); await this.modPage.waitAndClick(e.reactionsButton); await this.modPage.waitAndClick(e.raiseHandBtn); await sleep(1000); diff --git a/bigbluebutton-tests/playwright/notifications/notifications.spec.js b/bigbluebutton-tests/playwright/notifications/notifications.spec.js index d46b790a1341..00b20d2aea57 100644 --- a/bigbluebutton-tests/playwright/notifications/notifications.spec.js +++ b/bigbluebutton-tests/playwright/notifications/notifications.spec.js @@ -3,7 +3,8 @@ const { Notifications } = require('./notifications'); const { ChatNotifications } = require('./chatNotifications'); const { PresenterNotifications } = require('./presenterNotifications'); const { RecordingNotifications } = require('./recordingNotifications'); -const c = require('../parameters/constants'); +const { recordMeeting } = require('../parameters/constants'); +const { linkIssue } = require('../core/helpers'); test.describe.parallel('Notifications', { tag: '@ci' }, () => { test('Save settings notification', async ({ browser, context, page }) => { @@ -31,17 +32,20 @@ test.describe.parallel('Notifications', { tag: '@ci' }, () => { await notifications.raiseAndLowerHandNotification(); }); - test.describe.parallel('Chat', { tag: '@ci' }, () => { - // both tests are flaky due to missing refactor to get data from GraphQL - test('Public Chat notification', { tag: '@flaky' }, async ({ browser, context, page }) => { + test.describe.parallel('Chat', () => { + test('Public Chat notification', async ({ browser, context, page }) => { const chatNotifications = new ChatNotifications(browser, context); - await chatNotifications.initPages(page, true); + await chatNotifications.initPages(page); + await chatNotifications.modPage.closeAllToastNotifications(); + await chatNotifications.userPage.closeAllToastNotifications(); await chatNotifications.publicChatNotification(); }); - test('Private Chat notification', { tag: '@flaky' }, async ({ browser, context, page }) => { + test('Private Chat notification', async ({ browser, context, page }) => { const chatNotifications = new ChatNotifications(browser, context); - await chatNotifications.initPages(page, true); + await chatNotifications.initPages(page); + await chatNotifications.modPage.closeAllToastNotifications(); + await chatNotifications.userPage.closeAllToastNotifications(); await chatNotifications.privateChatNotification(); }); }); @@ -49,42 +53,53 @@ test.describe.parallel('Notifications', { tag: '@ci' }, () => { test.describe.parallel('Recording', () => { test('Notification appearing when user is not in audio', async ({ browser, page }) => { const recordingNotifications = new RecordingNotifications(browser, page); - await recordingNotifications.init(true, true, { createParameter: c.recordMeeting }); + await recordingNotifications.init(true, true, { createParameter: recordMeeting }); await recordingNotifications.notificationNoAudio(); }); + test('Notification appearing when user is in listen only', async ({ browser, page }) => { const recordingNotifications = new RecordingNotifications(browser, page); - await recordingNotifications.init(true, true, { createParameter: c.recordMeeting }); + await recordingNotifications.init(true, true, { createParameter: recordMeeting }); await recordingNotifications.notificationListenOnly(); }); + test('No notification appearing when user is in audio', async ({ browser, page }) => { const recordingNotifications = new RecordingNotifications(browser, page); - await recordingNotifications.init(true, true, { createParameter: c.recordMeeting }); + await recordingNotifications.init(true, true, { createParameter: recordMeeting }); await recordingNotifications.noNotificationInAudio(); }); - test('Modal appearing when user wants to start recording', { tag: '@ci' }, async ({ browser, page }) => { + + test('Modal appearing when user wants to start recording', async ({ browser, page }) => { const recordingNotifications = new RecordingNotifications(browser, page); - await recordingNotifications.init(true, true, { createParameter: c.recordMeeting }); + await recordingNotifications.init(true, true, { createParameter: recordMeeting }); await recordingNotifications.modalStartRecording(); }); }); - test.describe.parallel('Presenter', { tag: '@ci' }, () => { + test.describe.parallel('Presenter', () => { test('Poll results notification', async ({ browser, context, page }) => { const presenterNotifications = new PresenterNotifications(browser, context); - await presenterNotifications.initPages(page, true); + await presenterNotifications.initPages(page); + await presenterNotifications.modPage.closeAllToastNotifications(); + await presenterNotifications.userPage.closeAllToastNotifications(); await presenterNotifications.publishPollResults(); }); test('Presentation upload notification', { tag: '@flaky' }, async ({ browser, context, page }) => { + // uploader notification not displayed sometimes + // see https://github.com/bigbluebutton/bigbluebutton/issues/21321#issuecomment-2390301906 + linkIssue(21321); const presenterNotifications = new PresenterNotifications(browser, context); - await presenterNotifications.initPages(page, true); + await presenterNotifications.initPages(page); + await presenterNotifications.modPage.closeAllToastNotifications(); + await presenterNotifications.userPage.closeAllToastNotifications(); await presenterNotifications.fileUploaderNotification(); }); test('Screenshare notification', async ({ browser, browserName, context, page }) => { - test.skip(browserName === 'firefox' && process.env.DISPLAY === undefined, - "Screenshare tests not able in Firefox browser without desktop"); + test.skip(browserName === 'firefox', + 'Screenshare tests not able in Firefox browser without desktop', + ); const presenterNotifications = new PresenterNotifications(browser, context); await presenterNotifications.initModPage(page); await presenterNotifications.screenshareToast(); diff --git a/bigbluebutton-tests/playwright/notifications/presenterNotifications.js b/bigbluebutton-tests/playwright/notifications/presenterNotifications.js index dc75109c7acb..432455e0ba8a 100644 --- a/bigbluebutton-tests/playwright/notifications/presenterNotifications.js +++ b/bigbluebutton-tests/playwright/notifications/presenterNotifications.js @@ -12,7 +12,6 @@ class PresenterNotifications extends MultiUsers { } async publishPollResults() { - await util.waitAndClearDefaultPresentationNotification(this.modPage); await utilPolling.startPoll(this.modPage); await this.userPage.waitAndClick(e.pollAnswerOptionBtn); await this.modPage.hasElementEnabled(e.publishPollingLabel); diff --git a/bigbluebutton-tests/playwright/options/options.js b/bigbluebutton-tests/playwright/options/options.js index d4257567e70f..6f20c77c1697 100644 --- a/bigbluebutton-tests/playwright/options/options.js +++ b/bigbluebutton-tests/playwright/options/options.js @@ -1,8 +1,9 @@ const { expect } = require('@playwright/test'); const { openAboutModal, openSettings, getLocaleValues } = require('./util'); const e = require('../core/elements'); -const { ELEMENT_WAIT_TIME } = require('../core/constants'); +const { CI } = require('../core/constants'); const { MultiUsers } = require('../user/multiusers'); +const { sleep } = require('../core/helpers'); class Options extends MultiUsers { @@ -60,46 +61,107 @@ class Options extends MultiUsers { async darkMode() { await this.modPage.hasElement(e.whiteboard, 'should the whiteboard be display'); await this.modPage.waitAndClick(e.closePopup); - await openSettings(this.modPage); - - await this.modPage.waitAndClickElement(e.darkModeToggleBtn); - await this.modPage.waitAndClick(e.modalConfirmButton); + // send chat message + await this.modPage.type(e.chatBox, e.message); + await this.modPage.waitAndClick(e.sendButton); + await this.modPage.hasElement(e.chatUserMessageText, 'should the chat message be displayed'); + // set all locators + const [ + userListContainerLocator, + whiteboardOptionsButtonLocator, + messageTitleLocator, + presentationTitleLocator, + chatUserMessageTextLocator, + chatNotificationMessageItemLocator, + sendButtonLocator, + joinAudioLocator, + minimizePresentationLocator, + ] = [ + e.userListContainer, + e.whiteboardOptionsButton, + e.messageTitle, + e.presentationTitle, + e.chatUserMessageText, + e.chatNotificationMessageText, + `${e.sendButton} span[color]`, + `${e.joinAudio} span[color]`, + `${e.minimizePresentation} span[color]`, + ].map(e => this.modPage.getLocator(e)); + + const getBackgroundColorComputed = (node) => getComputedStyle(node).backgroundColor; + const getTextColorComputed = (node) => getComputedStyle(node).color; + // background color elements that should be changed (light mode) + const userListContainerBackgroundColor = await userListContainerLocator.evaluate(getBackgroundColorComputed); + const whiteboardOptionsButtonBackground = await whiteboardOptionsButtonLocator.evaluate(getBackgroundColorComputed); + const sendButtonBackgroundColor = await sendButtonLocator.evaluate(getBackgroundColorComputed); + const joinAudioBackgroundColor = await joinAudioLocator.evaluate(getBackgroundColorComputed); + const minimizePresentationBackgroundColor = await minimizePresentationLocator.evaluate(getBackgroundColorComputed); + // text colors that should be changed (light mode) + const chatMessagesBackgroundColor = await chatNotificationMessageItemLocator.evaluate(getTextColorComputed); + const messageTitleColor = await messageTitleLocator.evaluate(getTextColorComputed); + const presentationTitleColor = await presentationTitleLocator.evaluate(getTextColorComputed); + const chatUserMessageTextColor = await chatUserMessageTextLocator.evaluate(getTextColorComputed); - const modPageLocator = this.modPage.getLocator('body'); - await this.modPage.setHeightWidthViewPortSize(); - const screenshotOptions = { - maxDiffPixels: 1000, - }; - - await this.modPage.closeAllToastNotifications(); - await expect(modPageLocator, 'should the meeting be in dark mode').toHaveScreenshot('moderator-page-dark-mode.png', screenshotOptions); - await openSettings(this.modPage); await this.modPage.waitAndClickElement(e.darkModeToggleBtn); await this.modPage.waitAndClick(e.modalConfirmButton); - - await this.modPage.waitAndClick(e.chatOptions); - await this.modPage.waitAndClick(e.restoreWelcomeMessages); + await sleep(500); // wait for the changes to be applied + expect.soft(userListContainerBackgroundColor).not.toEqual(await userListContainerLocator.evaluate(getBackgroundColorComputed), 'should the user list container background color be changed'); + expect.soft(whiteboardOptionsButtonBackground).not.toEqual(await whiteboardOptionsButtonLocator.evaluate(getBackgroundColorComputed), 'should the whiteboard options button background color be changed'); + expect.soft(sendButtonBackgroundColor).not.toEqual(await sendButtonLocator.evaluate(getBackgroundColorComputed), 'should the send button background color be changed'); + expect.soft(joinAudioBackgroundColor).not.toEqual(await joinAudioLocator.evaluate(getBackgroundColorComputed), 'should the join audio button background color be changed'); + expect.soft(minimizePresentationBackgroundColor).not.toEqual(await minimizePresentationLocator.evaluate(getBackgroundColorComputed), 'should the minimize presentation button background color be changed'); + expect.soft(chatMessagesBackgroundColor).not.toEqual(await chatNotificationMessageItemLocator.evaluate(getTextColorComputed), 'should the chat notification message color be changed'); + expect.soft(messageTitleColor).not.toEqual(await messageTitleLocator.evaluate(getTextColorComputed), 'should the message title text color be changed'); + expect.soft(presentationTitleColor).not.toEqual(await presentationTitleLocator.evaluate(getTextColorComputed), 'should the presentation title text color be changed'); + expect.soft(chatUserMessageTextColor).not.toEqual(await chatUserMessageTextLocator.evaluate(getTextColorComputed), 'should the chat user message text color be changed'); + + if (!CI) { + const modPageLocator = this.modPage.getLocator('body'); + await this.modPage.setHeightWidthViewPortSize(); + const screenshotOptions = { + maxDiffPixels: 1000, + }; + await this.modPage.closeAllToastNotifications(); + await expect(modPageLocator, 'should the meeting be in dark mode').toHaveScreenshot('moderator-page-dark-mode.png', screenshotOptions); + } } async fontSizeTest() { await this.modPage.hasElement(e.whiteboard, 'should the whiteboard be display'); await this.modPage.waitAndClick(e.closePopup); + await this.modPage.setHeightWidthViewPortSize(); + const getFontSizeNumber = (node) => Number(getComputedStyle(node).fontSize.slice(0, -2)); + const [ + presentationTitleLocator, + chatButtonLocator, + messageTitleLocator, + ] = [ + e.presentationTitle, + e.chatButton, + e.messageTitle, + ].map(e => this.modPage.getLocator(e)); + const presentationTitleFontSize = await presentationTitleLocator.evaluate(getFontSizeNumber); + const chatButtonFontSize = await chatButtonLocator.evaluate(getFontSizeNumber); + const messageTitleFontSize = await messageTitleLocator.evaluate(getFontSizeNumber); + // Increasing font size await openSettings(this.modPage); await this.modPage.waitAndClick(e.increaseFontSize); await this.modPage.waitAndClick(e.modalConfirmButton); - - const modPageLocator = this.modPage.getLocator('body'); - - await this.modPage.setHeightWidthViewPortSize(); - const screenshotOptions = { - maxDiffPixels: 1000, - }; - - await this.modPage.closeAllToastNotifications(); - - await expect(modPageLocator, 'should the meeting display the font size increased').toHaveScreenshot('moderator-page-font-size.png', screenshotOptions); + await sleep(500); // wait for the changes to be applied + expect.soft(await presentationTitleLocator.evaluate(getFontSizeNumber)).toBeGreaterThan(presentationTitleFontSize, 'should the presentation title font size be increased'); + expect.soft(await chatButtonLocator.evaluate(getFontSizeNumber)).toBeGreaterThan(chatButtonFontSize, 'should the chat button font size be increased'); + expect.soft(await messageTitleLocator.evaluate(getFontSizeNumber)).toBeGreaterThan(messageTitleFontSize, 'should the message title font size be increased'); + + if (!CI) { + const modPageLocator = this.modPage.getLocator('body'); + const screenshotOptions = { + maxDiffPixels: 1000, + }; + await this.modPage.closeAllToastNotifications(); + await expect(modPageLocator, 'should the meeting display the font size increased').toHaveScreenshot('moderator-page-font-size.png', screenshotOptions); + } } } diff --git a/bigbluebutton-tests/playwright/options/options.spec.js b/bigbluebutton-tests/playwright/options/options.spec.js index f8a544e5906a..4978938dd95b 100644 --- a/bigbluebutton-tests/playwright/options/options.spec.js +++ b/bigbluebutton-tests/playwright/options/options.spec.js @@ -2,17 +2,13 @@ const { test } = require('../fixtures'); const { fullyParallel } = require('../playwright.config'); const { Options } = require('./options'); const { initializePages } = require('../core/helpers'); -const { encodeCustomParams } = require('../parameters/util'); -const { PARAMETER_HIDE_PRESENTATION_TOAST } = require('../core/constants'); -const hidePresentationToast = encodeCustomParams(PARAMETER_HIDE_PRESENTATION_TOAST); - -test.describe('Options', () => { +test.describe('Options', { tag: '@ci' }, () => { const options = new Options(); test.describe.configure({ mode: fullyParallel ? 'parallel' : 'serial' }); test[fullyParallel ? 'beforeEach' : 'beforeAll'](async ({ browser }) => { - await initializePages(options, browser, { joinParameter: hidePresentationToast }); + await initializePages(options, browser); }); test('Open about modal', async () => { @@ -23,15 +19,16 @@ test.describe('Options', () => { await options.openHelp(); }); - test('Locales test', async () => { + test('Locales', { tag: '@flaky' }, async () => { + // not applying the correct locale for some main elements await options.localesTest(); }); - test('Dark mode', { tag: ['@ci', '@flaky'] }, async () => { + test('Dark mode', async () => { await options.darkMode(); }); - test('Font size', { tag: ['@ci', '@flaky'] }, async () => { + test('Font size', async () => { await options.fontSizeTest(); }); }); diff --git a/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-dark-mode-Chromium-linux.png b/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-dark-mode-Chromium-linux.png index 6fdca4ac2550..d35d3410703e 100644 Binary files a/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-dark-mode-Chromium-linux.png and b/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-dark-mode-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-font-size-Chromium-linux.png b/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-font-size-Chromium-linux.png index da7c29cd4ed7..93368b30a2ad 100644 Binary files a/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-font-size-Chromium-linux.png and b/bigbluebutton-tests/playwright/options/options.spec.js-snapshots/moderator-page-font-size-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/package.json b/bigbluebutton-tests/playwright/package.json index 03bccccf4d9e..c885b1b43729 100644 --- a/bigbluebutton-tests/playwright/package.json +++ b/bigbluebutton-tests/playwright/package.json @@ -5,8 +5,8 @@ "test:filter": "npx playwright test -g", "test:headed": "npx playwright test --headed", "test:debug": "npx playwright test --debug -g", - "test-chromium-ci": "export CI='true' && npx playwright test --project=chromium --grep @ci --grep-invert @flaky", - "test-firefox-ci": "export CI='true' && npx playwright test --project=firefox --grep @ci --grep-invert @flaky", + "test-chromium-ci": "export CI='true' && npx playwright test --project=chromium --grep @ci --grep-invert '@flaky|@need-update|@only-headed|@setting-required'", + "test-firefox-ci": "export CI='true' && npx playwright test --project=firefox --grep @ci --grep-invert '@flaky|@need-update|@only-headed|@setting-required'", "rewrite-snapshots": "read -p 'CAUTION: You will delete ALL testing folders containing snapshots and run the tests to rewrite these files.\nProceed? (y/n) ' confirm && test $confirm = 'y' && sh core/scripts/rewrite-snapshots.sh" }, "dependencies": { @@ -19,4 +19,4 @@ "sha.js": "^2.4.11", "xml2js": "^0.6.2" } -} +} \ No newline at end of file diff --git a/bigbluebutton-tests/playwright/parameters/constants.js b/bigbluebutton-tests/playwright/parameters/constants.js index d0803df0cc61..b61f5fbba415 100644 --- a/bigbluebutton-tests/playwright/parameters/constants.js +++ b/bigbluebutton-tests/playwright/parameters/constants.js @@ -40,7 +40,7 @@ exports.presenterTools = 'userdata-bbb_presenter_tools=["select","draw", "arrow" exports.multiUserTools = 'userdata-bbb_multi_user_tools=["arrow","text"]'; const cssCode = `${e.presentationTitle}{display: none;}`; exports.customStyle = `userdata-bbb_custom_style=${cssCode}`; -exports.customStyleUrl = 'userdata-bbb_custom_style_url=https://develop.bigbluebutton.org/css-test-file.css'; +exports.customStyleUrl = 'userdata-bbb_custom_style_url=https://dev30.bigbluebutton.org/css-test-file.css'; exports.autoSwapLayout = 'userdata-bbb_auto_swap_layout=true'; exports.hidePresentationOnJoin = 'userdata-bbb_hide_presentation_on_join=true'; exports.outsideToggleSelfVoice = 'userdata-bbb_outside_toggle_self_voice=true'; diff --git a/bigbluebutton-tests/playwright/parameters/customparameters.js b/bigbluebutton-tests/playwright/parameters/customparameters.js index 5cb761896045..a308654d5279 100644 --- a/bigbluebutton-tests/playwright/parameters/customparameters.js +++ b/bigbluebutton-tests/playwright/parameters/customparameters.js @@ -112,9 +112,10 @@ class CustomParameters extends MultiUsers { } async forceListenOnly() { - await this.userPage.wasRemoved(e.audioModal, 'should not display the audio modal, should join without microphone'); - await this.userPage.hasElement(e.toastContainer, 'should display the toast container for the attendee', ELEMENT_WAIT_LONGER_TIME); - await util.forceListenOnly(this.userPage); + await this.userPage.wasRemoved(e.audioModal, 'should not display the audio modal after joining meeting'); + await this.userPage.hasElement(e.leaveListenOnly, 'should join listen only mode and display button to leave it'); + await this.userPage.wasRemoved(e.muteMicButton, 'should not display the mute mic button'); + await this.userPage.wasRemoved(e.unmuteMicButton, 'should not display the mute mic button'); } async skipCheck() { @@ -155,7 +156,7 @@ class CustomParameters extends MultiUsers { const notificationBarColor = await notificationLocator.evaluate((elem) => { return getComputedStyle(elem).backgroundColor; }, e.notificationBannerBar); - expect(notificationBarColor, 'should display the banner bar with the choosen color').toBe(colorToRGB); + expect(notificationBarColor, 'should display the banner bar with the chosen color').toBe(colorToRGB); } async hidePresentationOnJoin() { diff --git a/bigbluebutton-tests/playwright/parameters/parameters.spec.js b/bigbluebutton-tests/playwright/parameters/parameters.spec.js index 8c3672dd8a39..e646f20e9893 100644 --- a/bigbluebutton-tests/playwright/parameters/parameters.spec.js +++ b/bigbluebutton-tests/playwright/parameters/parameters.spec.js @@ -4,10 +4,7 @@ const { DisabledFeatures } = require('./disabledFeatures'); const c = require('./constants'); const { encodeCustomParams, getAllShortcutParams, hexToRgb } = require('./util'); const { CreateParameters } = require('./createParameters'); -const { PARAMETER_HIDE_PRESENTATION_TOAST } = require('../core/constants'); - -// it only works for snapshot comparisons. playwright assertions will complain about the element (still in the DOM) -const hidePresentationToast = encodeCustomParams(PARAMETER_HIDE_PRESENTATION_TOAST); +const { linkIssue } = require('../core/helpers'); test.describe.parallel('Create Parameters', { tag: '@ci' }, () => { test('Record Meeting', async ({ browser, context, page }) => { @@ -31,15 +28,16 @@ test.describe.parallel('Create Parameters', { tag: '@ci' }, () => { }); }); - // see https://github.com/bigbluebutton/bigbluebutton/issues/19426 test('Max Participants', { tag: '@flaky' }, async ({ browser, context, page }) => { + // considering value set - 1 (e.g. maxParticipants=3: 2 users would be able to join) + // see issue below + linkIssue(19426); const createParam = new CreateParameters(browser, context); await createParam.initModPage(page, true, { createParameter: c.maxParticipants }); await createParam.initModPage2(true, context); await createParam.maxParticipants(context); }); - // Not working due to missing data provided by GraphQL test('Meeting Duration', async ({ browser, context, page }) => { const createParam = new CreateParameters(browser, context); await createParam.initModPage(page, true, { createParameter: c.duration }); @@ -65,7 +63,7 @@ test.describe.parallel('Create Parameters', { tag: '@ci' }, () => { await createParam.muteOnStart(); }); - test('Allow Mods To Unmute Users', { tag: '@fci' }, async ({ browser, context, page }) => { + test('Allow Mods To Unmute Users', async ({ browser, context, page }) => { const createParam = new CreateParameters(browser, context); await createParam.initModPage(page, true, { createParameter: c.allowModsToUnmuteUsers }); await createParam.allowModsToUnmuteUsers(context); @@ -366,7 +364,7 @@ test.describe.parallel('Custom Parameters', { tag: '@ci' }, () => { await customParam.clientTitle(); }); - test('Ask for feedback on logout', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Ask for feedback on logout', async ({ browser, context, page }) => { const customParam = new CustomParameters(browser, context); await customParam.initModPage(page, true, { joinParameter: c.askForFeedbackOnLogout }); await customParam.askForFeedbackOnLogout(); @@ -393,7 +391,6 @@ test.describe.parallel('Custom Parameters', { tag: '@ci' }, () => { }); test('Custom Styles: URL', async ({ browser, context, page }) => { - test.fixme(); const customParam = new CustomParameters(browser, context); await customParam.initModPage(page, true, { joinParameter: encodeCustomParams(c.customStyleUrl) }); await customParam.customStyle(); @@ -430,8 +427,10 @@ test.describe.parallel('Custom Parameters', { tag: '@ci' }, () => { }); test.describe.parallel('Audio', () => { - // see https://github.com/bigbluebutton/bigbluebutton/issues/19427 - test('Auto join', async ({ browser, context, page }) => { + test('Auto join', { tag: '@flaky' }, async ({ browser, context, page }) => { + // first user to join the meeting is not auto-joining the audio + // see issue below + linkIssue(19427); const customParam = new CustomParameters(browser, context); await customParam.initModPage(page, false, { joinParameter: c.autoJoin }); await customParam.autoJoin(); @@ -443,9 +442,12 @@ test.describe.parallel('Custom Parameters', { tag: '@ci' }, () => { await customParam.listenOnlyMode(); }); - // see https://github.com/bigbluebutton/bigbluebutton/issues/19428 - test('Force Listen Only', async ({ browser, context, page }) => { + test('Force Listen Only', { tag: '@flaky' }, async ({ browser, context, page }) => { + // param applied to moderators (not expected) + // see issue below + linkIssue(21326); const customParam = new CustomParameters(browser, context); + // param only applied for attendees await customParam.initUserPage(false, context, { useModMeetingId: false, joinParameter: c.forceListenOnly }); await customParam.forceListenOnly(page); }); @@ -470,7 +472,6 @@ test.describe.parallel('Custom Parameters', { tag: '@ci' }, () => { }); test.describe.parallel('Presentation', () => { - // see https://github.com/bigbluebutton/bigbluebutton/issues/19456 test('Hide Presentation on join', async ({ browser, context, page }) => { const customParam = new CustomParameters(browser, context); await customParam.initModPage(page, true, { joinParameter: c.hidePresentationOnJoin }); @@ -478,7 +479,7 @@ test.describe.parallel('Custom Parameters', { tag: '@ci' }, () => { await customParam.hidePresentationOnJoin(); }); - test('Force restore presentation on new events', { tag: ['@ci', '@flaky'] }, async ({ browser, context, page }) => { + test('Force restore presentation on new events', { tag: '@flaky' }, async ({ browser, context, page }) => { // tagged as flaky because it's restoring presentation right after minimizing it due to unexpected zooming slide const customParam = new CustomParameters(browser, context); await customParam.initModPage(page); diff --git a/bigbluebutton-tests/playwright/parameters/util.js b/bigbluebutton-tests/playwright/parameters/util.js index 8bb3b29d14af..a76da6eec908 100644 --- a/bigbluebutton-tests/playwright/parameters/util.js +++ b/bigbluebutton-tests/playwright/parameters/util.js @@ -3,11 +3,6 @@ const e = require('../core/elements'); const c = require('./constants'); const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); -async function forceListenOnly(test) { - await test.wasRemoved(e.echoYesButton); - await test.hasText(e.toastContainer, e.joiningMessageToast); -} - function hexToRgb(hex) { const bigint = parseInt(hex, 16); const r = (bigint >> 16) & 255; @@ -109,7 +104,6 @@ exports.previousSlide = previousSlide; exports.nextSlide = nextSlide; exports.annotation = annotation; exports.hexToRgb = hexToRgb; -exports.forceListenOnly = forceListenOnly; exports.encodeCustomParams = encodeCustomParams; exports.getAllShortcutParams = getAllShortcutParams; exports.checkAccesskey = checkAccesskey; diff --git a/bigbluebutton-tests/playwright/playwright.config.js b/bigbluebutton-tests/playwright/playwright.config.js index 4349489a8010..01b4c28026e5 100644 --- a/bigbluebutton-tests/playwright/playwright.config.js +++ b/bigbluebutton-tests/playwright/playwright.config.js @@ -1,8 +1,7 @@ require('dotenv').config(); const { chromiumConfig, firefoxConfig, webkitConfig } = require('./core/browsersConfig'); -const { ELEMENT_WAIT_TIME } = require('./core/constants'); +const { ELEMENT_WAIT_TIME, CI } = require('./core/constants'); -const CI = process.env.CI === 'true'; const isParallel = !!process.env.npm_config_parallel; const config = { diff --git a/bigbluebutton-tests/playwright/polling/poll.js b/bigbluebutton-tests/playwright/polling/poll.js index c14f8e476481..bc9a7e9f65f8 100644 --- a/bigbluebutton-tests/playwright/polling/poll.js +++ b/bigbluebutton-tests/playwright/polling/poll.js @@ -273,38 +273,7 @@ class Polling extends MultiUsers { await this.userPage.waitAndClick(e.pollAnswerOptionBtn); await this.modPage.hasElement(e.publishPollingLabel, 'should display the publish poll button enabled after the attendee answered the poll'); await this.modPage.waitAndClick(e.publishPollingLabel); - await expect(wbDrawnRectangleLocator,'should display the rectangle with the poll information on the whiteboard').toHaveCount(initialWbDrawnRectangleCount + 1); - - const lastWbDrawnRectangleLocator = await wbDrawnRectangleLocator.last(); - await expect(lastWbDrawnRectangleLocator, 'should display the last rectangle with the poll information on the whiteboard').toBeVisible({ timeout: ELEMENT_WAIT_TIME}); - - const modWbLocator = this.modPage.getLocator(e.whiteboard); - const wbBox = await modWbLocator.boundingBox(); - - // poll results should be editable by the presenter - await lastWbDrawnRectangleLocator.dblclick({ timeout: ELEMENT_WAIT_TIME }); - await this.modPage.page.mouse.down(); - await this.modPage.page.mouse.move(wbBox.x + 0.7 * wbBox.width, wbBox.y + 0.7 * wbBox.height); - await this.modPage.page.mouse.up(); - await lastWbDrawnRectangleLocator.dblclick({ timeout: ELEMENT_WAIT_TIME }); - await this.modPage.page.keyboard.type('test'); - await expect(lastWbDrawnRectangleLocator, 'should display the text test on the last rectangle poll results on the whiteboard').toContainText('test'); - - // user turns to presenter to edit the poll results - await this.modPage.waitAndClick(e.userListItem); - await this.modPage.waitAndClick(e.makePresenter); - - await this.userPage.waitAndClick(e.zoomInButton); - await this.userPage.waitAndClick(e.resetZoomButton); - - const wbDrawnRectangleUserLocator = await this.userPage.getLocator(e.wbPollShape).last(); - await wbDrawnRectangleUserLocator.dblclick({ timeout: ELEMENT_WAIT_TIME }); - await this.userPage.page.keyboard.type('testUser'); - await expect(wbDrawnRectangleUserLocator, 'should display the edit that the attendee made to the poll results rectangle on the whiteboard').toContainText('testUser'); - - await this.modPage.waitAndClick(e.currentUser); - await this.modPage.waitAndClick(e.takePresenter); - await this.userPage.waitAndClick(e.hidePublicChat); + await expect(wbDrawnRectangleLocator,'should display a rectangle shape with the poll result on the whiteboard').toHaveCount(initialWbDrawnRectangleCount + 1); } async pollResultsInDifferentPresentation() { diff --git a/bigbluebutton-tests/playwright/polling/polling.spec.js b/bigbluebutton-tests/playwright/polling/polling.spec.js index 18a81f3f263f..0b929d4102f3 100644 --- a/bigbluebutton-tests/playwright/polling/polling.spec.js +++ b/bigbluebutton-tests/playwright/polling/polling.spec.js @@ -61,7 +61,7 @@ test.describe('Polling', { tag: '@ci' }, async () => { await polling.pollResultsOnChat(); }); - test('Poll results on whiteboard', { tag: '@flaky' } , async () => { + test('Poll results on whiteboard', async () => { await polling.pollResultsOnWhiteboard(); }); diff --git a/bigbluebutton-tests/playwright/presentation/presentation.js b/bigbluebutton-tests/playwright/presentation/presentation.js index e9671a2ba140..8d7edff6ff57 100644 --- a/bigbluebutton-tests/playwright/presentation/presentation.js +++ b/bigbluebutton-tests/playwright/presentation/presentation.js @@ -1,13 +1,10 @@ -const { expect, default: test } = require('@playwright/test'); +const { expect } = require('@playwright/test'); const { MultiUsers } = require('../user/multiusers'); -const Page = require('../core/page'); const e = require('../core/elements'); const { checkSvgIndex, getSlideOuterHtml, uploadSinglePresentation, uploadMultiplePresentations, getCurrentPresentationHeight } = require('./util.js'); -const { ELEMENT_WAIT_LONGER_TIME, ELEMENT_WAIT_EXTRA_LONG_TIME, UPLOAD_PDF_WAIT_TIME, ELEMENT_WAIT_TIME } = require('../core/constants'); +const { ELEMENT_WAIT_LONGER_TIME, ELEMENT_WAIT_EXTRA_LONG_TIME, UPLOAD_PDF_WAIT_TIME, CI } = require('../core/constants'); const { sleep } = require('../core/helpers'); const { getSettings } = require('../core/settings'); -const { waitAndClearNotification } = require('../notifications/util.js'); -const CI = process.env.CI === 'true'; const defaultZoomLevel = '100%'; @@ -112,23 +109,22 @@ class Presentation extends MultiUsers { await this.modPage.closeAllToastNotifications(); await this.userPage.closeAllToastNotifications(); - const modWhiteboardLocator = this.modPage.getLocator(e.whiteboard); - await this.modPage.setHeightWidthViewPortSize(); // Skip check for screenshot on ci, due to the ci and the local machine generating two different image sizes if (!CI) { + const modWhiteboardLocator = this.modPage.getLocator(e.whiteboard); await expect(modWhiteboardLocator).toHaveScreenshot('moderator-new-presentation-screenshot.png', { maxDiffPixels: 1000, }); } - const imageURLSecondPresentation = await this.modPage.page.evaluate(() => { + const imageURLSecondPresentation = await this.modPage.page.evaluate(() => { const element = document.querySelector('div[id="whiteboard-element"] div[class="tl-image"]'); const style = element.getAttribute('style') const urlMatch = style.match(/background-image: url\("([^"]+)"\)/); return urlMatch ? urlMatch[1] : null; }); - + await this.userPage.reloadPage(); await this.userPage.closeAudioModal(); await this.userPage.closeAllToastNotifications(); @@ -136,7 +132,7 @@ class Presentation extends MultiUsers { await this.userPage.setHeightWidthViewPortSize(); await expect(imageURLFirstPresentation).not.toBe(imageURLSecondPresentation); - + // Skip check for screenshot on ci, due to the ci and the local machine generating two different image sizes if (!CI) { await expect(userWhiteboardLocator).toHaveScreenshot('viewer-new-presentation-screenshot.png', { @@ -337,17 +333,19 @@ class Presentation extends MultiUsers { async uploadAndRemoveAllPresentations() { await uploadSinglePresentation(this.modPage, e.uploadPresentationFileName); + await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME); + await sleep(1000); // timeout to avoid trying to get the slide data before it's ready const modSlides1 = await getSlideOuterHtml(this.modPage); const userSlides1 = await getSlideOuterHtml(this.userPage); await expect(modSlides1, 'should the moderator slide and the attendee slide to be equal').toEqual(userSlides1); // Remove - await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME); await this.modPage.waitAndClick(e.actions); await this.modPage.waitAndClick(e.managePresentations); - await this.modPage.waitAndClick(e.removePresentation); - await this.modPage.waitAndClick(e.removePresentation); + await this.modPage.checkElementCount(e.presentationItem, 2, 'should display both default and uploaded presentation on the manage presentations modal'); + await this.modPage.waitAndClick(e.removePresentation); // remove first presentation + await this.modPage.waitAndClick(e.removePresentation); // remove second presentation await this.modPage.waitAndClick(e.confirmManagePresentation); await this.modPage.wasRemoved(e.whiteboard, 'should not display the whiteboard for the moderator'); @@ -371,6 +369,8 @@ class Presentation extends MultiUsers { } async removePreviousPresentationFromPreviousPresenter() { + await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME); + await this.modPage.closeAllToastNotifications(); await uploadSinglePresentation(this.modPage, e.uploadPresentationFileName); const modSlides1 = await getSlideOuterHtml(this.modPage); @@ -414,12 +414,16 @@ class Presentation extends MultiUsers { } async hidePresentationToolbar() { + await this.modPage.waitAndClick(e.multiUsersWhiteboardOn); await this.modPage.waitAndClick(e.whiteboardOptionsButton); await this.modPage.waitAndClick(e.toolVisibility); + const screenshotOptions = { + maxDiffPixels: 1000, + }; await this.modPage.wasRemoved(e.wbToolbar, 'should not display the whiteboard toolbar for the moderator'); - await this.modPage.wasRemoved(e.wbStyles, 'should not display the whiteboard styles menu'); - await this.modPage.wasRemoved(e.wbUndo, 'should not display the whiteboard undo button'); - await this.modPage.wasRemoved(e.wbRedo, 'should not display the whiteboard redo button'); + if (!CI) await expect(this.modPage.page, 'should not display the presentation toolbar').toHaveScreenshot('mod-hide-toolbars.png', screenshotOptions); + await this.userPage.hasElement(e.wbToolbar, 'should display the whiteboard toolbar for the viewer with whiteboard access'); + if (!CI) await expect(this.userPage.page, 'should display the presentation toolbar').toHaveScreenshot('user-toolbars.png', screenshotOptions); } async zoom() { diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js b/bigbluebutton-tests/playwright/presentation/presentation.spec.js index b551259b92d4..a03908690358 100644 --- a/bigbluebutton-tests/playwright/presentation/presentation.spec.js +++ b/bigbluebutton-tests/playwright/presentation/presentation.spec.js @@ -2,71 +2,77 @@ const { test } = require('../fixtures'); const { encodeCustomParams } = require('../parameters/util'); const { Presentation } = require('./presentation'); const { linkIssue } = require('../core/helpers'); +const { PARAMETER_HIDE_PRESENTATION_TOAST } = require('../core/constants'); -const customStyleAvoidUploadingNotifications = encodeCustomParams(`userdata-bbb_custom_style=.presentationUploaderToast{display: none;}`); +const hidePresentationToast = encodeCustomParams(PARAMETER_HIDE_PRESENTATION_TOAST); -test.describe.parallel('Presentation', () => { +test.describe.parallel('Presentation', { tag: '@ci' }, () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#navigation-automated - test('Skip slide', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Skip slide', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.skipSlide(); }); - test('Share Camera As Content', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Share Camera As Content', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.shareCameraAsContent(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#minimizerestore-presentation-automated - test('Hide/Restore presentation', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Hide/Restore presentation', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.hideAndRestorePresentation(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#start-youtube-video-sharing - test('Start external video', { tag: [ '@ci', '@flaky' ] }, async ({ browser, context, page }) => { + test('Start external video', { tag: '@flaky' }, async ({ browser, context, page }) => { + // requiring logged user to start external video on CI environment + linkIssue(21589); const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.startExternalVideo(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#fit-to-width-option - test('Presentation fit to width', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Presentation fit to width', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); - await presentation.initModPage(page, true, { createParameter: customStyleAvoidUploadingNotifications }); + await presentation.initModPage(page, true, { joinParameter: hidePresentationToast }); await presentation.initUserPage(true, context); await presentation.fitToWidthTest(); }); - test('Presentation fullscreen', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Presentation fullscreen', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.presentationFullscreen(); }); - test('Presentation snapshot', { tag: '@ci' }, async ({ browser, context, page }, testInfo) => { + test('Presentation snapshot', async ({ browser, context, page }, testInfo) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.presentationSnapshot(testInfo); }); - test('Hide Presentation Toolbar', { tag: ['@ci', '@flaky'] }, async ({ browser, context, page }) => { + test('Hide Presentation Toolbar', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); - await presentation.initPages(page); + await presentation.initModPage(page, true, { joinParameter: hidePresentationToast }); + await presentation.initUserPage(page, context, { joinParameter: hidePresentationToast }); await presentation.hidePresentationToolbar(); }); - test('Zoom In, Zoom Out, Reset Zoom', { tag: ['@ci', '@flaky'] }, async ({ browser, context, page }) => { - // @flaky: see https://github.com/bigbluebutton/bigbluebutton/issues/21266 + test('Zoom In, Zoom Out, Reset Zoom', { tag: '@flaky' }, async ({ browser, context, page }) => { + // Oct, 24 => Recent failures in CI runs. doesn't seem to be reproducible locally + // see issue below + linkIssue(21266); const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.zoom(); }); - test('Select Slide', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Select Slide', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.selectSlide(); @@ -74,13 +80,17 @@ test.describe.parallel('Presentation', () => { test.describe.parallel('Manage', () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#uploading-a-presentation-automated - test('Upload single presentation', { tag: ['@ci', '@flaky'] }, async ({ browser, context, page }) => { + test('Upload single presentation', { tag: '@flaky' }, async ({ browser, context, page }) => { + // current presentation toast not being displayed sometimes + linkIssue(21576); const presentation = new Presentation(browser, context); await presentation.initPages(page, true); await presentation.uploadSinglePresentationTest(); }); - test('Upload Other Presentations Format', { tag: ['@ci', '@flaky'] }, async ({ browser, context, page }) => { + test('Upload Other Presentations Format', { tag: '@flaky' }, async ({ browser, context, page }) => { + // file with wrong (not expected) ideogram conversion pushed, which is used for assertions + // see issue below linkIssue(18971); const presentation = new Presentation(browser, context); await presentation.initPages(page, true); @@ -88,40 +98,46 @@ test.describe.parallel('Presentation', () => { }); // https://docs.bigbluebutton.org/2.6/release-tests.html#uploading-multiple-presentations-automated - test('Upload multiple presentations', async ({ browser, context, page }) => { + test('Upload multiple presentations', { tag: '@flaky' }, async ({ browser, context, page }) => { + // current presentation toast not being displayed sometimes + linkIssue(21576); const presentation = new Presentation(browser, context); await presentation.initPages(page, true); await presentation.uploadMultiplePresentationsTest(); }); // https://docs.bigbluebutton.org/2.6/release-tests.html#enabling-and-disabling-presentation-download-automated - test('Enable and disable original presentation download', { tag: '@ci' }, async ({ browser, context, page }, testInfo) => { + test('Enable and disable original presentation download', async ({ browser, context, page }, testInfo) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.enableAndDisablePresentationDownload(testInfo); }); - test('Send presentation in the current state (with annotations) to chat for downloading', { tag: '@ci' }, async ({ browser, context, page }, testInfo) => { + test('Send presentation in the current state (with annotations) to chat for downloading', async ({ browser, context, page }, testInfo) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.sendPresentationToDownload(testInfo); }); - test('Remove all presentation', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Remove all presentations', async ({ browser, context, page }) => { const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.removeAllPresentation(); }); - test('Upload and remove all presentations', async ({ browser, context, page }) => { + test('Upload and remove all presentations', { tag: '@flaky' }, async ({ browser, context, page }) => { + // sometimes the uploaded presentation is not displayed in the manage presentations modal + linkIssue(21624); const presentation = new Presentation(browser, context); await presentation.initPages(page); await presentation.uploadAndRemoveAllPresentations(); }); - test('Remove previous presentation from previous presenter', async ({ browser, context, page }) => { + test('Remove previous presentation from previous presenter', { tag: '@flaky' }, async ({ browser, context, page }) => { + // missing the uploader presentation toast notification in some CI runs + linkIssue(21576) const presentation = new Presentation(browser, context); - await presentation.initModPage(page, true, { createParameter: customStyleAvoidUploadingNotifications }); + await presentation.initModPage(page, true); await presentation.initUserPage(true, context); await presentation.removePreviousPresentationFromPreviousPresenter(); }); diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/mod-hide-toolbars-Chromium-linux.png b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/mod-hide-toolbars-Chromium-linux.png new file mode 100644 index 000000000000..70420acdc942 Binary files /dev/null and b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/mod-hide-toolbars-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator-new-presentation-screenshot-Chromium-linux.png b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator-new-presentation-screenshot-Chromium-linux.png index 1b1701ccff19..24c7535e5c75 100644 Binary files a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator-new-presentation-screenshot-Chromium-linux.png and b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator-new-presentation-screenshot-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide10-Chromium-linux.png b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide10-Chromium-linux.png index d98866d231d9..106b0e083adf 100644 Binary files a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide10-Chromium-linux.png and b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide10-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide13-Chromium-linux.png b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide13-Chromium-linux.png index df0327b4e692..12e8bba9c6d3 100644 Binary files a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide13-Chromium-linux.png and b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide13-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide5-Chromium-linux.png b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide5-Chromium-linux.png index 3a420e8650d1..e4191c9814f2 100644 Binary files a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide5-Chromium-linux.png and b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/moderator1-select-slide5-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/user-toolbars-Chromium-linux.png b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/user-toolbars-Chromium-linux.png new file mode 100644 index 000000000000..3a470b250b22 Binary files /dev/null and b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/user-toolbars-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/viewer-new-presentation-screenshot-Chromium-linux.png b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/viewer-new-presentation-screenshot-Chromium-linux.png index 78f72359eb5d..ffc48b942c68 100644 Binary files a/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/viewer-new-presentation-screenshot-Chromium-linux.png and b/bigbluebutton-tests/playwright/presentation/presentation.spec.js-snapshots/viewer-new-presentation-screenshot-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/presentation/util.js b/bigbluebutton-tests/playwright/presentation/util.js index d072deee547f..cd2e02bcfa58 100644 --- a/bigbluebutton-tests/playwright/presentation/util.js +++ b/bigbluebutton-tests/playwright/presentation/util.js @@ -36,7 +36,7 @@ async function uploadSinglePresentation(test, fileName, uploadTimeout = UPLOAD_P await test.hasText('body', e.statingUploadPresentationToast, 'should display the toast message uploading the presentation'); await test.waitAndClick(e.confirmManagePresentation); - await test.hasElement(e.presentationUploadProgressToast, 'should display the toast presentation upload progress after confiming the presentation to be uploaded', ELEMENT_WAIT_EXTRA_LONG_TIME); + await test.hasElement(e.presentationUploadProgressToast, 'should display the toast presentation upload progress after confirming the presentation to be uploaded', ELEMENT_WAIT_EXTRA_LONG_TIME); await test.page.waitForFunction(([selector, firstSlideSrc]) => { const currentSrc = document.querySelector(selector) ?.style?.backgroundImage?.split('"')[1]; diff --git a/bigbluebutton-tests/playwright/reconnection/reconnection.spec.js b/bigbluebutton-tests/playwright/reconnection/reconnection.spec.js index 9e8f6da00a09..66ec9401b976 100644 --- a/bigbluebutton-tests/playwright/reconnection/reconnection.spec.js +++ b/bigbluebutton-tests/playwright/reconnection/reconnection.spec.js @@ -2,7 +2,10 @@ const { test } = require('../fixtures'); const { Reconnection } = require('./reconnection'); const { checkRootPermission } = require('../core/helpers'); -test.describe.parallel('Reconnection', () => { +test.describe.parallel('Reconnection', { tag: '@flaky' }, () => { + // @ci Note: both tests are failing due to "server closed connection" bug + // see issue https://github.com/bigbluebutton/bigbluebutton/issues/21147 + test('Chat', async ({ browser, context, page }) => { await checkRootPermission(); // check sudo permission before starting test const reconnection = new Reconnection(browser, context); diff --git a/bigbluebutton-tests/playwright/screenshare/screenshare.spec.js b/bigbluebutton-tests/playwright/screenshare/screenshare.spec.js index 662161c1b1aa..fbf4bdbf35be 100644 --- a/bigbluebutton-tests/playwright/screenshare/screenshare.spec.js +++ b/bigbluebutton-tests/playwright/screenshare/screenshare.spec.js @@ -1,54 +1,23 @@ const { test } = require('../fixtures'); -const { devices } = require('@playwright/test'); const { ScreenShare } = require('./screenshare'); +const { linkIssue } = require('../core/helpers'); -test.describe.parallel('Screenshare', () => { +test.describe.parallel('Screenshare', { tag: '@ci' }, () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#sharing-screen-in-full-screen-mode-automated - test('Share screen', { tag: '@ci' }, async ({ browser, browserName, page }) => { - test.skip(browserName === 'firefox' && process.env.DISPLAY === undefined, - 'Screenshare tests not able in Firefox browser without desktop' + test('Share screen', async ({ browser, browserName, page }) => { + test.skip(browserName === 'firefox', + 'Screenshare tests not able in Firefox browser without desktop', ); const screenshare = new ScreenShare(browser, page); await screenshare.init(true, true); await screenshare.startSharing(); }); - test('Start screenshare stops external video', { tag: [ '@ci', '@flaky' ] }, async ({ browser, page }) => { + test('Start screenshare stops external video', { tag: '@flaky' }, async ({ browser, page }) => { + // requiring logged user to start external video on CI environment + linkIssue(21589); const screenshare = new ScreenShare(browser, page); await screenshare.init(true, true); await screenshare.screenshareStopsExternalVideo(); }); - - test.describe.parallel('Mobile', () => { - test.beforeEach(({ browserName }) => { - test.skip(browserName === 'firefox', 'Mobile tests are not able in Firefox browser'); - }); - - test('Share screen unavailable on Mobile Android', async ({ browser }) => { - const motoG4 = devices['Moto G4']; - const context = await browser.newContext({ ...motoG4 }); - const page = await context.newPage(); - const screenshare = new ScreenShare(browser, page); - await screenshare.init(true, true); - await screenshare.testMobileDevice(); - }); - - test('Share screen unavailable on Mobile iPhone', async ({ browser }) => { - const iPhone11 = devices['iPhone 11']; - const context = await browser.newContext({ ...iPhone11 }); - const page = await context.newPage(); - const screenshare = new ScreenShare(browser, page); - await screenshare.init(true, true); - await screenshare.testMobileDevice(); - }); - - test('Share screen unavailable on Tablet iPad', async ({ browser }) => { - const iPadPro11 = devices['iPad Pro 11']; - const context = await browser.newContext({ ...iPadPro11 }); - const page = await context.newPage(); - const screenshare = new ScreenShare(browser, page); - await screenshare.init(true, true); - await screenshare.testMobileDevice(); - }); - }); }); diff --git a/bigbluebutton-tests/playwright/sharednotes/sharednotes.spec.js b/bigbluebutton-tests/playwright/sharednotes/sharednotes.spec.js index b7222e55dce4..eb015c37e846 100644 --- a/bigbluebutton-tests/playwright/sharednotes/sharednotes.spec.js +++ b/bigbluebutton-tests/playwright/sharednotes/sharednotes.spec.js @@ -3,7 +3,7 @@ const { SharedNotes } = require('./sharednotes'); const { linkIssue, initializePages } = require('../core/helpers'); const { fullyParallel } = require('../playwright.config'); -test.describe('Shared Notes', () => { +test.describe('Shared Notes', { tag: '@ci' }, () => { const sharedNotes = new SharedNotes(); test.describe.configure({ mode: fullyParallel ? 'parallel' : 'serial' }); @@ -11,23 +11,23 @@ test.describe('Shared Notes', () => { await initializePages(sharedNotes, browser, { isMultiUser: true }); }); - test('Open shared notes', { tag: '@ci' }, async () => { + test('Open shared notes', async () => { await sharedNotes.openSharedNotes(); }); - test('Type in shared notes', { tag: '@ci' }, async () => { + test('Type in shared notes', async () => { await sharedNotes.typeInSharedNotes(); }); - test('Formate text in shared notes', { tag: '@ci' }, async () => { + test('Formate text in shared notes', async () => { await sharedNotes.formatTextInSharedNotes(); }); - test('Export shared notes', { tag: '@ci' }, async ({}, testInfo) => { + test('Export shared notes', async ({}, testInfo) => { await sharedNotes.exportSharedNotes(testInfo); }); - test('Convert notes to presentation', { tag: '@ci' }, async () => { + test('Convert notes to presentation', async () => { await sharedNotes.convertNotesToWhiteboard(); }); @@ -39,8 +39,9 @@ test.describe('Shared Notes', () => { await sharedNotes.seeNotesWithoutEditPermission(); }); - test('Pin and unpin notes onto whiteboard', { tag: [ '@ci', '@flaky' ] }, async () => { + test('Pin and unpin notes onto whiteboard', { tag: '@flaky' }, async () => { linkIssue('20892'); + linkIssue('21283'); await sharedNotes.pinAndUnpinNotesOntoWhiteboard(); }); }); diff --git a/bigbluebutton-tests/playwright/stress/stress.spec.js b/bigbluebutton-tests/playwright/stress/stress.spec.js index db9e808bf0b6..a5f4e3326126 100644 --- a/bigbluebutton-tests/playwright/stress/stress.spec.js +++ b/bigbluebutton-tests/playwright/stress/stress.spec.js @@ -1,6 +1,8 @@ const { test } = require('../fixtures'); const { Stress } = require('./stress.js'); +// @ci Note: Stress tests are not intended to be run in CI + test.describe.parallel('Stress', () => { test.beforeEach(async () => test.setTimeout(0)); diff --git a/bigbluebutton-tests/playwright/user/guestPolicy.js b/bigbluebutton-tests/playwright/user/guestPolicy.js index a14c571ac791..0d269dd79066 100644 --- a/bigbluebutton-tests/playwright/user/guestPolicy.js +++ b/bigbluebutton-tests/playwright/user/guestPolicy.js @@ -66,7 +66,7 @@ class GuestPolicy extends MultiUsers { await this.modPage.waitAndClick(e.waitingUsersBtn); await this.modPage.waitAndClick(e.privateMessageGuest); - await this.modPage.type(e.inputPrivateLobbyMesssage, 'test'); + await this.modPage.type(e.inputPrivateLobbyMessage, 'test'); await this.modPage.waitAndClick(e.sendPrivateLobbyMessage); await this.userPage.hasText(e.guestMessage, /test/, 'should the guest message contain the text "test" for the attendee', ELEMENT_WAIT_LONGER_TIME); } diff --git a/bigbluebutton-tests/playwright/user/lockViewers.js b/bigbluebutton-tests/playwright/user/lockViewers.js index 470b626a0a0d..c1cf837e55fc 100644 --- a/bigbluebutton-tests/playwright/user/lockViewers.js +++ b/bigbluebutton-tests/playwright/user/lockViewers.js @@ -2,11 +2,14 @@ const { MultiUsers } = require("./multiusers"); const { openLockViewers, drawArrow } = require('./util'); const e = require('../core/elements'); const { expect } = require("@playwright/test"); -const { ELEMENT_WAIT_LONGER_TIME, ELEMENT_WAIT_TIME } = require("../core/constants"); +const { ELEMENT_WAIT_LONGER_TIME, ELEMENT_WAIT_TIME, PARAMETER_HIDE_PRESENTATION_TOAST } = require("../core/constants"); const { getNotesLocator } = require("../sharednotes/util"); const { waitAndClearNotification } = require("../notifications/util"); +const { encodeCustomParams } = require("../parameters/util"); const { sleep } = require("../core/helpers"); +const hidePresentationToast = encodeCustomParams(PARAMETER_HIDE_PRESENTATION_TOAST); + class LockViewers extends MultiUsers { constructor(browser, page) { super(browser, page); @@ -168,25 +171,49 @@ class LockViewers extends MultiUsers { await this.modPage.waitForSelector(e.whiteboard); await this.modPage.waitAndClick(e.multiUsersWhiteboardOn); await this.userPage.waitForSelector(e.whiteboard); + await sleep(1000); // timeout to ensure that the userPage presentation is zoomed in stabilized await drawArrow(this.userPage); + const screenshotOptions = { + maxDiffPixels: 250, + }; + // lock the viewers annotations await openLockViewers(this.modPage); await this.modPage.waitAndClickElement(e.hideViewersAnnotation); await this.modPage.waitAndClick(e.applyLockSettings); - - const screenshotOptions = { - maxDiffPixels: 1000, - }; - - await this.initUserPage2(true); - const userWbLocator = this.userPage2.getLocator(e.whiteboard); - await expect(userWbLocator).toHaveScreenshot('viewer2-no-arrow.png', screenshotOptions); - + await sleep(1000); // timeout to ensure the lock settings are applied + + // check if previous annotations is displayed for the viewer joining after the lock + await this.initUserPage2(true, this.modPage.context, { joinParameter: hidePresentationToast }); // avoid presentation toast notification due to screenshot comparisons + const user2WbLocator = this.userPage2.getLocator(e.whiteboard); + await this.userPage2.hasElement(e.whiteboard); + await sleep(1000); // timeout to ensure the user2 presentation is zoomed correctly + await this.userPage2.wasRemoved(e.wbDrawnArrow, 'should not display the other viewer annotation for the viewer who just joined'); + await this.userPage.getLocator(e.chatButton).hover(); // ensure userPage cursor won't be visible on the screenshot + await expect(user2WbLocator, 'should not display the other viewer annotation for the viewer who just joined').toHaveScreenshot('viewer2-just-joined.png', screenshotOptions); + + // draw a rectangle and check if it is displayed + await this.userPage.waitAndClick(e.wbShapesButton); + await this.userPage.waitAndClick(e.wbRectangleShape); + await this.userPage.waitAndClick(e.whiteboard); + await this.userPage.getLocator(e.chatButton).hover(); // ensure userPage cursor won't be visible on the screenshot + await this.userPage2.wasRemoved(e.wbDrawnShape, 'should not display the new annotation for the other viewer'); + await expect(user2WbLocator, 'should not display the new annotation for the other viewer').toHaveScreenshot('viewer2-no-rectangle.png', screenshotOptions); + + // unlock user2 await this.modPage.waitAndClick(`${e.userListItem}>>nth=1`); await this.modPage.waitAndClick(`${e.unlockUserButton}>>nth=1`); - const userWbLocatorArrow = this.userPage2.getLocator(e.whiteboard); - await expect(userWbLocatorArrow).toHaveScreenshot('viewer2-arrow.png', screenshotOptions); + // check if previous annotations is displayed after unlocking user + await this.userPage2.hasElement(e.wbDrawnArrow, 'should display the arrow drawn before user join'); + await this.userPage2.hasElement(e.wbDrawnShape, 'should display the rectangle drawn before unlocking user'); + await expect(user2WbLocator, 'should display the other viewer annotations when unlocking specific user').toHaveScreenshot('viewer2-previous-shapes.png', screenshotOptions); + + // check if new annotations is displayed after unlocking user + await drawArrow(this.userPage); + await this.userPage.getLocator(e.chatButton).hover(); // ensure userPage cursor will be visible on the screenshot + await this.userPage2.checkElementCount(e.wbDrawnArrow, 2, 'should display all arrows drawn for unlocked user'); + await expect(user2WbLocator, 'should display all arrows drawn for unlocked user').toHaveScreenshot('viewer2-new-arrow.png', screenshotOptions); } async lockSeeOtherViewersCursor() { @@ -203,13 +230,15 @@ class LockViewers extends MultiUsers { await this.modPage.checkElementCount(e.whiteboardCursorIndicator, 1, 'should contain one whiteboard cursor indicator for the moderator'); await this.initUserPage2(true); - await this.userPage2.checkElementCount(e.whiteboardCursorIndicator, 0, 'should contain zero whiteboard cursor indicator for the second attendee'); + await this.userPage2.checkElementCount(e.whiteboardCursorIndicator, 0, 'should contain no whiteboard cursor indicator for the second attendee when locking viewers cursor'); + // Unlock user2 await this.modPage.waitAndClick(`${e.userListItem}>>nth=1`); await this.modPage.waitAndClick(`${e.unlockUserButton}>>nth=1`); await drawArrow(this.userPage); - await this.userPage2.checkElementCount(e.whiteboardCursorIndicator, 1, 'should contain one whiteboard cursor indicator for the second attendee'); + await this.userPage.getLocator(e.whiteboard).hover(); // ensure userPage cursor will be visible on the screenshot + await this.userPage2.checkElementCount(e.whiteboardCursorIndicator, 1, 'should be displayed the other viewer whiteboard cursor indicator when unlocking user is unlocked'); } } diff --git a/bigbluebutton-tests/playwright/user/mobileDevices.js b/bigbluebutton-tests/playwright/user/mobileDevices.js index a490145cb60a..e242e102f76e 100644 --- a/bigbluebutton-tests/playwright/user/mobileDevices.js +++ b/bigbluebutton-tests/playwright/user/mobileDevices.js @@ -11,27 +11,6 @@ class MobileDevices extends MultiUsers { await this.modPage.waitForSelector(e.currentUser); await this.modPage.hasElement(e.mobileUser, 'should display the mobile user element for the moderator '); } - - async whiteboardNotAppearOnMobile() { - await this.modPage.waitForSelector(e.whiteboard); - await this.modPage.waitAndClick(e.userListButton); - await this.userPage.waitAndClick(e.userListButton); - await this.userPage.waitAndClick(e.chatButtonKey); - await this.modPage.wasRemoved(e.whiteboard, 'should not display the whiteboard for the moderator'); - await this.userPage.wasRemoved(e.whiteboard, 'should not display the whiteboard for the attendeee'); - } - - async userListNotAppearOnMobile() { - await this.modPage.wasRemoved(e.userListItem, 'should not display the user list for the moderator'); - await this.userPage.wasRemoved(e.userListItem, 'should not display the user list for the attendee'); - } - - async chatPanelNotAppearOnMobile() { - await this.modPage.wasRemoved(e.chatButtonKey, 'should not display the chat button key for the moderator'); - await this.userPage.waitAndClick(e.userListButton); - await this.userPage.waitAndClick(e.chatButtonKey); - await this.userPage.hasElement(e.chatButtonKey, 'should display the chat button key for the attendee'); - } } exports.MobileDevices = MobileDevices; diff --git a/bigbluebutton-tests/playwright/user/multiusers.js b/bigbluebutton-tests/playwright/user/multiusers.js index 2769d98021ef..2490108b52f2 100644 --- a/bigbluebutton-tests/playwright/user/multiusers.js +++ b/bigbluebutton-tests/playwright/user/multiusers.js @@ -99,7 +99,7 @@ class MultiUsers { 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'); const isPresenter = await checkIsPresenter(this.userPage); - await expect(isPresenter, 'should the attende be presenter').toBeTruthy(); + await expect(isPresenter, 'should the attendee be presenter').toBeTruthy(); } async takePresenter() { @@ -241,7 +241,7 @@ class MultiUsers { await this.modPage.waitAndClick(e.manageUsers); await this.modPage.waitAndClick(e.muteAllExceptPresenter); - await this.modPage.hasElement(e.isTalking, 'should display the is talking element for the moderator'); + await this.modPage.hasElement(e.isTalking, 'should display the is talking element only for the moderator - 1 item'); await checkMutedUsers(this.modPage2); await checkMutedUsers(this.userPage); } @@ -280,9 +280,9 @@ class MultiUsers { // Due to same reason above, sometimes it displays different messages try { - await this.modPage2.hasText(e.userBannedMessage2, /banned/, 'should display the banned message for the second moderator'); + await this.modPage2.hasText('body', /banned/, 'should display the banned message for the second moderator'); } catch { - await this.modPage2.hasText(e.userBannedMessage1, /removed/, 'should display the removed message for the second moderator'); + await this.modPage2.hasText('body', /removed/, 'should display the removed message for the second moderator'); } } } diff --git a/bigbluebutton-tests/playwright/user/user.spec.js b/bigbluebutton-tests/playwright/user/user.spec.js index d8a54ff135d5..512249797b41 100644 --- a/bigbluebutton-tests/playwright/user/user.spec.js +++ b/bigbluebutton-tests/playwright/user/user.spec.js @@ -12,8 +12,8 @@ const iPhone11 = devices['iPhone 11']; const hidePresentationToast = encodeCustomParams(PARAMETER_HIDE_PRESENTATION_TOAST); -test.describe.parallel('User', () => { - test.describe.parallel('Actions', { tag: '@ci' }, () => { +test.describe.parallel('User', { tag: '@ci' }, () => { + test.describe.parallel('Actions', () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#set-status--raise-hand-automated test('Raise and lower Hand', async ({ browser, context, page }) => { const multiusers = new MultiUsers(browser, context); @@ -46,7 +46,7 @@ test.describe.parallel('User', () => { }); }); - test.describe.parallel('List', { tag: '@ci' } , () => { + test.describe.parallel('List', () => { test('User presence check (multiple users)', async ({ browser, context, page }) => { const multiusers = new MultiUsers(browser, context); await multiusers.initPages(page); @@ -94,8 +94,7 @@ test.describe.parallel('User', () => { await multiusers.removeUser(); }); - // User is currently getting stuck when trying to rejoin - no error message is shown - test('Remove user and prevent rejoining', { tag: '@flaky' }, async ({ browser, context, page }) => { + test('Remove user and prevent rejoining', async ({ browser, context, page }) => { const multiusers = new MultiUsers(browser, context); await multiusers.initModPage(page, true); await multiusers.initModPage2(true, context, { joinParameter: 'userID=Moderator2' }); @@ -104,7 +103,7 @@ test.describe.parallel('User', () => { }); test.describe.parallel('Manage', () => { - test.describe.parallel('Guest policy', { tag: '@ci' }, () => { + test.describe.parallel('Guest policy', () => { test.describe.parallel('ASK_MODERATOR', () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#ask-moderator test('Message to guest lobby', async ({ browser, context, page }) => { @@ -129,7 +128,7 @@ test.describe.parallel('User', () => { await guestPolicy.rememberChoice(); }); - test.describe.parallel('Actions to specific pending user', { tag: '@ci' }, () => { + test.describe.parallel('Actions to specific pending user', () => { test('Message', async ({ browser, context, page }) => { const guestPolicy = new GuestPolicy(browser, context); await guestPolicy.initModPage(page); @@ -163,7 +162,7 @@ test.describe.parallel('User', () => { }); }); - test.describe.parallel('Lock viewers', { tag: '@ci' }, () => { + test.describe.parallel('Lock viewers', () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#webcam test('Lock Share webcam', async ({ browser, context, page }) => { const lockViewers = new LockViewers(browser, context); @@ -213,7 +212,7 @@ test.describe.parallel('User', () => { await lockViewers.lockSeeOtherViewersUserList(); }); - test('Lock see other viewers annotations', { tag: '@flaky' }, async ({ browser, context, page }) => { + test('Lock see other viewers annotations', async ({ browser, context, page }) => { const lockViewers = new LockViewers(browser, context); await lockViewers.initModPage(page, true, { joinParameter: hidePresentationToast }); await lockViewers.initUserPage(true, context, { joinParameter: hidePresentationToast }); @@ -221,6 +220,7 @@ test.describe.parallel('User', () => { }); test('Lock see other viewers cursor', { tag: '@flaky' }, async ({ browser, context, page }) => { + // Unlocking specific user not working, see https://github.com/bigbluebutton/bigbluebutton/issues/21297 const lockViewers = new LockViewers(browser, context); await lockViewers.initPages(page); await lockViewers.lockSeeOtherViewersCursor(); @@ -228,7 +228,7 @@ test.describe.parallel('User', () => { }); // https://docs.bigbluebutton.org/2.6/release-tests.html#saving-usernames - test('Save user names', { tag: '@ci' }, async ({ browser, context, page }, testInfo) => { + test('Save user names', async ({ browser, context, page }, testInfo) => { const multiusers = new MultiUsers(browser, context); await multiusers.initPages(page); await multiusers.saveUserNames(testInfo); @@ -242,7 +242,8 @@ test.describe.parallel('User', () => { await multiusers.muteAllUsers(); }); - test('Mute all users except presenter', async ({ browser, context, page }) => { + test('Mute all users except presenter', { tag: '@flaky' }, async ({ browser, context, page }) => { + // Feature not working, see https://github.com/bigbluebutton/bigbluebutton/issues/21174 const multiusers = new MultiUsers(browser, context); await multiusers.initModPage(page, false); await multiusers.initModPage2(false); @@ -256,44 +257,12 @@ test.describe.parallel('User', () => { test.skip(browserName === 'firefox', 'Mobile tests are not able in Firefox browser'); }); - test('Mobile Tag Name For Mobile User', { tag: '@ci' }, async ({ browser }) => { + test('Mobile Tag Name For Mobile User', async ({ browser }) => { const context = await browser.newContext({ ...iPhone11 }); const mobilePage = await context.newPage(); const mobileDevices = new MobileDevices(browser, context); await mobileDevices.initModPage(mobilePage); await mobileDevices.mobileTagName(); }); - - test('Whiteboard should not be accessible when chat panel or user list are active on mobile devices', async ({ browser }) => { - test.fixme(); - const iphoneContext = await browser.newContext({ ...iPhone11 }); - const motoContext = await browser.newContext({ ...motoG4 }); - const modPage = await iphoneContext.newPage(); - const mobileDevices = new MobileDevices(browser, iphoneContext); - await mobileDevices.initModPage(modPage); - await mobileDevices.initUserPage(true, motoContext); - await mobileDevices.whiteboardNotAppearOnMobile(); - }); - - test('User List should not appear when Chat Panel or Whiteboard are active on mobile devices', async ({ browser }) => { - test.fixme(); - const iphoneContext = await browser.newContext({ ...iPhone11 }); - const motoContext = await browser.newContext({ ...motoG4 }); - const modPage = await iphoneContext.newPage(); - const mobileDevices = new MobileDevices(browser, iphoneContext); - await mobileDevices.initModPage(modPage); - await mobileDevices.initUserPage(true, motoContext); - await mobileDevices.userListNotAppearOnMobile(); - }); - - test('Chat Panel should not appear when UserList or Whiteboard are active on mobile devices', async ({ browser }) => { - const iphoneContext = await browser.newContext({ ...iPhone11 }); - const motoContext = await browser.newContext({ ...motoG4 }); - const modPage = await iphoneContext.newPage(); - const mobileDevices = new MobileDevices(browser, iphoneContext); - await mobileDevices.initModPage(modPage); - await mobileDevices.initUserPage(true, motoContext); - await mobileDevices.chatPanelNotAppearOnMobile(); - }); }); }); diff --git a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-arrow-Chromium-linux.png b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-arrow-Chromium-linux.png deleted file mode 100644 index 6cca16f60d56..000000000000 Binary files a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-arrow-Chromium-linux.png and /dev/null differ diff --git a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-just-joined-Chromium-linux.png b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-just-joined-Chromium-linux.png new file mode 100644 index 000000000000..37cf1759762f Binary files /dev/null and b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-just-joined-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-new-arrow-Chromium-linux.png b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-new-arrow-Chromium-linux.png new file mode 100644 index 000000000000..73deb299415d Binary files /dev/null and b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-new-arrow-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-no-arrow-Chromium-linux.png b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-no-arrow-Chromium-linux.png deleted file mode 100644 index a4a6e051d021..000000000000 Binary files a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-no-arrow-Chromium-linux.png and /dev/null differ diff --git a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-no-rectangle-Chromium-linux.png b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-no-rectangle-Chromium-linux.png new file mode 100644 index 000000000000..37cf1759762f Binary files /dev/null and b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-no-rectangle-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-previous-shapes-Chromium-linux.png b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-previous-shapes-Chromium-linux.png new file mode 100644 index 000000000000..22f3099bee67 Binary files /dev/null and b/bigbluebutton-tests/playwright/user/user.spec.js-snapshots/viewer2-previous-shapes-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/virtualizedlist/virtualize.js b/bigbluebutton-tests/playwright/virtualizedlist/virtualize.js deleted file mode 100644 index e779d007ac82..000000000000 --- a/bigbluebutton-tests/playwright/virtualizedlist/virtualize.js +++ /dev/null @@ -1,38 +0,0 @@ -const { expect } = require('@playwright/test'); -const Page = require('../core/page'); -const e = require('../core/elements'); -const { USER_LIST_VLIST_BOTS_LISTENING } = require('../core/constants'); - -class VirtualizeList { - constructor(browser, page) { - this.page1 = new Page(browser, page); - this.browser = browser; - this.pagesArray = []; - } - - // Join BigBlueButton meeting - async init() { - await this.page1.init(true, true, { fullName: 'BroadCaster1' }); - await this.page1.waitForSelector(e.currentUser); - for (let i = 1; i <= parseInt(USER_LIST_VLIST_BOTS_LISTENING); i++) { - const newPage = await this.browser.newPage(); - const viewerPage = new Page(this.browser, newPage); - const fullName = `Viewer-${i}`; - await viewerPage.init(false, true, { fullName, meetingId: this.page1.meetingId }); - - console.log(`${fullName} joined`); - this.pagesArray.push(viewerPage); - } - } - - async test() { - const USER_LIST_VLIST_VISIBLE_USERS = await this.page1.getSelectorCount(e.userListItem); - const totalNumberOfUsersMongo = await this.page1.page.evaluate(() => { - const collection = require('/imports/api/users/index.js'); - return collection.default._collection.find().count(); - }); - await expect(USER_LIST_VLIST_VISIBLE_USERS).toBeLessThan(totalNumberOfUsersMongo); - } -} - -exports.VirtualizeList = VirtualizeList; diff --git a/bigbluebutton-tests/playwright/virtualizedlist/virtualizedlist.spec.js b/bigbluebutton-tests/playwright/virtualizedlist/virtualizedlist.spec.js deleted file mode 100644 index ae8f72c0e64b..000000000000 --- a/bigbluebutton-tests/playwright/virtualizedlist/virtualizedlist.spec.js +++ /dev/null @@ -1,11 +0,0 @@ -const { test } = require('../fixtures'); -const { VirtualizeList } = require('./virtualize'); - -test.describe.parallel('Virtualize list', () => { - test('Virtualized Users List', async ({ browser, page }) => { - test.setTimeout(0); - const virtualizeList = new VirtualizeList(browser, page); - await virtualizeList.init(); - await virtualizeList.test(); - }); -}); diff --git a/bigbluebutton-tests/playwright/webcam/webcam.js b/bigbluebutton-tests/playwright/webcam/webcam.js index 97a1ce28db93..f13cf26dcedc 100644 --- a/bigbluebutton-tests/playwright/webcam/webcam.js +++ b/bigbluebutton-tests/playwright/webcam/webcam.js @@ -84,6 +84,7 @@ class Webcam extends Page { }); await this.waitAndClick(e.dropdownWebcamButton); await this.waitAndClick(e.webcamsFullscreenButton); + await sleep(1000); // timeout to ensure the video is in fullscreen // get fullscreen webcam size const { width, height } = await this.getLocator('video').boundingBox(); await expect(width + 1, 'should the width to be the same as window width').toBe(windowWidth); // not sure why there is a difference of 1 pixel diff --git a/bigbluebutton-tests/playwright/webcam/webcam.spec.js b/bigbluebutton-tests/playwright/webcam/webcam.spec.js index c181e2a6845e..4f9de273ecc4 100644 --- a/bigbluebutton-tests/playwright/webcam/webcam.spec.js +++ b/bigbluebutton-tests/playwright/webcam/webcam.spec.js @@ -2,9 +2,9 @@ const { test } = require('../fixtures'); const { MultiUsers } = require('../user/multiusers'); const { Webcam } = require('./webcam'); -test.describe.parallel('Webcam', () => { +test.describe.parallel('Webcam', { tag: '@ci' }, () => { // https://docs.bigbluebutton.org/2.6/release-tests.html#joining-webcam-automated - test('Shares webcam', { tag: '@ci' }, async ({ browser, page }) => { + test('Shares webcam', async ({ browser, page }) => { const webcam = new Webcam(browser, page); await webcam.init(true, true); await webcam.share(); @@ -16,13 +16,13 @@ test.describe.parallel('Webcam', () => { await webcam.checksContent(); }); - test('Webcam talking indicator', { tag: '@ci' }, async ({ browser, page }) => { + test('Webcam talking indicator', async ({ browser, page }) => { const webcam = new Webcam(browser, page); await webcam.init(true, false); await webcam.talkingIndicator(); }); - test('Pinning and unpinning webcams', { tag: '@ci' }, async ({ browser, context, page }) => { + test('Pinning and unpinning webcams', async ({ browser, context, page }) => { const webcam = new MultiUsers(browser, context); await webcam.initModPage(page); await webcam.initUserPage(); @@ -30,7 +30,8 @@ test.describe.parallel('Webcam', () => { await webcam.pinningWebcams(); }); - test('Change video quality', async ({ browser, page }) => { + test('Change video quality', { tag: '@flaky' } , async ({ browser, page }) => { + // Current approach is not reliable enough to ensure the video quality is changed const webcam = new Webcam(browser, page); await webcam.init(true, true); await webcam.changeVideoQuality(); @@ -42,13 +43,13 @@ test.describe.parallel('Webcam', () => { await webcam.webcamFullscreen(); }); - test('Disable Self-view', { tag: '@ci' }, async ({ browser, page }) => { + test('Disable Self-view', async ({ browser, page }) => { const webcam = new Webcam(browser, page); await webcam.init(true, true); await webcam.disableSelfView(); }); - test.describe('Webcam background', { tag: '@ci' }, () => { + test.describe('Webcam background', () => { test('Select one of the default backgrounds', async ({ browser, page }) => { const webcam = new Webcam(browser, page); await webcam.init(true, true); diff --git a/bigbluebutton-tests/playwright/whiteboard/deleteDrawing.js b/bigbluebutton-tests/playwright/whiteboard/deleteDrawing.js index df1f11f0d1ed..ab799a809d50 100644 --- a/bigbluebutton-tests/playwright/whiteboard/deleteDrawing.js +++ b/bigbluebutton-tests/playwright/whiteboard/deleteDrawing.js @@ -1,4 +1,3 @@ -const { expect } = require('@playwright/test'); const e = require('../core/elements'); const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); const { MultiUsers } = require('../user/multiusers'); @@ -10,19 +9,19 @@ class DeleteDrawing extends MultiUsers { async test() { await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME); - const modWbLocator = this.modPage.getLocator(e.whiteboard); const wbBox = await modWbLocator.boundingBox(); - + // draw an arrow await this.modPage.waitAndClick(e.wbArrowShape); - await this.modPage.page.mouse.move(wbBox.x + 0.3 * wbBox.width, wbBox.y + 0.3 * wbBox.height); await this.modPage.page.mouse.down(); await this.modPage.page.mouse.move(wbBox.x + 0.7 * wbBox.width, wbBox.y + 0.7 * wbBox.height); await this.modPage.page.mouse.up(); - - await this.modPage.waitAndClick(e.wbDelete); - + // check existence of the drawn arrow + await this.modPage.hasElement(e.wbDrawnArrow); + await this.userPage.hasElement(e.wbDrawnArrow); + // delete the drawn arrow + await this.modPage.press('Delete'); await this.modPage.wasRemoved(e.wbDrawnArrow); await this.userPage.wasRemoved(e.wbDrawnArrow); } diff --git a/bigbluebutton-tests/playwright/whiteboard/drawEllipse.js b/bigbluebutton-tests/playwright/whiteboard/drawEllipse.js index 3e067f2881f1..199110e54ef4 100644 --- a/bigbluebutton-tests/playwright/whiteboard/drawEllipse.js +++ b/bigbluebutton-tests/playwright/whiteboard/drawEllipse.js @@ -1,8 +1,7 @@ const { expect } = require('@playwright/test'); const e = require('../core/elements'); -const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); +const { ELEMENT_WAIT_LONGER_TIME, CI } = require('../core/constants'); const { MultiUsers } = require('../user/multiusers'); -const CI = process.env.CI === 'true'; class DrawEllipse extends MultiUsers { constructor(browser, context) { @@ -24,7 +23,7 @@ class DrawEllipse extends MultiUsers { await this.modPage.page.mouse.up(); await this.modPage.hasElement(e.wbDrawnShape); - if(CI) { + if (!CI) { await this.modPage.setHeightWidthViewPortSize(); await this.userPage.setHeightWidthViewPortSize(); await expect(modWbLocator).toHaveScreenshot('moderator-ellipse.png'); diff --git a/bigbluebutton-tests/playwright/whiteboard/drawLine.js b/bigbluebutton-tests/playwright/whiteboard/drawLine.js index aa7545cbab46..7f776b87f624 100644 --- a/bigbluebutton-tests/playwright/whiteboard/drawLine.js +++ b/bigbluebutton-tests/playwright/whiteboard/drawLine.js @@ -1,8 +1,6 @@ -const { expect } = require('@playwright/test'); const e = require('../core/elements'); const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); const { MultiUsers } = require('../user/multiusers'); -const CI = process.env.CI === 'true'; class DrawLine extends MultiUsers { constructor(browser, context) { diff --git a/bigbluebutton-tests/playwright/whiteboard/drawRectangle.js b/bigbluebutton-tests/playwright/whiteboard/drawRectangle.js index 36586ba74327..e9c64289adc8 100644 --- a/bigbluebutton-tests/playwright/whiteboard/drawRectangle.js +++ b/bigbluebutton-tests/playwright/whiteboard/drawRectangle.js @@ -1,8 +1,6 @@ -const { expect } = require('@playwright/test'); const e = require('../core/elements'); const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); const { MultiUsers } = require('../user/multiusers'); -const CI = process.env.CI === 'true'; class DrawRectangle extends MultiUsers { constructor(browser, context) { diff --git a/bigbluebutton-tests/playwright/whiteboard/drawTriangle.js b/bigbluebutton-tests/playwright/whiteboard/drawTriangle.js index 3514835879fa..760f2957f3f4 100644 --- a/bigbluebutton-tests/playwright/whiteboard/drawTriangle.js +++ b/bigbluebutton-tests/playwright/whiteboard/drawTriangle.js @@ -1,8 +1,6 @@ -const { expect } = require('@playwright/test'); const e = require('../core/elements'); const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); const { MultiUsers } = require('../user/multiusers'); -const CI = process.env.CI === 'true'; class DrawTriangle extends MultiUsers { constructor(browser, context) { diff --git a/bigbluebutton-tests/playwright/whiteboard/pan.js b/bigbluebutton-tests/playwright/whiteboard/pan.js index 8e0695c7d5ab..012621aa9c25 100644 --- a/bigbluebutton-tests/playwright/whiteboard/pan.js +++ b/bigbluebutton-tests/playwright/whiteboard/pan.js @@ -21,7 +21,7 @@ class Pan extends MultiUsers { for(let i = 100; i < 200; i += 25) { const currentZoomLabel = await zoomResetBtn.textContent(); await this.modPage.waitAndClick(e.zoomInButton); - await expect(zoomResetBtn).not.toContainText(currentZoomLabel); + await expect(zoomResetBtn, 'reset zoom button label should change after clicking to zoom in').not.toContainText(currentZoomLabel); } await this.modPage.page.mouse.move(wbBox.x + 0.3 * wbBox.width, wbBox.y + 0.3 * wbBox.height); diff --git a/bigbluebutton-tests/playwright/whiteboard/shapeOptions.js b/bigbluebutton-tests/playwright/whiteboard/shapeOptions.js index 410f386ad90f..527423f7496f 100644 --- a/bigbluebutton-tests/playwright/whiteboard/shapeOptions.js +++ b/bigbluebutton-tests/playwright/whiteboard/shapeOptions.js @@ -2,7 +2,6 @@ const { expect } = require('@playwright/test'); const e = require('../core/elements'); const { ELEMENT_WAIT_LONGER_TIME } = require('../core/constants'); const { MultiUsers } = require('../user/multiusers'); -const { sleep } = require('../core/helpers'); class ShapeOptions extends MultiUsers { constructor(browser, context) { diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js index b0cd31d35669..1c0442a9b424 100644 --- a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js +++ b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js @@ -17,6 +17,7 @@ const { RedoDrawing } = require('./redoDraw'); const { ChangeStyles } = require('./changeStyles'); const { RealTimeText } = require('./realTimeText'); const { ShapeOptions } = require('./shapeOptions'); +const { linkIssue } = require('../core/helpers'); const hidePresentationToast = encodeCustomParams(PARAMETER_HIDE_PRESENTATION_TOAST); @@ -73,14 +74,18 @@ test.describe.parallel('Whiteboard tools', { tag: ['@ci', '@flaky'] }, () => { await drawText.test(); }); - test('Create sticky note', { tag: '@flaky'}, async ({ browser, context, page }) => { + test('Create sticky note', { tag: '@flaky' }, async ({ browser, context, page }) => { + // wrong/unexpected slide zoom for some users causing screenshot comparison to fail + linkIssue(21302); const drawStickyNote = new DrawStickyNote(browser, context); await drawStickyNote.initModPage(page, true, { customMeetingId: 'draw_sticky_meeting', joinParameter: hidePresentationToast }); await drawStickyNote.initUserPage(true, context, { joinParameter: hidePresentationToast }); await drawStickyNote.test(); }); - test('Pan', { tag: '@flaky'}, async ({ browser, context, page }) => { + test('Pan', { tag: '@flaky' } , async ({ browser, context, page }) => { + // different zoom position when clicking toolbar's zoom button + linkIssue(21266); const pan = new Pan(browser, context); await pan.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await pan.initUserPage(true, context, { joinParameter: hidePresentationToast }); @@ -101,28 +106,28 @@ test.describe.parallel('Whiteboard tools', { tag: ['@ci', '@flaky'] }, () => { await drawArrow.test(); }); - test.describe.parallel('Change Shapes Styles', { tag: '@ci'}, async () => { + test.describe.parallel('Change Shapes Styles', async () => { test('Change color', async ({ browser, context, page }) => { const changeColor = new ChangeStyles(browser, context); await changeColor.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await changeColor.initUserPage(true, context, { joinParameter: hidePresentationToast }); await changeColor.changingColor(); }); - + test('Fill drawing', async ({ browser, context, page }) => { const fillDrawing = new ChangeStyles(browser, context); await fillDrawing.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await fillDrawing.initUserPage(true, context, { joinParameter: hidePresentationToast }); await fillDrawing.fillDrawing(); }); - + test('Dash drawing', async ({ browser, context, page }) => { const dashDrawing = new ChangeStyles(browser, context); await dashDrawing.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await dashDrawing.initUserPage(true, context, { joinParameter: hidePresentationToast }); await dashDrawing.dashDrawing(); }); - + test('Size drawing', async ({ browser, context, page }) => { const sizeDrawing = new ChangeStyles(browser, context); await sizeDrawing.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); @@ -131,44 +136,50 @@ test.describe.parallel('Whiteboard tools', { tag: ['@ci', '@flaky'] }, () => { }); }); - test('Delete drawing', { tag: '@flaky'}, async ({ browser, context, page }) => { + test('Delete drawing', async ({ browser, context, page }) => { const deleteDrawing = new DeleteDrawing(browser, context); await deleteDrawing.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await deleteDrawing.initUserPage(true, context, { joinParameter: hidePresentationToast }); await deleteDrawing.test(); }); - test('Undo drawing', { tag: '@ci'}, async ({ browser, context, page }) => { + test.fixme('Undo drawing', async ({ browser, context, page }) => { + // action button has been removed on #21738 + // alternative: use keyboard shortcut const undoDrawing = new UndoDrawing(browser, context); await undoDrawing.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await undoDrawing.initUserPage(true, context, { joinParameter: hidePresentationToast }); await undoDrawing.test(); }); - test('Redo drawing', { tag: '@ci'}, async ({ browser, context, page }) => { + test.fixme('Redo drawing', async ({ browser, context, page }) => { + // action button has been removed on #21738 + // alternative: use keyboard shortcut const redoDrawing = new RedoDrawing(browser, context); await redoDrawing.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await redoDrawing.initUserPage(true, context, { joinParameter: hidePresentationToast }); await redoDrawing.test(); }); - - - test('Real time text typing', { tag: '@ci'}, async ({ browser, context, page }) => { + test('Real time text typing', async ({ browser, context, page }) => { const realTimeText = new RealTimeText(browser, context); await realTimeText.initModPage(page, true, { customMeetingId: 'draw_line_meeting', joinParameter: hidePresentationToast }); await realTimeText.initUserPage(true, context, { joinParameter: hidePresentationToast }); await realTimeText.realTimeTextTyping(); }); - test.describe.parallel('Shape Options', { tag: ['@ci', '@flaky']}, () => { - test('Duplicate', async ({ browser, context, page }) => { + test.describe.parallel('Shape Options', { tag: '@flaky' }, () => { + // wrong/unexpected slide zoom for some users causing screenshot comparison to fail + // see https://github.com/bigbluebutton/bigbluebutton/issues/21302 + test.fixme('Duplicate', async ({ browser, context, page }) => { + // action button has been removed on #21738 + // alternative: use keyboard shortcut const shapeOptions = new ShapeOptions(browser, context); await shapeOptions.initModPage(page, true); await shapeOptions.initUserPage(true, context); await shapeOptions.duplicate(); }); - + test('Rotate', async ({ browser, context, page }) => { const shapeOptions = new ShapeOptions(browser, context); await shapeOptions.initModPage(page, true); diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-change-color-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-change-color-Chromium-linux.png index d9fb23859fef..7b4f478b0f57 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-change-color-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-change-color-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-dash-drawing-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-dash-drawing-Chromium-linux.png index 15aa10978831..48b331587f23 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-dash-drawing-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-dash-drawing-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-ellipse-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-ellipse-Chromium-linux.png index e6ee0640e360..4a40aa9941b6 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-ellipse-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-ellipse-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-fill-drawing-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-fill-drawing-Chromium-linux.png index e3192d5ef034..2f0aee854723 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-fill-drawing-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-fill-drawing-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-2-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-2-Chromium-linux.png index fcfa3a1a7ed4..3314f9c0ed70 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-2-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-2-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-Chromium-linux.png index 1576c8579707..67ffb4a6d2ee 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-realtime-text-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-rotate-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-rotate-Chromium-linux.png index faa726798f5d..2da410cee49f 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-rotate-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-rotate-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-size-drawing-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-size-drawing-Chromium-linux.png index d39a311f5a0e..6a117e2b41ae 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-size-drawing-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-size-drawing-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-sticky-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-sticky-Chromium-linux.png index 1c516b81dec6..62a3921fdf37 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-sticky-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/moderator-sticky-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-change-color-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-change-color-Chromium-linux.png index cdd7e47d7be1..42b3a4ab1ba0 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-change-color-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-change-color-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-dash-drawing-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-dash-drawing-Chromium-linux.png index 7e03e0396e17..c4cff552cc8d 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-dash-drawing-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-dash-drawing-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-ellipse-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-ellipse-Chromium-linux.png index fb5feb7de798..ba1840c59052 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-ellipse-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-ellipse-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-fill-drawing-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-fill-drawing-Chromium-linux.png index 7c3c92573d27..8abf803c637a 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-fill-drawing-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-fill-drawing-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-2-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-2-Chromium-linux.png index 2a8fa57ca67d..541e57ff4779 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-2-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-2-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-Chromium-linux.png index 5cb7857675ce..b81eeb0414b3 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-realtime-text-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-rotate-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-rotate-Chromium-linux.png index a51e9416fb70..13fee524c89c 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-rotate-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-rotate-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-size-drawing-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-size-drawing-Chromium-linux.png index e82356c9b219..e80fa9432550 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-size-drawing-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-size-drawing-Chromium-linux.png differ diff --git a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-sticky-Chromium-linux.png b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-sticky-Chromium-linux.png index 8f182139ac83..1732d9070ba2 100644 Binary files a/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-sticky-Chromium-linux.png and b/bigbluebutton-tests/playwright/whiteboard/whiteboard.spec.js-snapshots/viewer-sticky-Chromium-linux.png differ