From 2bcee71daf5ad81ce438e8db202ed77514000e15 Mon Sep 17 00:00:00 2001 From: Jessica Schelly Souza Date: Fri, 7 Nov 2025 13:14:17 -0300 Subject: [PATCH 1/7] test: improve e2ee encryption tests to use page objects --- .../e2ee-encrypted-channels.spec.ts | 143 +++++++----------- .../e2ee-file-encryption.spec.ts | 15 +- .../e2e-encryption/e2ee-legacy-format.spec.ts | 5 +- .../e2ee-passphrase-management.spec.ts | 9 +- .../e2ee-server-settings.spec.ts | 9 +- .../tests/e2e/page-objects/fragments/e2ee.ts | 32 ++++ .../page-objects/fragments/home-content.ts | 8 + .../tests/e2e/page-objects/fragments/index.ts | 3 + .../e2e/page-objects/fragments/message.ts | 10 ++ .../fragments/pinned-messages-tab.ts | 33 ++++ .../page-objects/fragments/room-toolbar.ts | 39 +++++ .../fragments/starred-messages-tab.ts | 33 ++++ 12 files changed, 237 insertions(+), 102 deletions(-) create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts create mode 100644 apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts index 7720ed0cab9f0..2a7027e675375 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts @@ -2,6 +2,10 @@ import { faker } from '@faker-js/faker'; import { Users } from '../fixtures/userStates'; import { HomeChannel } from '../page-objects'; +import { EncryptedRoomPage } from '../page-objects/encrypted-room'; +import { E2EEMessageActions, EnableRoomEncryptionModal } from '../page-objects/fragments/e2ee'; +import { PinnedMessagesTab } from '../page-objects/fragments/pinned-messages-tab'; +import { StarredMessagesTab } from '../page-objects/fragments/starred-messages-tab'; import { preserveSettings } from '../utils/preserveSettings'; import { test, expect } from '../utils/test'; @@ -16,6 +20,11 @@ preserveSettings(settingsList); test.describe('E2EE Encrypted Channels', () => { let poHomeChannel: HomeChannel; + let encryptedRoomPage: EncryptedRoomPage; + let e2eeMessageActions: E2EEMessageActions; + let enableEncryptionModal: EnableRoomEncryptionModal; + let pinnedMessagesTab: PinnedMessagesTab; + let starredMessagesTab: StarredMessagesTab; test.use({ storageState: Users.userE2EE.state }); @@ -29,6 +38,11 @@ test.describe('E2EE Encrypted Channels', () => { test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); + encryptedRoomPage = new EncryptedRoomPage(page); + e2eeMessageActions = new E2EEMessageActions(page); + enableEncryptionModal = new EnableRoomEncryptionModal(page); + pinnedMessagesTab = new PinnedMessagesTab(page); + starredMessagesTab = new StarredMessagesTab(page); await page.goto('/home'); }); @@ -44,7 +58,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('hello world'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await poHomeChannel.tabs.kebab.click({ force: true }); @@ -58,7 +72,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('hello world not encrypted'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world not encrypted'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).not.toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).not.toBeVisible(); await poHomeChannel.tabs.kebab.click({ force: true }); await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible(); @@ -71,7 +85,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('hello world encrypted again'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world encrypted again'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); }); test('expect create a private encrypted channel and send a encrypted thread message', async ({ page }) => { @@ -86,7 +100,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('This is the thread main message.'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is the thread main message.'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await page.locator('[data-qa-type="message"]').last().hover(); await page.locator('role=button[name="Reply in thread"]').click(); @@ -97,8 +111,7 @@ test.describe('E2EE Encrypted Channels', () => { await expect(poHomeChannel.content.mainThreadMessageText.locator('.rcx-icon--name-key')).toBeVisible(); await poHomeChannel.content.toggleAlsoSendThreadToChannel(true); - await page.getByRole('dialog').locator('[name="msg"]').last().fill('This is an encrypted thread message also sent in channel'); - await page.keyboard.press('Enter'); + await poHomeChannel.content.sendMessageInThread('This is an encrypted thread message also sent in channel'); await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is an encrypted thread message also sent in channel'); await expect(poHomeChannel.content.lastThreadMessageText.locator('.rcx-icon--name-key')).toBeVisible(); await expect(poHomeChannel.content.lastUserMessage).toContainText('This is an encrypted thread message also sent in channel'); @@ -118,15 +131,15 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('This is an encrypted message.'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); - await page.locator('[data-qa-type="message"]').last().hover(); - await expect(page.locator('role=button[name="Forward message not available on encrypted content"]')).toBeDisabled(); + await poHomeChannel.content.lastUserMessage.hover(); + await e2eeMessageActions.expectForwardMessageToBeDisabled(); await poHomeChannel.content.openLastMessageMenu(); - await expect(page.locator('role=menuitem[name="Reply in direct message"]')).toHaveClass(/disabled/); - await expect(page.locator('role=menuitem[name="Copy link"]')).toHaveClass(/disabled/); + await e2eeMessageActions.expectReplyInDirectMessageToBeDisabled(); + await e2eeMessageActions.expectCopyLinkToBeDisabled(); }); test('expect create a private channel, encrypt it and send an encrypted message', async ({ page }) => { @@ -143,21 +156,15 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.dismissToast(); await poHomeChannel.tabs.kebab.click(); - // TODO(@jessicaschelly/@dougfabris): fix this flaky behavior - if (!(await poHomeChannel.tabs.btnEnableE2E.isVisible())) { - await poHomeChannel.tabs.kebab.click(); - } + await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible(); await poHomeChannel.tabs.btnEnableE2E.click(); - await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible(); - await page.getByRole('button', { name: 'Enable encryption' }).click(); - await page.waitForTimeout(1000); - + await enableEncryptionModal.enable(); await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible(); await poHomeChannel.content.sendMessage('hello world'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); }); test('expect create a encrypted private channel and mention user', async ({ page }) => { @@ -171,11 +178,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('hello @user1'); - const userMention = page.getByRole('button', { - name: 'user1', - }); - - await expect(userMention).toBeVisible(); + await expect(poHomeChannel.content.getUserMention('user1')).toBeVisible(); }); test('expect create a encrypted private channel, mention a channel and navigate to it', async ({ page }) => { @@ -189,13 +192,9 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('Are you in the #general channel?'); - const channelMention = page.getByRole('button', { - name: 'general', - }); + await expect(poHomeChannel.content.getChannelMention('general')).toBeVisible(); - await expect(channelMention).toBeVisible(); - - await channelMention.click(); + await poHomeChannel.content.getChannelMention('general').click(); await expect(page).toHaveURL(`/channel/general`); }); @@ -211,16 +210,8 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage('Are you in the #general channel, @user1 ?'); - const channelMention = page.getByRole('button', { - name: 'general', - }); - - const userMention = page.getByRole('button', { - name: 'user1', - }); - - await expect(userMention).toBeVisible(); - await expect(channelMention).toBeVisible(); + await expect(poHomeChannel.content.getUserMention('user1')).toBeVisible(); + await expect(poHomeChannel.content.getChannelMention('general')).toBeVisible(); }); test('expect create a private channel, send unecrypted messages, encrypt the channel and delete the last message and check the last message in the sidebar', async ({ @@ -260,13 +251,7 @@ test.describe('E2EE Encrypted Channels', () => { // Delete last message await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(encriptedMessage2); - await poHomeChannel.content.openLastMessageMenu(); - // TODO(@jessicaschelly/@dougfabris): fix this flaky behavior - if (!(await page.locator('role=menuitem[name="Delete"]').isVisible())) { - await poHomeChannel.content.openLastMessageMenu(); - } - await page.locator('role=menuitem[name="Delete"]').click(); - await page.locator('#modal-root .rcx-button-group--align-end .rcx-button--danger').click(); + await poHomeChannel.content.deleteLastMessage(); // Check last message in the sidebar const sidebarChannel = poHomeChannel.sidenav.getSidebarItemByName(channelName); @@ -283,48 +268,35 @@ test.describe('E2EE Encrypted Channels', () => { await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible(); - await poHomeChannel.content.sendMessage('This message should be pinned and stared.'); + await poHomeChannel.content.sendMessage('This message should be pinned and starred.'); - await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This message should be pinned and stared.'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This message should be pinned and starred.'); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await poHomeChannel.content.openLastMessageMenu(); - await page.locator('role=menuitem[name="Star"]').click(); + await poHomeChannel.content.btnOptionStarMessage.click(); await expect(poHomeChannel.toastSuccess).toBeVisible(); await poHomeChannel.dismissToast(); await poHomeChannel.content.openLastMessageMenu(); - await page.locator('role=menuitem[name="Pin"]').click(); - await page.locator('#modal-root >> button:has-text("Yes, pin message")').click(); + await poHomeChannel.content.btnOptionPinMessage.click(); + await poHomeChannel.content.btnModalConfirm.click(); await expect(poHomeChannel.toastSuccess).toBeVisible(); await poHomeChannel.dismissToast(); - await poHomeChannel.tabs.kebab.click(); - await poHomeChannel.tabs.btnPinnedMessagesList.click(); - - await expect(page.getByRole('dialog', { name: 'Pinned Messages' })).toBeVisible(); - - const lastPinnedMessage = page.getByRole('dialog', { name: 'Pinned Messages' }).locator('[data-qa-type="message"]').last(); - await expect(lastPinnedMessage).toContainText('This message should be pinned and stared.'); - await lastPinnedMessage.hover(); - await lastPinnedMessage.locator('role=button[name="More"]').waitFor(); - await lastPinnedMessage.locator('role=button[name="More"]').click(); - await expect(page.locator('role=menuitem[name="Copy link"]')).toHaveClass(/disabled/); + await pinnedMessagesTab.openTab(); + await pinnedMessagesTab.expectLastMessageToContainText('This message should be pinned and starred.'); + await pinnedMessagesTab.openLastMessageMenu(); + await e2eeMessageActions.expectCopyLinkToBeDisabled(); await poHomeChannel.btnContextualbarClose.click(); - await poHomeChannel.tabs.kebab.click(); - await poHomeChannel.tabs.btnStarredMessageList.click(); - - const lastStarredMessage = page.getByRole('dialog', { name: 'Starred Messages' }).locator('[data-qa-type="message"]').last(); - await expect(page.getByRole('dialog', { name: 'Starred Messages' })).toBeVisible(); - await expect(lastStarredMessage).toContainText('This message should be pinned and stared.'); - await lastStarredMessage.hover(); - await lastStarredMessage.locator('role=button[name="More"]').waitFor(); - await lastStarredMessage.locator('role=button[name="More"]').click(); - await expect(page.locator('role=menuitem[name="Copy link"]')).toHaveClass(/disabled/); + await starredMessagesTab.openTab(); + await starredMessagesTab.expectLastMessageToContainText('This message should be pinned and starred.'); + await starredMessagesTab.openLastMessageMenu(); + await e2eeMessageActions.expectCopyLinkToBeDisabled(); }); test('expect to edit encrypted message', async ({ page }) => { @@ -339,7 +311,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage(originalMessage); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(originalMessage); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await poHomeChannel.content.openLastMessageMenu(); await poHomeChannel.content.btnOptionEditMessage.click(); @@ -348,7 +320,7 @@ test.describe('E2EE Encrypted Channels', () => { await page.keyboard.press('Enter'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(editedMessage); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); }); test('expect to edit encrypted message to include mention', async ({ page }) => { @@ -363,7 +335,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.sendMessage(originalMessage); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(originalMessage); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await poHomeChannel.content.openLastMessageMenu(); await poHomeChannel.content.btnOptionEditMessage.click(); @@ -372,18 +344,9 @@ test.describe('E2EE Encrypted Channels', () => { await page.keyboard.press('Enter'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(displayedMessage); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); - - const userMention = page.getByRole('button', { - name: 'user1', - }); - - await expect(userMention).toBeVisible(); - - const channelMention = page.getByRole('button', { - name: 'general', - }); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); - await expect(channelMention).toBeVisible(); + await expect(poHomeChannel.content.getUserMention('user1')).toBeVisible(); + await expect(poHomeChannel.content.getChannelMention('general')).toBeVisible(); }); }); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts index bfb18e84f4b3f..7591ebf02de50 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts @@ -2,6 +2,7 @@ import { faker } from '@faker-js/faker'; import { Users } from '../fixtures/userStates'; import { HomeChannel } from '../page-objects'; +import { EncryptedRoomPage } from '../page-objects/encrypted-room'; import { preserveSettings } from '../utils/preserveSettings'; import { test, expect } from '../utils/test'; @@ -17,6 +18,7 @@ const originalSettings = preserveSettings(settingsList); test.describe('E2EE File Encryption', () => { let poHomeChannel: HomeChannel; + let encryptedRoomPage: EncryptedRoomPage; test.use({ storageState: Users.userE2EE.state }); @@ -35,6 +37,7 @@ test.describe('E2EE File Encryption', () => { test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); + encryptedRoomPage = new EncryptedRoomPage(page); await page.goto('/home'); }); @@ -55,7 +58,7 @@ test.describe('E2EE File Encryption', () => { await poHomeChannel.content.fileNameInput.fill('any_file1.txt'); await poHomeChannel.content.btnModalConfirm.click(); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await expect(poHomeChannel.content.getFileDescription).toHaveText('any_description'); await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file1.txt'); }); @@ -90,7 +93,7 @@ test.describe('E2EE File Encryption', () => { await poHomeChannel.content.fileNameInput.fill('any_file1.txt'); await poHomeChannel.content.btnModalConfirm.click(); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await expect(poHomeChannel.content.getFileDescription).toHaveText('message 1'); await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file1.txt'); }); @@ -105,7 +108,7 @@ test.describe('E2EE File Encryption', () => { await poHomeChannel.content.fileNameInput.fill('any_file2.txt'); await poHomeChannel.content.btnModalConfirm.click(); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await expect(poHomeChannel.content.getFileDescription).toHaveText('message 2'); await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file2.txt'); }); @@ -120,7 +123,7 @@ test.describe('E2EE File Encryption', () => { await poHomeChannel.content.fileNameInput.fill('any_file3.txt'); await poHomeChannel.content.btnModalConfirm.click(); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await expect(poHomeChannel.content.getFileDescription).toHaveText('message 2'); await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file2.txt'); }); @@ -152,7 +155,7 @@ test.describe('E2EE File Encryption', () => { await poHomeChannel.content.sendMessage('This is an encrypted message.'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); }); await test.step('send a text file in channel, file should not be encrypted', async () => { @@ -161,7 +164,7 @@ test.describe('E2EE File Encryption', () => { await poHomeChannel.content.fileNameInput.fill('any_file1.txt'); await poHomeChannel.content.btnModalConfirm.click(); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).not.toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).not.toBeVisible(); await expect(poHomeChannel.content.getFileDescription).toHaveText('any_description'); await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file1.txt'); }); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts index fcd3c11010fc1..bf6e4d2695064 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts @@ -5,6 +5,7 @@ import { BASE_API_URL } from '../config/constants'; import injectInitialData from '../fixtures/inject-initial-data'; import { Users, restoreState } from '../fixtures/userStates'; import { HomeChannel } from '../page-objects'; +import { EncryptedRoomPage } from '../page-objects/encrypted-room'; import { preserveSettings } from '../utils/preserveSettings'; import { test, expect } from '../utils/test'; @@ -35,6 +36,7 @@ const sendEncryptedMessage = async (request: APIRequestContext, rid: string, enc test.describe('E2EE Legacy Format', () => { let poHomeChannel: HomeChannel; + let encryptedRoomPage: EncryptedRoomPage; test.use({ storageState: Users.userE2EE.state }); @@ -48,6 +50,7 @@ test.describe('E2EE Legacy Format', () => { test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); + encryptedRoomPage = new EncryptedRoomPage(page); await page.goto('/home'); }); @@ -87,6 +90,6 @@ test.describe('E2EE Legacy Format', () => { await sendEncryptedMessage(request, rid, kid + encryptedMessage); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('world'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); }); }); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts index ae2d2870086e7..34a2fcd7204b4 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts @@ -5,6 +5,7 @@ import { Users, storeState, restoreState } from '../fixtures/userStates'; import { AccountProfile, HomeChannel } from '../page-objects'; import { setupE2EEPassword } from './setupE2EEPassword'; import { AccountSecurityPage } from '../page-objects/account-security'; +import { EncryptedRoomPage } from '../page-objects/encrypted-room'; import { HomeSidenav } from '../page-objects/fragments'; import { E2EEKeyDecodeFailureBanner, @@ -185,6 +186,7 @@ const roomSetupSettingsList = ['E2E_Enable', 'E2E_Allow_Unencrypted_Messages']; test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { let poAccountProfile: AccountProfile; let poHomeChannel: HomeChannel; + let encryptedRoomPage: EncryptedRoomPage; let e2eePassword: string; preserveSettings(roomSetupSettingsList); @@ -192,6 +194,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { test.beforeEach(async ({ page }) => { poAccountProfile = new AccountProfile(page); poHomeChannel = new HomeChannel(page); + encryptedRoomPage = new EncryptedRoomPage(page); }); test.beforeAll(async ({ api }) => { @@ -248,7 +251,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await poHomeChannel.content.sendMessage('hello world'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); }); test('expect enter password state on encrypted room', async ({ page }) => { @@ -294,7 +297,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await poHomeChannel.content.sendMessage('hello world'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await storeState(page, Users.admin); }); @@ -313,7 +316,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await poHomeChannel.content.sendMessage('hello world'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await poHomeChannel.sidenav.btnUserProfileMenu.click(); await poHomeChannel.sidenav.accountProfileOption.click(); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts index 9a6fd5de8576d..c908bfce6cb93 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts @@ -3,6 +3,7 @@ import { faker } from '@faker-js/faker'; import { IS_EE } from '../config/constants'; import { Users } from '../fixtures/userStates'; import { HomeChannel } from '../page-objects'; +import { EncryptedRoomPage } from '../page-objects/encrypted-room'; import { preserveSettings } from '../utils/preserveSettings'; import { test, expect } from '../utils/test'; @@ -17,6 +18,7 @@ preserveSettings(settingsList); test.describe('E2EE Server Settings', () => { let poHomeChannel: HomeChannel; + let encryptedRoomPage: EncryptedRoomPage; test.use({ storageState: Users.userE2EE.state }); @@ -30,6 +32,7 @@ test.describe('E2EE Server Settings', () => { test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); + encryptedRoomPage = new EncryptedRoomPage(page); await page.goto('/home'); }); @@ -46,7 +49,7 @@ test.describe('E2EE Server Settings', () => { await poHomeChannel.content.sendMessage('This is an encrypted message.'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await page.locator('[name="msg"]').type('/'); await expect(page.locator('#popup-item-contextualbar')).not.toHaveClass(/disabled/); @@ -62,9 +65,11 @@ test.describe('E2EE Server Settings', () => { test.describe('un-encrypted messages not allowed in e2ee rooms', () => { test.skip(!IS_EE, 'Premium Only'); let poHomeChannel: HomeChannel; + let encryptedRoomPage: EncryptedRoomPage; test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); + encryptedRoomPage = new EncryptedRoomPage(page); await page.goto('/home'); }); @@ -88,7 +93,7 @@ test.describe('E2EE Server Settings', () => { await poHomeChannel.content.sendMessage('This is an encrypted message.'); await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); - await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible(); + await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await page.locator('[name="msg"]').pressSequentially('/'); await expect(page.locator('#popup-item-contextualbar')).toHaveClass(/disabled/); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts b/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts index 151915016bbc2..70ce451d950b4 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts @@ -152,3 +152,35 @@ export class DisableRoomEncryptionModal extends Modal { await this.toastMessages.dismissToast('success'); } } + +export class E2EEMessageActions { + private readonly page: Page; + + constructor(page: Page) { + this.page = page; + } + + private get forwardMessageButton(): Locator { + return this.page.getByRole('button', { name: 'Forward message not available on encrypted content' }); + } + + private get replyInDirectMessageOption(): Locator { + return this.page.getByRole('menuitem', { name: 'Reply in direct message' }); + } + + private get copyLinkOption(): Locator { + return this.page.getByRole('menuitem', { name: 'Copy link' }); + } + + async expectForwardMessageToBeDisabled(): Promise { + await expect(this.forwardMessageButton).toBeDisabled(); + } + + async expectReplyInDirectMessageToBeDisabled(): Promise { + await expect(this.replyInDirectMessageOption).toHaveClass(/disabled/); + } + + async expectCopyLinkToBeDisabled(): Promise { + await expect(this.copyLinkOption).toHaveClass(/disabled/); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index b0a474a00930c..4e7d19f75e80f 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -66,6 +66,14 @@ export class HomeContent { return this.page.locator('[data-qa-type="message"][data-sequential="false"]').last(); } + getUserMention(username: string): Locator { + return this.page.getByRole('button', { name: username }); + } + + getChannelMention(channelName: string): Locator { + return this.page.getByRole('button', { name: channelName }); + } + get encryptedRoomHeaderIcon(): Locator { return this.page.locator('.rcx-room-header i.rcx-icon--name-key'); } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/index.ts b/apps/meteor/tests/e2e/page-objects/fragments/index.ts index 66e32ce94687e..9b26c81651ec5 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/index.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/index.ts @@ -13,3 +13,6 @@ export * from './report-message-modal'; export * from './toast-messages'; export * from './export-messages-tab'; export * from './menu'; +export * from './pinned-messages-tab'; +export * from './room-toolbar'; +export * from './starred-messages-tab'; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/message.ts b/apps/meteor/tests/e2e/page-objects/fragments/message.ts index 77dee24c85ca0..02e1f29ca836e 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/message.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/message.ts @@ -14,4 +14,14 @@ export class Message { get encryptedIcon() { return this.root.locator('.rcx-icon--name-key'); } + + get moreButton() { + return this.root.getByRole('button', { name: 'More' }); + } + + async openMenu(): Promise { + await this.root.hover(); + await this.moreButton.waitFor(); + await this.moreButton.click(); + } } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts b/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts new file mode 100644 index 0000000000000..a1fb186c3d6b1 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts @@ -0,0 +1,33 @@ +import type { Locator, Page } from '@playwright/test'; + +import { Message } from './message'; +import { RoomToolbar } from './room-toolbar'; +import { expect } from '../../utils/test'; + +export class PinnedMessagesTab { + private readonly root: Locator; + + private readonly roomToolbar: RoomToolbar; + + constructor(page: Page) { + this.root = page.getByRole('dialog', { name: 'Pinned Messages' }); + this.roomToolbar = new RoomToolbar(page); + } + + private get lastMessage(): Message { + return new Message(this.root.locator('[data-qa-type="message"]').last()); + } + + async openTab(): Promise { + await this.roomToolbar.openPinnedMessagesList(); + await expect(this.root).toBeVisible(); + } + + async expectLastMessageToContainText(text: string): Promise { + await expect(this.lastMessage.root).toContainText(text); + } + + async openLastMessageMenu(): Promise { + await this.lastMessage.openMenu(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts b/apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts new file mode 100644 index 0000000000000..28835f578d866 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts @@ -0,0 +1,39 @@ +import type { Locator, Page } from '@playwright/test'; + +export class RoomToolbar { + private readonly page: Page; + + constructor(page: Page) { + this.page = page; + } + + private get toolbarPrimaryActions(): Locator { + return this.page.getByRole('toolbar', { name: 'Primary Room actions' }); + } + + private get btnToolbarPrimaryActionsMore(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Options' }); + } + + private get menuToolbarPrimaryActionsMore(): Locator { + return this.page.getByRole('menu', { name: 'Options' }); + } + + private get optionPinnedMessages(): Locator { + return this.menuToolbarPrimaryActionsMore.getByRole('menuitem', { name: 'Pinned Messages' }); + } + + private get optionStarredMessages(): Locator { + return this.menuToolbarPrimaryActionsMore.getByRole('menuitem', { name: 'Starred Messages' }); + } + + async openPinnedMessagesList(): Promise { + await this.btnToolbarPrimaryActionsMore.click(); + await this.optionPinnedMessages.click(); + } + + async openStarredMessagesList(): Promise { + await this.btnToolbarPrimaryActionsMore.click(); + await this.optionStarredMessages.click(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts b/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts new file mode 100644 index 0000000000000..ef162323b7de1 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts @@ -0,0 +1,33 @@ +import type { Locator, Page } from '@playwright/test'; + +import { Message } from './message'; +import { RoomToolbar } from './room-toolbar'; +import { expect } from '../../utils/test'; + +export class StarredMessagesTab { + private readonly root: Locator; + + private readonly roomToolbar: RoomToolbar; + + constructor(page: Page) { + this.root = page.getByRole('dialog', { name: 'Starred Messages' }); + this.roomToolbar = new RoomToolbar(page); + } + + private get lastMessage(): Message { + return new Message(this.root.locator('[data-qa-type="message"]').last()); + } + + async openTab(): Promise { + await this.roomToolbar.openStarredMessagesList(); + await expect(this.root).toBeVisible(); + } + + async expectLastMessageToContainText(text: string): Promise { + await expect(this.lastMessage.root).toContainText(text); + } + + async openLastMessageMenu(): Promise { + await this.lastMessage.openMenu(); + } +} From de8659de892ffab0f8d941a7aa3ba0f66c7feacf Mon Sep 17 00:00:00 2001 From: Jessica Schelly Souza Date: Fri, 7 Nov 2025 14:33:06 -0300 Subject: [PATCH 2/7] test: passphrase management tests to utilize page objects --- .../e2ee-passphrase-management.spec.ts | 74 ++++++++----------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts index 34a2fcd7204b4..95165c7beeaa2 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts @@ -28,6 +28,13 @@ const originalSettings = preserveSettings(settingsList); test.describe('E2EE Passphrase Management - Initial Setup', () => { test.use({ storageState: Users.admin.state }); + let loginPage: LoginPage; + let enterE2EEPasswordBanner: EnterE2EEPasswordBanner; + let enterE2EEPasswordModal: EnterE2EEPasswordModal; + let e2EEKeyDecodeFailureBanner: E2EEKeyDecodeFailureBanner; + let sidenav: HomeSidenav; + let accountSecurityPage: AccountSecurityPage; + let resetE2EEPasswordModal: ResetE2EEPasswordModal; test.beforeAll(async ({ api }) => { await api.post('/settings/E2E_Enable', { value: true }); @@ -36,6 +43,16 @@ test.describe('E2EE Passphrase Management - Initial Setup', () => { await api.post('/settings/E2E_Enabled_Default_PrivateRooms', { value: false }); }); + test.beforeEach(async ({ page }) => { + loginPage = new LoginPage(page); + enterE2EEPasswordBanner = new EnterE2EEPasswordBanner(page); + enterE2EEPasswordModal = new EnterE2EEPasswordModal(page); + e2EEKeyDecodeFailureBanner = new E2EEKeyDecodeFailureBanner(page); + sidenav = new HomeSidenav(page); + accountSecurityPage = new AccountSecurityPage(page); + resetE2EEPasswordModal = new ResetE2EEPasswordModal(page); + }); + test.afterAll(async ({ api }) => { await api.post('/settings/E2E_Enable', { value: originalSettings.E2E_Enable }); await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: originalSettings.E2E_Allow_Unencrypted_Messages }); @@ -45,8 +62,6 @@ test.describe('E2EE Passphrase Management - Initial Setup', () => { test.describe('Generate', () => { test.beforeEach(async ({ page, api }) => { - const loginPage = new LoginPage(page); - await api.post('/method.call/e2e.resetOwnE2EKey', { message: JSON.stringify({ msg: 'method', id: '1', method: 'e2e.resetOwnE2EKey', params: [] }), }); @@ -57,12 +72,6 @@ test.describe('E2EE Passphrase Management - Initial Setup', () => { }); test('expect the randomly generated password to work', async ({ page }) => { - const loginPage = new LoginPage(page); - const enterE2EEPasswordBanner = new EnterE2EEPasswordBanner(page); - const enterE2EEPasswordModal = new EnterE2EEPasswordModal(page); - const e2EEKeyDecodeFailureBanner = new E2EEKeyDecodeFailureBanner(page); - const sidenav = new HomeSidenav(page); - const password = await setupE2EEPassword(page); // Log out @@ -79,10 +88,7 @@ test.describe('E2EE Passphrase Management - Initial Setup', () => { await e2EEKeyDecodeFailureBanner.expectToNotBeVisible(); }); - test('expect to manually reset the password', async ({ page }) => { - const accountSecurityPage = new AccountSecurityPage(page); - const loginPage = new LoginPage(page); - + test('expect to manually reset the password', async () => { // Reset the E2EE key to start the flow from the beginning await accountSecurityPage.goto(); await accountSecurityPage.resetE2EEPassword(); @@ -91,12 +97,6 @@ test.describe('E2EE Passphrase Management - Initial Setup', () => { }); test('should reset e2e password from the modal', async ({ page }) => { - const sidenav = new HomeSidenav(page); - const loginPage = new LoginPage(page); - const enterE2EEPasswordBanner = new EnterE2EEPasswordBanner(page); - const enterE2EEPasswordModal = new EnterE2EEPasswordModal(page); - const resetE2EEPasswordModal = new ResetE2EEPasswordModal(page); - await setupE2EEPassword(page); // Logout @@ -115,13 +115,6 @@ test.describe('E2EE Passphrase Management - Initial Setup', () => { }); test('expect to manually set a new password', async ({ page }) => { - const accountSecurityPage = new AccountSecurityPage(page); - const loginPage = new LoginPage(page); - const enterE2EEPasswordBanner = new EnterE2EEPasswordBanner(page); - const enterE2EEPasswordModal = new EnterE2EEPasswordModal(page); - const e2EEKeyDecodeFailureBanner = new E2EEKeyDecodeFailureBanner(page); - const sidenav = new HomeSidenav(page); - const newPassword = faker.internet.password({ length: 30, prefix: @@ -161,16 +154,10 @@ test.describe('E2EE Passphrase Management - Initial Setup', () => { await page.goto('/home'); await injectInitialData(); await restoreState(page, Users.userE2EE); - const sidenav = new HomeSidenav(page); await sidenav.logout(); - const loginPage = new LoginPage(page); await loginPage.loginByUserState(Users.userE2EE, { except: ['private_key', 'public_key'] }); - const enterE2EEPasswordBanner = new EnterE2EEPasswordBanner(page); - const enterE2EEPasswordModal = new EnterE2EEPasswordModal(page); - const e2EEKeyDecodeFailureBanner = new E2EEKeyDecodeFailureBanner(page); - await enterE2EEPasswordBanner.click(); await enterE2EEPasswordModal.enterPassword('minus mobile dexter forest elvis'); await e2EEKeyDecodeFailureBanner.expectToNotBeVisible(); @@ -187,6 +174,9 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { let poAccountProfile: AccountProfile; let poHomeChannel: HomeChannel; let encryptedRoomPage: EncryptedRoomPage; + let loginPage: LoginPage; + let accountSecurityPage: AccountSecurityPage; + let enterE2EEPasswordModal: EnterE2EEPasswordModal; let e2eePassword: string; preserveSettings(roomSetupSettingsList); @@ -195,6 +185,9 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { poAccountProfile = new AccountProfile(page); poHomeChannel = new HomeChannel(page); encryptedRoomPage = new EncryptedRoomPage(page); + loginPage = new LoginPage(page); + accountSecurityPage = new AccountSecurityPage(page); + enterE2EEPasswordModal = new EnterE2EEPasswordModal(page); }); test.beforeAll(async ({ api }) => { @@ -284,9 +277,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await poHomeChannel.btnRoomEnterE2EEPassword.click(); - await page.locator('#modal-root input').fill(e2eePassword); - - await page.locator('#modal-root .rcx-button--primary').click(); + await enterE2EEPasswordModal.enterPassword(e2eePassword); await expect(poHomeChannel.bannerEnterE2EEPassword).not.toBeVisible(); @@ -318,26 +309,23 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world'); await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); - await poHomeChannel.sidenav.btnUserProfileMenu.click(); - await poHomeChannel.sidenav.accountProfileOption.click(); - - await page.locator('role=navigation >> a:has-text("Security")').click(); + await accountSecurityPage.goto(); await poAccountProfile.securityE2EEncryptionSection.click(); await poAccountProfile.securityE2EEncryptionResetKeyButton.click(); - await page.locator('role=button[name="Login"]').waitFor(); + await loginPage.waitForIt(); await page.reload(); - await page.locator('role=button[name="Login"]').waitFor(); + await loginPage.waitForIt(); await injectInitialData(); await restoreState(page, Users.admin); - await page.locator('role=navigation >> role=button[name=Search]').click(); - await page.locator('role=search >> role=searchbox').fill(channelName); - await page.locator(`role=search >> role=listbox >> role=link >> text="${channelName}"`).click(); + await poHomeChannel.sidenav.openSearch(); + await poHomeChannel.sidenav.inputSearch.fill(channelName); + await poHomeChannel.sidenav.getSearchItemByName(channelName).click(); await poHomeChannel.btnRoomSaveE2EEPassword.click(); await poHomeChannel.btnSavedMyPassword.click(); From ac841c77784ba4cba00f8826dc214ca03893d7a8 Mon Sep 17 00:00:00 2001 From: Jessica Schelly Souza Date: Fri, 7 Nov 2025 16:15:59 -0300 Subject: [PATCH 3/7] fix: remove extra settings --- .../e2ee-encrypted-channels.spec.ts | 18 +++++++----------- .../e2ee-file-encryption.spec.ts | 1 - .../e2e/e2e-encryption/e2ee-key-reset.spec.ts | 1 - .../e2e-encryption/e2ee-legacy-format.spec.ts | 1 - .../tests/e2e/e2e-encryption/e2ee-otr.spec.ts | 14 +++++++------- .../e2ee-server-settings.spec.ts | 6 +++--- 6 files changed, 17 insertions(+), 24 deletions(-) diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts index 2a7027e675375..120221e0d3ace 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts @@ -3,7 +3,7 @@ import { faker } from '@faker-js/faker'; import { Users } from '../fixtures/userStates'; import { HomeChannel } from '../page-objects'; import { EncryptedRoomPage } from '../page-objects/encrypted-room'; -import { E2EEMessageActions, EnableRoomEncryptionModal } from '../page-objects/fragments/e2ee'; +import { DisableRoomEncryptionModal, E2EEMessageActions, EnableRoomEncryptionModal } from '../page-objects/fragments/e2ee'; import { PinnedMessagesTab } from '../page-objects/fragments/pinned-messages-tab'; import { StarredMessagesTab } from '../page-objects/fragments/starred-messages-tab'; import { preserveSettings } from '../utils/preserveSettings'; @@ -23,6 +23,7 @@ test.describe('E2EE Encrypted Channels', () => { let encryptedRoomPage: EncryptedRoomPage; let e2eeMessageActions: E2EEMessageActions; let enableEncryptionModal: EnableRoomEncryptionModal; + let disableEncryptionModal: DisableRoomEncryptionModal; let pinnedMessagesTab: PinnedMessagesTab; let starredMessagesTab: StarredMessagesTab; @@ -41,6 +42,7 @@ test.describe('E2EE Encrypted Channels', () => { encryptedRoomPage = new EncryptedRoomPage(page); e2eeMessageActions = new E2EEMessageActions(page); enableEncryptionModal = new EnableRoomEncryptionModal(page); + disableEncryptionModal = new DisableRoomEncryptionModal(page); pinnedMessagesTab = new PinnedMessagesTab(page); starredMessagesTab = new StarredMessagesTab(page); await page.goto('/home'); @@ -64,9 +66,7 @@ test.describe('E2EE Encrypted Channels', () => { await expect(poHomeChannel.tabs.btnDisableE2E).toBeVisible(); await poHomeChannel.tabs.btnDisableE2E.click({ force: true }); - await expect(page.getByRole('dialog', { name: 'Disable encryption' })).toBeVisible(); - await page.getByRole('button', { name: 'Disable encryption' }).click(); - await poHomeChannel.dismissToast(); + await disableEncryptionModal.disable(); await page.waitForTimeout(1000); await poHomeChannel.content.sendMessage('hello world not encrypted'); @@ -77,9 +77,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.tabs.kebab.click({ force: true }); await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible(); await poHomeChannel.tabs.btnEnableE2E.click({ force: true }); - await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible(); - await page.getByRole('button', { name: 'Enable encryption' }).click(); - await poHomeChannel.dismissToast(); + await enableEncryptionModal.enable(); await page.waitForTimeout(1000); await poHomeChannel.content.sendMessage('hello world encrypted again'); @@ -102,8 +100,7 @@ test.describe('E2EE Encrypted Channels', () => { await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is the thread main message.'); await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); - await page.locator('[data-qa-type="message"]').last().hover(); - await page.locator('role=button[name="Reply in thread"]').click(); + await poHomeChannel.content.openReplyInThread(); await expect(page).toHaveURL(/.*thread/); @@ -238,8 +235,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.tabs.kebab.click({ force: true }); await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible(); await poHomeChannel.tabs.btnEnableE2E.click({ force: true }); - await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible(); - await page.getByRole('button', { name: 'Enable encryption' }).click(); + await enableEncryptionModal.enable(); await page.waitForTimeout(1000); await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible(); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts index 7591ebf02de50..8abb0eccdbc3b 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts @@ -27,7 +27,6 @@ test.describe('E2EE File Encryption', () => { await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: true }); await api.post('/settings/E2E_Enabled_Default_DirectRooms', { value: false }); await api.post('/settings/E2E_Enabled_Default_PrivateRooms', { value: false }); - await api.post('/im.delete', { username: 'user2' }); }); test.afterAll(async ({ api }) => { diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-key-reset.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-key-reset.spec.ts index fab641ba6021c..d95cc55e9d8ba 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-key-reset.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-key-reset.spec.ts @@ -25,7 +25,6 @@ test.describe('E2EE Key Reset', () => { await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: true }); await api.post('/settings/E2E_Enabled_Default_DirectRooms', { value: false }); await api.post('/settings/E2E_Enabled_Default_PrivateRooms', { value: false }); - await api.post('/im.delete', { username: 'user2' }); }); test.beforeEach(async ({ browser, page }) => { diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts index bf6e4d2695064..00e78da23acc4 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-legacy-format.spec.ts @@ -45,7 +45,6 @@ test.describe('E2EE Legacy Format', () => { await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: true }); await api.post('/settings/E2E_Enabled_Default_DirectRooms', { value: false }); await api.post('/settings/E2E_Enabled_Default_PrivateRooms', { value: false }); - await api.post('/im.delete', { username: 'user2' }); }); test.beforeEach(async ({ page }) => { diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts index b2c1e427dc974..955fd57726f71 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts @@ -1,5 +1,6 @@ import { Users } from '../fixtures/userStates'; import { HomeChannel } from '../page-objects'; +import { DisableRoomEncryptionModal, EnableRoomEncryptionModal } from '../page-objects/fragments/e2ee'; import { preserveSettings } from '../utils/preserveSettings'; import { test, expect } from '../utils/test'; @@ -14,6 +15,8 @@ preserveSettings(settingsList); test.describe('E2EE OTR (Off-The-Record)', () => { let poHomeChannel: HomeChannel; + let enableEncryptionModal: EnableRoomEncryptionModal; + let disableEncryptionModal: DisableRoomEncryptionModal; test.use({ storageState: Users.userE2EE.state }); @@ -27,6 +30,8 @@ test.describe('E2EE OTR (Off-The-Record)', () => { test.beforeEach(async ({ page }) => { poHomeChannel = new HomeChannel(page); + enableEncryptionModal = new EnableRoomEncryptionModal(page); + disableEncryptionModal = new DisableRoomEncryptionModal(page); await page.goto('/home'); }); @@ -43,21 +48,16 @@ test.describe('E2EE OTR (Off-The-Record)', () => { await poHomeChannel.tabs.kebab.click({ force: true }); if (await poHomeChannel.tabs.btnDisableE2E.isVisible()) { await poHomeChannel.tabs.btnDisableE2E.click({ force: true }); - await expect(page.getByRole('dialog', { name: 'Disable encryption' })).toBeVisible(); - await page.getByRole('button', { name: 'Disable encryption' }).click(); - await poHomeChannel.dismissToast(); + await disableEncryptionModal.disable(); await poHomeChannel.tabs.kebab.click({ force: true }); } await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible(); await poHomeChannel.tabs.btnEnableE2E.click({ force: true }); - await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible(); - await page.getByRole('button', { name: 'Enable encryption' }).click(); + await enableEncryptionModal.enable(); await page.waitForTimeout(1000); await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible(); - await poHomeChannel.dismissToast(); - await poHomeChannel.tabs.kebab.click({ force: true }); await expect(poHomeChannel.tabs.btnEnableOTR).toBeVisible(); await poHomeChannel.tabs.btnEnableOTR.click({ force: true }); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts index c908bfce6cb93..031e113b4e4cf 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-server-settings.spec.ts @@ -51,9 +51,9 @@ test.describe('E2EE Server Settings', () => { await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); - await page.locator('[name="msg"]').type('/'); + await poHomeChannel.content.inputMessage.pressSequentially('/'); await expect(page.locator('#popup-item-contextualbar')).not.toHaveClass(/disabled/); - await page.locator('[name="msg"]').clear(); + await poHomeChannel.content.inputMessage.clear(); await poHomeChannel.content.dispatchSlashCommand('/contextualbar'); await expect(poHomeChannel.btnContextualbarClose).toBeVisible(); @@ -95,7 +95,7 @@ test.describe('E2EE Server Settings', () => { await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.'); await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); - await page.locator('[name="msg"]').pressSequentially('/'); + await poHomeChannel.content.inputMessage.pressSequentially('/'); await expect(page.locator('#popup-item-contextualbar')).toHaveClass(/disabled/); }); }); From cb9962449d1843bd258e70426d9422f3c3a3ffe3 Mon Sep 17 00:00:00 2001 From: Jessica Schelly Souza Date: Fri, 14 Nov 2025 10:06:50 -0300 Subject: [PATCH 4/7] refactor: replace RoomToolbar usage with toolbar --- .../tests/e2e/page-objects/fragments/index.ts | 1 - .../fragments/pinned-messages-tab.ts | 5 ++- .../page-objects/fragments/room-toolbar.ts | 39 ------------------- .../fragments/starred-messages-tab.ts | 5 ++- 4 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts diff --git a/apps/meteor/tests/e2e/page-objects/fragments/index.ts b/apps/meteor/tests/e2e/page-objects/fragments/index.ts index 9f46e9b51aee9..8c579733884ad 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/index.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/index.ts @@ -14,6 +14,5 @@ export * from './toast-messages'; export * from './export-messages-tab'; export * from './menu'; export * from './pinned-messages-tab'; -export * from './room-toolbar'; export * from './starred-messages-tab'; export * from './toolbar'; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts b/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts index a1fb186c3d6b1..e93c36c46bbfd 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { Message } from './message'; -import { RoomToolbar } from './room-toolbar'; +import { RoomToolbar } from './toolbar'; import { expect } from '../../utils/test'; export class PinnedMessagesTab { @@ -19,7 +19,8 @@ export class PinnedMessagesTab { } async openTab(): Promise { - await this.roomToolbar.openPinnedMessagesList(); + await this.roomToolbar.openMoreOptions(); + await this.roomToolbar.menuItemPinnedMessages.click(); await expect(this.root).toBeVisible(); } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts b/apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts deleted file mode 100644 index 28835f578d866..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/fragments/room-toolbar.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -export class RoomToolbar { - private readonly page: Page; - - constructor(page: Page) { - this.page = page; - } - - private get toolbarPrimaryActions(): Locator { - return this.page.getByRole('toolbar', { name: 'Primary Room actions' }); - } - - private get btnToolbarPrimaryActionsMore(): Locator { - return this.toolbarPrimaryActions.getByRole('button', { name: 'Options' }); - } - - private get menuToolbarPrimaryActionsMore(): Locator { - return this.page.getByRole('menu', { name: 'Options' }); - } - - private get optionPinnedMessages(): Locator { - return this.menuToolbarPrimaryActionsMore.getByRole('menuitem', { name: 'Pinned Messages' }); - } - - private get optionStarredMessages(): Locator { - return this.menuToolbarPrimaryActionsMore.getByRole('menuitem', { name: 'Starred Messages' }); - } - - async openPinnedMessagesList(): Promise { - await this.btnToolbarPrimaryActionsMore.click(); - await this.optionPinnedMessages.click(); - } - - async openStarredMessagesList(): Promise { - await this.btnToolbarPrimaryActionsMore.click(); - await this.optionStarredMessages.click(); - } -} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts b/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts index ef162323b7de1..05cb664027681 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts @@ -1,7 +1,7 @@ import type { Locator, Page } from '@playwright/test'; import { Message } from './message'; -import { RoomToolbar } from './room-toolbar'; +import { RoomToolbar } from './toolbar'; import { expect } from '../../utils/test'; export class StarredMessagesTab { @@ -19,7 +19,8 @@ export class StarredMessagesTab { } async openTab(): Promise { - await this.roomToolbar.openStarredMessagesList(); + await this.roomToolbar.openMoreOptions(); + await this.roomToolbar.menuItemStarredMessages.click(); await expect(this.root).toBeVisible(); } From ad2fc7aec0126fff2c907bbc00d05eb00036d828 Mon Sep 17 00:00:00 2001 From: Jessica Schelly Souza Date: Fri, 14 Nov 2025 11:16:11 -0300 Subject: [PATCH 5/7] refactor: update RoomToolbar to use page context for menu items --- .../meteor/tests/e2e/page-objects/fragments/toolbar.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts b/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts index f55910a6d2b02..46a6245d2627b 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts @@ -12,7 +12,7 @@ export abstract class Toolbar { } export class RoomToolbar extends Toolbar { - constructor(page: Page) { + constructor(private page: Page) { super(page.getByRole('toolbar', { name: 'Primary Room actions' })); } @@ -65,19 +65,19 @@ export class RoomToolbar extends Toolbar { } get menuItemMentions(): Locator { - return this.root.getByRole('menuitem', { name: 'Mentions' }); + return this.page.getByRole('menuitem', { name: 'Mentions' }); } get menuItemStarredMessages(): Locator { - return this.root.getByRole('menuitem', { name: 'Starred Messages' }); + return this.page.getByRole('menuitem', { name: 'Starred Messages' }); } get menuItemPinnedMessages(): Locator { - return this.root.getByRole('menuitem', { name: 'Pinned Messages' }); + return this.page.getByRole('menuitem', { name: 'Pinned Messages' }); } get menuItemPruneMessages(): Locator { - return this.root.getByRole('menuitem', { name: 'Prune Messages' }); + return this.page.getByRole('menuitem', { name: 'Prune Messages' }); } async openRoomInfo() { From 2c5711fa2c1dc50eee6e0f232bb1d0b862677777 Mon Sep 17 00:00:00 2001 From: Jessica Schelly Souza Date: Wed, 19 Nov 2025 13:52:05 -0300 Subject: [PATCH 6/7] fix: review --- .../e2ee-encrypted-channels.spec.ts | 14 +++++++------- .../tests/e2e/page-objects/fragments/e2ee.ts | 18 +++--------------- .../e2e/page-objects/fragments/home-content.ts | 4 ++-- .../fragments/pinned-messages-tab.ts | 8 ++------ .../fragments/starred-messages-tab.ts | 8 ++------ 5 files changed, 16 insertions(+), 36 deletions(-) diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts index 6a91ac1596698..b1da4a158b481 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts @@ -131,12 +131,12 @@ test.describe('E2EE Encrypted Channels', () => { await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible(); await poHomeChannel.content.lastUserMessage.hover(); - await e2eeMessageActions.expectForwardMessageToBeDisabled(); + await expect(e2eeMessageActions.forwardMessageButton).toBeDisabled(); await poHomeChannel.content.openLastMessageMenu(); - await e2eeMessageActions.expectReplyInDirectMessageToBeDisabled(); - await e2eeMessageActions.expectCopyLinkToBeDisabled(); + await expect(e2eeMessageActions.replyInDirectMessageOption).toHaveClass(/disabled/); + await expect(e2eeMessageActions.copyLinkOption).toHaveClass(/disabled/); }); test('expect create a private channel, encrypt it and send an encrypted message', async ({ page }) => { @@ -282,16 +282,16 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.toastMessage.dismissToast(); await pinnedMessagesTab.openTab(); - await pinnedMessagesTab.expectLastMessageToContainText('This message should be pinned and starred.'); + await expect(pinnedMessagesTab.lastMessage.body).toContainText('This message should be pinned and starred.'); await pinnedMessagesTab.openLastMessageMenu(); - await e2eeMessageActions.expectCopyLinkToBeDisabled(); + await expect(e2eeMessageActions.copyLinkOption).toHaveClass(/disabled/); await poHomeChannel.btnContextualbarClose.click(); await starredMessagesTab.openTab(); - await starredMessagesTab.expectLastMessageToContainText('This message should be pinned and starred.'); + await expect(starredMessagesTab.lastMessage.body).toContainText('This message should be pinned and starred.'); await starredMessagesTab.openLastMessageMenu(); - await e2eeMessageActions.expectCopyLinkToBeDisabled(); + await expect(e2eeMessageActions.copyLinkOption).toHaveClass(/disabled/); }); test('expect to edit encrypted message', async ({ page }) => { diff --git a/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts b/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts index 70ce451d950b4..2e22455a4b3ad 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/e2ee.ts @@ -160,27 +160,15 @@ export class E2EEMessageActions { this.page = page; } - private get forwardMessageButton(): Locator { + get forwardMessageButton(): Locator { return this.page.getByRole('button', { name: 'Forward message not available on encrypted content' }); } - private get replyInDirectMessageOption(): Locator { + get replyInDirectMessageOption(): Locator { return this.page.getByRole('menuitem', { name: 'Reply in direct message' }); } - private get copyLinkOption(): Locator { + get copyLinkOption(): Locator { return this.page.getByRole('menuitem', { name: 'Copy link' }); } - - async expectForwardMessageToBeDisabled(): Promise { - await expect(this.forwardMessageButton).toBeDisabled(); - } - - async expectReplyInDirectMessageToBeDisabled(): Promise { - await expect(this.replyInDirectMessageOption).toHaveClass(/disabled/); - } - - async expectCopyLinkToBeDisabled(): Promise { - await expect(this.copyLinkOption).toHaveClass(/disabled/); - } } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index 4e7d19f75e80f..ce35f99f51b8a 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -67,11 +67,11 @@ export class HomeContent { } getUserMention(username: string): Locator { - return this.page.getByRole('button', { name: username }); + return this.page.locator('[data-uid]', { hasText: username }); } getChannelMention(channelName: string): Locator { - return this.page.getByRole('button', { name: channelName }); + return this.page.locator('[title="Mentions channel"]', { hasText: channelName }); } get encryptedRoomHeaderIcon(): Locator { diff --git a/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts b/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts index e93c36c46bbfd..6b5bd03b915c3 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/pinned-messages-tab.ts @@ -5,7 +5,7 @@ import { RoomToolbar } from './toolbar'; import { expect } from '../../utils/test'; export class PinnedMessagesTab { - private readonly root: Locator; + readonly root: Locator; private readonly roomToolbar: RoomToolbar; @@ -14,7 +14,7 @@ export class PinnedMessagesTab { this.roomToolbar = new RoomToolbar(page); } - private get lastMessage(): Message { + get lastMessage(): Message { return new Message(this.root.locator('[data-qa-type="message"]').last()); } @@ -24,10 +24,6 @@ export class PinnedMessagesTab { await expect(this.root).toBeVisible(); } - async expectLastMessageToContainText(text: string): Promise { - await expect(this.lastMessage.root).toContainText(text); - } - async openLastMessageMenu(): Promise { await this.lastMessage.openMenu(); } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts b/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts index 05cb664027681..d766661d42ed6 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/starred-messages-tab.ts @@ -5,7 +5,7 @@ import { RoomToolbar } from './toolbar'; import { expect } from '../../utils/test'; export class StarredMessagesTab { - private readonly root: Locator; + readonly root: Locator; private readonly roomToolbar: RoomToolbar; @@ -14,7 +14,7 @@ export class StarredMessagesTab { this.roomToolbar = new RoomToolbar(page); } - private get lastMessage(): Message { + get lastMessage(): Message { return new Message(this.root.locator('[data-qa-type="message"]').last()); } @@ -24,10 +24,6 @@ export class StarredMessagesTab { await expect(this.root).toBeVisible(); } - async expectLastMessageToContainText(text: string): Promise { - await expect(this.lastMessage.root).toContainText(text); - } - async openLastMessageMenu(): Promise { await this.lastMessage.openMenu(); } From 55250089a95fdc2968d1c1ae57bf0d3fca894e45 Mon Sep 17 00:00:00 2001 From: Jessica Schelly Souza Date: Wed, 3 Dec 2025 13:09:57 -0300 Subject: [PATCH 7/7] fix locator --- apps/meteor/tests/e2e/page-objects/fragments/home-content.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index ce35f99f51b8a..1af46811ea84d 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -67,7 +67,7 @@ export class HomeContent { } getUserMention(username: string): Locator { - return this.page.locator('[data-uid]', { hasText: username }); + return this.page.locator('[title="Mentions user"]', { hasText: username }); } getChannelMention(channelName: string): Locator {