From 58bbb2f9578cd10ecfd89998dd9eb76b1ac6fb12 Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Tue, 30 Jun 2026 15:24:54 +0200 Subject: [PATCH 01/10] test: verify opening settings page through menu item (TC-11010) --- e2e-tests/poms/webapp/settings.page.ts | 26 ++++++++ e2e-tests/specs/regression/menuBar.spec.ts | 75 ++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 e2e-tests/poms/webapp/settings.page.ts create mode 100644 e2e-tests/specs/regression/menuBar.spec.ts diff --git a/e2e-tests/poms/webapp/settings.page.ts b/e2e-tests/poms/webapp/settings.page.ts new file mode 100644 index 00000000000..18e8965d15e --- /dev/null +++ b/e2e-tests/poms/webapp/settings.page.ts @@ -0,0 +1,26 @@ +/* + * Wire + * Copyright (C) 2026 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +import {Page} from '@playwright/test'; + +export const settingsPage = (page: Page) => { + return { + accountButton: page.getByRole('button', {name: 'Account'}), + }; +}; diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts new file mode 100644 index 00000000000..642d1102afb --- /dev/null +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -0,0 +1,75 @@ +import {conversationsList} from './../../poms/webapp/conversationList.page'; +/* + * Wire + * Copyright (C) 2026 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +/* + * Wire + * Copyright (C) 2026 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +import {createGroup} from '../../actions/createGroup'; +import {loginUser} from '../../actions/loginUser'; +import {test, expect} from '../../fixtures'; +import {settingsPage} from '../../poms/webapp/settings.page'; +import {conversation} from '../../poms/webapp/conversation.page'; + +test.describe('Menu Bar', () => { + test('Open preferences/settings with menu bar', {tag: ['@TC-11010', '@regression']}, async ({app, createUser}) => { + const user = await createUser(); + await loginUser(app.page, user); + + // Access the native Electron application menu and click the appropriate item + const menuItem = await app.evaluate(async ({Menu, BrowserWindow}) => { + const menu = Menu.getApplicationMenu(); + const target = menu?.items + .flatMap(item => item.submenu?.items ?? []) + .find(item => item.label === 'Preferences' || item.label === 'Settings'); + + if (!target) { + throw new Error('Menu item not found'); + } + + const targetWindow = BrowserWindow.getFocusedWindow() || BrowserWindow.getAllWindows()[0]; + if (!targetWindow) { + throw new Error('No Electron window found to send the menu event to'); + } + + // Trigger the click handler associated with the menu item + target.click(target, targetWindow); + return target; + }); + + expect(menuItem.accelerator).toMatch(/^(Command\+,|Ctrl\+,)$/); + await expect(settingsPage(app.page).accountButton).toBeVisible(); + }); +}); From 1c4d82d259690b58d52fc13295c248dc8951cf3a Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Tue, 30 Jun 2026 16:37:51 +0200 Subject: [PATCH 02/10] test: verify conversation navigation via menu bar (TC-11068) --- .../poms/webapp/conversationList.page.ts | 5 +- e2e-tests/specs/regression/menuBar.spec.ts | 107 +++++++++++------- 2 files changed, 72 insertions(+), 40 deletions(-) diff --git a/e2e-tests/poms/webapp/conversationList.page.ts b/e2e-tests/poms/webapp/conversationList.page.ts index c26f2336f60..444429f7f9e 100644 --- a/e2e-tests/poms/webapp/conversationList.page.ts +++ b/e2e-tests/poms/webapp/conversationList.page.ts @@ -20,8 +20,10 @@ import {Page} from '@playwright/test'; export const conversationsList = (page: Page) => { + const items = page.getByTestId('item-conversation'); + const getConversation = (conversationName: string, options?: {protocol?: 'mls' | 'proteus'}) => { - let conversation = page.getByTestId('item-conversation').filter({hasText: conversationName}); + let conversation = items.filter({hasText: conversationName}); if (options?.protocol) { conversation = conversation.and(page.locator(`[data-protocol="${options.protocol}"]`)); @@ -39,6 +41,7 @@ export const conversationsList = (page: Page) => { const createGroupButton = page.getByTestId('conversation-list-header').getByTestId('go-create-group'); return { + items, getConversation, createGroupButton, }; diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index 642d1102afb..e1f7a19e884 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -1,23 +1,3 @@ -import {conversationsList} from './../../poms/webapp/conversationList.page'; -/* - * Wire - * Copyright (C) 2026 Wire Swiss GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - /* * Wire * Copyright (C) 2026 Wire Swiss GmbH @@ -42,6 +22,43 @@ import {loginUser} from '../../actions/loginUser'; import {test, expect} from '../../fixtures'; import {settingsPage} from '../../poms/webapp/settings.page'; import {conversation} from '../../poms/webapp/conversation.page'; +import {type App} from '../../actions/createApp'; +import {conversationsList} from './../../poms/webapp/conversationList.page'; +import {MenuItem} from 'electron'; + +/** + * Triggers an Electron application menu item by matching its label. + * Supports cross-platform variants by accepting either a single string or an array of strings. + * * @param {object} app - The Playwright Electron application instance + * @param {string|string[]} labels - The menu label(s) to match against (e.g., 'Settings' or ['Preferences', 'Settings']) + * @returns A Promise resolving to the serialized accelerator string of the clicked MenuItem + */ + +const triggerApplicationMenu = async (app: App, labels: string[]): Promise> => { + // Normalize input to an array so we can consistently use .includes() + const labelList = Array.isArray(labels) ? labels : [labels]; + + return await app.evaluate(async ({Menu, BrowserWindow}, targets) => { + const menu = Menu.getApplicationMenu(); + + const target = menu?.items.flatMap(item => item.submenu?.items ?? []).find(item => targets.includes(item.label)); + + if (!target) { + throw new Error('Menu item not found'); + } + + const targetWindow = BrowserWindow.getFocusedWindow() || BrowserWindow.getAllWindows()[0]; + if (!targetWindow) { + throw new Error('No Electron window found to send the menu event to'); + } + + // Programmatically trigger the menu item's click action + target.click(target, targetWindow); + return { + accelerator: target.accelerator, + }; + }, labelList); +}; test.describe('Menu Bar', () => { test('Open preferences/settings with menu bar', {tag: ['@TC-11010', '@regression']}, async ({app, createUser}) => { @@ -49,27 +66,39 @@ test.describe('Menu Bar', () => { await loginUser(app.page, user); // Access the native Electron application menu and click the appropriate item - const menuItem = await app.evaluate(async ({Menu, BrowserWindow}) => { - const menu = Menu.getApplicationMenu(); - const target = menu?.items - .flatMap(item => item.submenu?.items ?? []) - .find(item => item.label === 'Preferences' || item.label === 'Settings'); - - if (!target) { - throw new Error('Menu item not found'); - } - - const targetWindow = BrowserWindow.getFocusedWindow() || BrowserWindow.getAllWindows()[0]; - if (!targetWindow) { - throw new Error('No Electron window found to send the menu event to'); - } - - // Trigger the click handler associated with the menu item - target.click(target, targetWindow); - return target; - }); + const menuItem = await triggerApplicationMenu(app, ['Preferences', 'Settings']); expect(menuItem.accelerator).toMatch(/^(Command\+,|Ctrl\+,)$/); await expect(settingsPage(app.page).accountButton).toBeVisible(); }); + + test( + 'Verify switching to next and previous conversation using menu bar', + {tag: ['@TC-11068', '@regression']}, + async ({app, createUser}) => { + const user = await createUser(); + await loginUser(app.page, user); + + await test.step('Create multiple group conversations', async () => { + await createGroup(app.page, 'Group 1', []); + await createGroup(app.page, 'Group 2', []); + await expect(conversationsList(app.page).items).toHaveCount(2); + }); + + await test.step('Verify navigation to the next conversation and validate its keyboard shortcut', async () => { + await conversationsList(app.page).getConversation('Group 1').open(); + const menuItem = await triggerApplicationMenu(app, ['Next Conversation']); + + expect(menuItem.accelerator).toMatch(/^(Alt\+(Cmd|Shift)\+Up)$/); + await expect(conversation(app.page).conversationTitle).toContainText('Group 2'); + }); + + await test.step('Navigate to the previous conversation via the application menu', async () => { + const menuItem = await triggerApplicationMenu(app, ['Previous Conversation']); + + expect(menuItem.accelerator).toMatch(/^(Alt\+(Cmd|Shift)\+Down)$/); + await expect(conversation(app.page).conversationTitle).toContainText('Group 1'); + }); + }, + ); }); From 62ed7772a0a4fb2daefd0e12b613f8b0f9972c18 Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Tue, 30 Jun 2026 17:02:46 +0200 Subject: [PATCH 03/10] test: verify group creation and sign out using menu bar --- e2e-tests/specs/regression/menuBar.spec.ts | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index e1f7a19e884..c7e2d1e190b 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -25,6 +25,7 @@ import {conversation} from '../../poms/webapp/conversation.page'; import {type App} from '../../actions/createApp'; import {conversationsList} from './../../poms/webapp/conversationList.page'; import {MenuItem} from 'electron'; +import {loginPage} from '../../poms/webapp/login.page'; /** * Triggers an Electron application menu item by matching its label. @@ -101,4 +102,27 @@ test.describe('Menu Bar', () => { }); }, ); + + test( + 'Verify I can create a group conversation with menu bar', + {tag: ['@TC-11066', '@regression']}, + async ({app, createUser}) => { + const user = await createUser(); + await loginUser(app.page, user); + + const menuItem = await triggerApplicationMenu(app, ['Create Group']); + + expect(menuItem.accelerator).toBe('CmdOrCtrl+N'); + await expect(app.page.getByRole('dialog').getByText('Create group')).toBeVisible(); + }, + ); + + test('Sign out with menu bar', {tag: ['@TC-11041', '@regression']}, async ({app, createUser}) => { + const user = await createUser(); + await loginUser(app.page, user); + + await triggerApplicationMenu(app, ['Log Out']); + await app.page.getByRole('dialog').getByRole('button', {name: 'Log out'}).click(); + await expect(loginPage(app.page).loginButton).toBeVisible(); + }); }); From 64f8936a27b4f64c70619b4d9f7b3de110ffc5ca Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Tue, 30 Jun 2026 19:15:53 +0200 Subject: [PATCH 04/10] test: verify pinging 1:1 and group conversation (TC-11043) --- e2e-tests/poms/webapp/conversation.page.ts | 3 ++- e2e-tests/specs/regression/menuBar.spec.ts | 30 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/e2e-tests/poms/webapp/conversation.page.ts b/e2e-tests/poms/webapp/conversation.page.ts index b59dc1c375a..f56f42c5f17 100644 --- a/e2e-tests/poms/webapp/conversation.page.ts +++ b/e2e-tests/poms/webapp/conversation.page.ts @@ -24,7 +24,7 @@ import {User} from '../../actions/createUser'; export const conversation = (page: Page) => { const conversationTitle = page.getByTestId('status-conversation-title-bar-label'); const startCallButton = page.getByTestId('do-call'); - + const systemMessages = page.locator('[data-uie-name="item-message"].system-message:not([data-uie-send-status="1"])'); /** * The attribute 'send-status' will be 1 while the message is being sent, since we only want to assert on sent messages these messages will be excluded. See: {@see StatusTypes} * Status type -1 ensures that system messages do NOT count as sent messages @@ -67,6 +67,7 @@ export const conversation = (page: Page) => { return { conversationTitle, startCallButton, + systemMessages, sendMessage, getMessage, }; diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index c7e2d1e190b..2e921e9d69a 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -26,6 +26,7 @@ import {type App} from '../../actions/createApp'; import {conversationsList} from './../../poms/webapp/conversationList.page'; import {MenuItem} from 'electron'; import {loginPage} from '../../poms/webapp/login.page'; +import {connectWithUser} from '../../actions/connectWithUser'; /** * Triggers an Electron application menu item by matching its label. @@ -125,4 +126,33 @@ test.describe('Menu Bar', () => { await app.page.getByRole('dialog').getByRole('button', {name: 'Log out'}).click(); await expect(loginPage(app.page).loginButton).toBeVisible(); }); + + test( + 'Verify I can ping 1:1 and group conversation using the menu bar', + {tag: ['@TC-11043', '@regression']}, + async ({app, createUser, createTeam, createPage}) => { + const userB = await createUser(); + const {owner: userA} = await createTeam('Test Team', {users: [userB]}); + const userAPage = app.page; + const userBPage = await createPage(); + + await Promise.all([loginUser(userAPage, userA), loginUser(userBPage, userB)]); + await connectWithUser(userAPage, userB); + + await test.step('User A can ping 1:1 conversation', async () => { + await conversationsList(userAPage).getConversation(userB.fullName).open(); + await triggerApplicationMenu(app, ['Ping']); + + await expect(conversation(app.page).systemMessages.filter({hasText: 'You pinged'})).toBeVisible(); + }); + + await test.step('User A can ping group conversation', async () => { + await createGroup(app.page, 'Test group', [userB]); + await conversationsList(userAPage).getConversation('Test group').open(); + await triggerApplicationMenu(app, ['Ping']); + + await expect(conversation(app.page).systemMessages.filter({hasText: 'You pinged'})).toBeVisible(); + }); + }, + ); }); From 201ed6e9cf6f1b950705cf52f082a9e3c0971baf Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Wed, 1 Jul 2026 12:32:22 +0200 Subject: [PATCH 05/10] test: verify deleting content via menu bar (TC-11042) --- e2e-tests/specs/regression/menuBar.spec.ts | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index 2e921e9d69a..2fbd0bbf194 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -127,6 +127,36 @@ test.describe('Menu Bar', () => { await expect(loginPage(app.page).loginButton).toBeVisible(); }); + test( + 'Delete conversation content with menu bar', + {tag: ['@TC-11042', '@regression']}, + async ({app, createUser, createTeam, createPage}) => { + const userB = await createUser(); + const {owner: userA} = await createTeam('Test Team', {users: [userB]}); + const userAPage = app.page; + const userBPage = await createPage(); + + await Promise.all([loginUser(userAPage, userA), loginUser(userBPage, userB)]); + await connectWithUser(userAPage, userB); + + await test.step('User A can delete 1:1 conversation', async () => { + await conversationsList(userAPage).getConversation(userB.fullName).open(); + await triggerApplicationMenu(app, ['Delete Content...']); + + await expect(app.page.getByRole('dialog').getByText('Clear content?')).toBeVisible(); + await app.page.getByRole('dialog').getByRole('button', {name: 'Cancel'}).click(); + }); + + await test.step('User A can ping group conversation', async () => { + await createGroup(app.page, 'Test group', [userB]); + await conversationsList(userAPage).getConversation('Test group').open(); + + await triggerApplicationMenu(app, ['Delete Content...']); + await expect(app.page.getByRole('dialog').getByText('Clear content?')).toBeVisible(); + }); + }, + ); + test( 'Verify I can ping 1:1 and group conversation using the menu bar', {tag: ['@TC-11043', '@regression']}, From d0e63d4222dceaa52341d9e21a93d2ec4c257b46 Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Wed, 1 Jul 2026 15:07:46 +0200 Subject: [PATCH 06/10] test: verify opening people popover with menu bar (TC-11045) --- e2e-tests/specs/regression/menuBar.spec.ts | 89 +++++++++++----------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index 2fbd0bbf194..ec249555e55 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -19,7 +19,7 @@ import {createGroup} from '../../actions/createGroup'; import {loginUser} from '../../actions/loginUser'; -import {test, expect} from '../../fixtures'; +import {test, expect, Page} from '../../fixtures'; import {settingsPage} from '../../poms/webapp/settings.page'; import {conversation} from '../../poms/webapp/conversation.page'; import {type App} from '../../actions/createApp'; @@ -127,40 +127,45 @@ test.describe('Menu Bar', () => { await expect(loginPage(app.page).loginButton).toBeVisible(); }); - test( - 'Delete conversation content with menu bar', - {tag: ['@TC-11042', '@regression']}, - async ({app, createUser, createTeam, createPage}) => { - const userB = await createUser(); - const {owner: userA} = await createTeam('Test Team', {users: [userB]}); - const userAPage = app.page; - const userBPage = await createPage(); - - await Promise.all([loginUser(userAPage, userA), loginUser(userBPage, userB)]); - await connectWithUser(userAPage, userB); - - await test.step('User A can delete 1:1 conversation', async () => { - await conversationsList(userAPage).getConversation(userB.fullName).open(); - await triggerApplicationMenu(app, ['Delete Content...']); - - await expect(app.page.getByRole('dialog').getByText('Clear content?')).toBeVisible(); - await app.page.getByRole('dialog').getByRole('button', {name: 'Cancel'}).click(); - }); - - await test.step('User A can ping group conversation', async () => { - await createGroup(app.page, 'Test group', [userB]); - await conversationsList(userAPage).getConversation('Test group').open(); - - await triggerApplicationMenu(app, ['Delete Content...']); - await expect(app.page.getByRole('dialog').getByText('Clear content?')).toBeVisible(); - }); + const testCases = [ + { + name: 'Verify opening people popover with menu bar in the conversation', + tag: '@TC-11045', + menuItem: 'People', + verifyDirect: async (page: Page) => { + await expect(page.getByTestId('status-profile-picture')).toBeVisible(); + }, + verifyGroup: async (page: Page) => { + await expect(page.getByTestId('list-users')).toBeVisible(); + }, }, - ); + { + name: 'Delete conversation content with menu bar', + tag: '@TC-11042', + menuItem: 'Delete Content...', + verifyDirect: async (page: Page) => { + await expect(page.getByRole('dialog').getByText('Clear content?')).toBeVisible(); + await page.getByRole('dialog').getByRole('button', {name: 'Cancel'}).click(); + }, + verifyGroup: async (page: Page) => { + await expect(page.getByRole('dialog').getByText('Clear content?')).toBeVisible(); + }, + }, + { + name: 'Verify I can ping 1:1 and group conversation using the menu bar', + tag: '@TC-11043', + menuItem: 'Ping', + verifyDirect: async (page: Page) => { + await expect(conversation(page).systemMessages.filter({hasText: 'You pinged'})).toBeVisible(); + }, + verifyGroup: async (page: Page) => { + await expect(conversation(page).systemMessages.filter({hasText: 'You pinged'})).toBeVisible(); + }, + }, + ]; - test( - 'Verify I can ping 1:1 and group conversation using the menu bar', - {tag: ['@TC-11043', '@regression']}, - async ({app, createUser, createTeam, createPage}) => { + testCases.forEach(({name, tag, menuItem, verifyDirect, verifyGroup}) => { + test(name, {tag: [tag, '@regression']}, async ({app, createUser, createTeam, createPage}) => { const userB = await createUser(); const {owner: userA} = await createTeam('Test Team', {users: [userB]}); const userAPage = app.page; @@ -169,20 +174,18 @@ test.describe('Menu Bar', () => { await Promise.all([loginUser(userAPage, userA), loginUser(userBPage, userB)]); await connectWithUser(userAPage, userB); - await test.step('User A can ping 1:1 conversation', async () => { + await test.step('User A actions in 1:1 conversation', async () => { await conversationsList(userAPage).getConversation(userB.fullName).open(); - await triggerApplicationMenu(app, ['Ping']); - - await expect(conversation(app.page).systemMessages.filter({hasText: 'You pinged'})).toBeVisible(); + await triggerApplicationMenu(app, [menuItem]); + await verifyDirect(app.page); }); - await test.step('User A can ping group conversation', async () => { + await test.step('User A actions in group conversation', async () => { await createGroup(app.page, 'Test group', [userB]); await conversationsList(userAPage).getConversation('Test group').open(); - await triggerApplicationMenu(app, ['Ping']); - - await expect(conversation(app.page).systemMessages.filter({hasText: 'You pinged'})).toBeVisible(); + await triggerApplicationMenu(app, [menuItem]); + await verifyGroup(app.page); }); - }, - ); + }); + }); }); From 2da0db74d43b1c9be14bcab63e22ae9190cd86b1 Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Wed, 1 Jul 2026 15:24:22 +0200 Subject: [PATCH 07/10] test: write adding people to the conversation with menu bar (TC-11046) --- e2e-tests/specs/regression/menuBar.spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index ec249555e55..4b5c2ec01f3 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -127,6 +127,21 @@ test.describe('Menu Bar', () => { await expect(loginPage(app.page).loginButton).toBeVisible(); }); + test( + 'Verify adding people to the conversation with menu bar', + {tag: ['@TC-11046', '@regression']}, + async ({app, createUser}) => { + const user = await createUser(); + await loginUser(app.page, user); + + await createGroup(app.page, 'Test group', []); + await conversationsList(app.page).getConversation('Test group').open(); + + await triggerApplicationMenu(app, ['Add People...']); + await expect(app.page.locator('#add-participants')).toBeVisible(); + }, + ); + const testCases = [ { name: 'Verify opening people popover with menu bar in the conversation', From 32cb668af6aa86e92cf32bfecf389396234f1d7f Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Wed, 1 Jul 2026 16:31:31 +0200 Subject: [PATCH 08/10] test: verify starting a call via menu bar (TC-11044) --- e2e-tests/poms/webapp/callCell.page.ts | 1 + e2e-tests/specs/regression/menuBar.spec.ts | 35 +++++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/e2e-tests/poms/webapp/callCell.page.ts b/e2e-tests/poms/webapp/callCell.page.ts index 38322a2dac9..62cb56e95ce 100644 --- a/e2e-tests/poms/webapp/callCell.page.ts +++ b/e2e-tests/poms/webapp/callCell.page.ts @@ -24,6 +24,7 @@ export const callCell = (page: Page) => { return Object.assign(callCell, { acceptCallButton: callCell.getByRole('button', {name: 'Accept'}), + declineButton: callCell.getByRole('button', {name: 'Hang up'}), goFullScreen: page.locator('[data-uie-name="do-maximize-call"]'), }); }; diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index 4b5c2ec01f3..bfc37efacff 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -27,6 +27,7 @@ import {conversationsList} from './../../poms/webapp/conversationList.page'; import {MenuItem} from 'electron'; import {loginPage} from '../../poms/webapp/login.page'; import {connectWithUser} from '../../actions/connectWithUser'; +import {callCell} from '../../poms/webapp/callCell.page'; /** * Triggers an Electron application menu item by matching its label. @@ -143,17 +144,6 @@ test.describe('Menu Bar', () => { ); const testCases = [ - { - name: 'Verify opening people popover with menu bar in the conversation', - tag: '@TC-11045', - menuItem: 'People', - verifyDirect: async (page: Page) => { - await expect(page.getByTestId('status-profile-picture')).toBeVisible(); - }, - verifyGroup: async (page: Page) => { - await expect(page.getByTestId('list-users')).toBeVisible(); - }, - }, { name: 'Delete conversation content with menu bar', tag: '@TC-11042', @@ -177,6 +167,29 @@ test.describe('Menu Bar', () => { await expect(conversation(page).systemMessages.filter({hasText: 'You pinged'})).toBeVisible(); }, }, + { + name: 'Verify starting a call via the menu bar', + tag: '@TC-11044', + menuItem: 'Call', + verifyDirect: async (page: Page) => { + await expect(callCell(page)).toBeVisible(); + await callCell(page).declineButton.click(); + }, + verifyGroup: async (page: Page) => { + await expect(callCell(page)).toBeVisible(); + }, + }, + { + name: 'Verify opening people popover with menu bar in the conversation', + tag: '@TC-11045', + menuItem: 'People', + verifyDirect: async (page: Page) => { + await expect(page.getByTestId('status-profile-picture')).toBeVisible(); + }, + verifyGroup: async (page: Page) => { + await expect(page.getByTestId('list-users')).toBeVisible(); + }, + }, ]; testCases.forEach(({name, tag, menuItem, verifyDirect, verifyGroup}) => { From f8097c63d3d64afabe1de553510de678a52b1189 Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Wed, 1 Jul 2026 17:39:13 +0200 Subject: [PATCH 09/10] test: verify archiving conversations with menu bar --- .../poms/webapp/conversationsSidebar.page.ts | 1 + e2e-tests/specs/regression/menuBar.spec.ts | 72 +++++++++++++++---- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/e2e-tests/poms/webapp/conversationsSidebar.page.ts b/e2e-tests/poms/webapp/conversationsSidebar.page.ts index 99d5b42401f..7b583b9d8ac 100644 --- a/e2e-tests/poms/webapp/conversationsSidebar.page.ts +++ b/e2e-tests/poms/webapp/conversationsSidebar.page.ts @@ -25,5 +25,6 @@ export const conversationsSidebar = (page: Page) => { return { userAvatar: sidebar.getByTestId('element-avatar-user'), connectButton: sidebar.getByTestId('go-people'), + archiveButton: sidebar.getByTestId('go-archive'), }; }; diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index bfc37efacff..21750d507f3 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -17,30 +17,30 @@ * */ +import {MenuItem} from 'electron'; + +import {conversationsList} from './../../poms/webapp/conversationList.page'; + +import {connectWithUser} from '../../actions/connectWithUser'; +import {type App} from '../../actions/createApp'; import {createGroup} from '../../actions/createGroup'; import {loginUser} from '../../actions/loginUser'; import {test, expect, Page} from '../../fixtures'; -import {settingsPage} from '../../poms/webapp/settings.page'; +import {callCell} from '../../poms/webapp/callCell.page'; import {conversation} from '../../poms/webapp/conversation.page'; -import {type App} from '../../actions/createApp'; -import {conversationsList} from './../../poms/webapp/conversationList.page'; -import {MenuItem} from 'electron'; +import {conversationsSidebar} from '../../poms/webapp/conversationsSidebar.page'; import {loginPage} from '../../poms/webapp/login.page'; -import {connectWithUser} from '../../actions/connectWithUser'; -import {callCell} from '../../poms/webapp/callCell.page'; +import {settingsPage} from '../../poms/webapp/settings.page'; /** * Triggers an Electron application menu item by matching its label. * Supports cross-platform variants by accepting either a single string or an array of strings. * * @param {object} app - The Playwright Electron application instance - * @param {string|string[]} labels - The menu label(s) to match against (e.g., 'Settings' or ['Preferences', 'Settings']) + * @param {string[]} labels - The menu label(s) to match against (e.g., 'Settings' or ['Preferences', 'Settings']) * @returns A Promise resolving to the serialized accelerator string of the clicked MenuItem */ const triggerApplicationMenu = async (app: App, labels: string[]): Promise> => { - // Normalize input to an array so we can consistently use .includes() - const labelList = Array.isArray(labels) ? labels : [labels]; - return await app.evaluate(async ({Menu, BrowserWindow}, targets) => { const menu = Menu.getApplicationMenu(); @@ -60,7 +60,7 @@ const triggerApplicationMenu = async (app: App, labels: string[]): Promise { @@ -138,11 +138,51 @@ test.describe('Menu Bar', () => { await createGroup(app.page, 'Test group', []); await conversationsList(app.page).getConversation('Test group').open(); - await triggerApplicationMenu(app, ['Add People...']); + const menuItem = await triggerApplicationMenu(app, ['Add People...']); + + expect(menuItem.accelerator).toBe('Shift+CmdOrCtrl+K'); await expect(app.page.locator('#add-participants')).toBeVisible(); }, ); + test( + 'Archive a 1:1 and a group conversation with menu bar', + {tag: ['@TC-11067', '@regression']}, + async ({app, createUser, createTeam, createPage}) => { + const userB = await createUser(); + const {owner: userA} = await createTeam('Test Team', {users: [userB]}); + const userAPage = app.page; + const userBPage = await createPage(); + + await Promise.all([loginUser(userAPage, userA), loginUser(userBPage, userB)]); + await connectWithUser(userAPage, userB); + + await createGroup(app.page, 'Test group', []); + await expect(conversationsList(app.page).items).toHaveCount(2); + + await test.step('Archive in 1:1 conversation', async () => { + await conversationsList(app.page).getConversation(userB.fullName).open(); + const menuItem = await triggerApplicationMenu(app, ['Archive']); + + expect(menuItem.accelerator).toBe('CmdOrCtrl+D'); + await expect(conversationsList(app.page).getConversation(userB.fullName)).not.toBeVisible(); + await expect(conversationsList(app.page).items).toHaveCount(1); + }); + + await test.step('Archive group conversation', async () => { + await conversationsList(userAPage).getConversation('Test group').open(); + await triggerApplicationMenu(app, ['Archive']); + await expect(conversationsList(app.page).getConversation(userB.fullName)).not.toBeVisible(); + await expect(conversationsList(app.page).items).toHaveCount(0); + }); + + await test.step('Confirm that conversations were moved to archive folder', async () => { + await conversationsSidebar(userAPage).archiveButton.click(); + await expect(conversationsList(app.page).items).toHaveCount(2); + }); + }, + ); + const testCases = [ { name: 'Delete conversation content with menu bar', @@ -183,6 +223,7 @@ test.describe('Menu Bar', () => { name: 'Verify opening people popover with menu bar in the conversation', tag: '@TC-11045', menuItem: 'People', + expectedAccelerator: 'CmdOrCtrl+I', verifyDirect: async (page: Page) => { await expect(page.getByTestId('status-profile-picture')).toBeVisible(); }, @@ -192,7 +233,7 @@ test.describe('Menu Bar', () => { }, ]; - testCases.forEach(({name, tag, menuItem, verifyDirect, verifyGroup}) => { + testCases.forEach(({name, tag, menuItem, expectedAccelerator, verifyDirect, verifyGroup}) => { test(name, {tag: [tag, '@regression']}, async ({app, createUser, createTeam, createPage}) => { const userB = await createUser(); const {owner: userA} = await createTeam('Test Team', {users: [userB]}); @@ -204,7 +245,10 @@ test.describe('Menu Bar', () => { await test.step('User A actions in 1:1 conversation', async () => { await conversationsList(userAPage).getConversation(userB.fullName).open(); - await triggerApplicationMenu(app, [menuItem]); + const menuResult = await triggerApplicationMenu(app, [menuItem]); + if (expectedAccelerator) { + expect(menuResult?.accelerator).toBe(expectedAccelerator); + } await verifyDirect(app.page); }); From c3036a2b795d1c2d6fac4be978af56a0af358f33 Mon Sep 17 00:00:00 2001 From: zhanna_chaikovska Date: Thu, 2 Jul 2026 15:51:29 +0200 Subject: [PATCH 10/10] test: specify protocol for 1:1 conversations --- e2e-tests/specs/regression/menuBar.spec.ts | 59 +++++++++++++--------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/e2e-tests/specs/regression/menuBar.spec.ts b/e2e-tests/specs/regression/menuBar.spec.ts index 21750d507f3..dd76cdfa2b5 100644 --- a/e2e-tests/specs/regression/menuBar.spec.ts +++ b/e2e-tests/specs/regression/menuBar.spec.ts @@ -50,7 +50,7 @@ const triggerApplicationMenu = async (app: App, labels: string[]): Promise { const menuItem = await triggerApplicationMenu(app, ['Add People...']); expect(menuItem.accelerator).toBe('Shift+CmdOrCtrl+K'); - await expect(app.page.locator('#add-participants')).toBeVisible(); + await expect(app.page.getByRole('complementary').filter({hasText: 'Add participants'})).toBeVisible(); }, ); @@ -161,18 +161,18 @@ test.describe('Menu Bar', () => { await expect(conversationsList(app.page).items).toHaveCount(2); await test.step('Archive in 1:1 conversation', async () => { - await conversationsList(app.page).getConversation(userB.fullName).open(); + await conversationsList(app.page).getConversation(userB.fullName, {protocol: 'mls'}).open(); const menuItem = await triggerApplicationMenu(app, ['Archive']); expect(menuItem.accelerator).toBe('CmdOrCtrl+D'); - await expect(conversationsList(app.page).getConversation(userB.fullName)).not.toBeVisible(); + await expect(conversationsList(app.page).getConversation(userB.fullName, {protocol: 'mls'})).not.toBeVisible(); await expect(conversationsList(app.page).items).toHaveCount(1); }); await test.step('Archive group conversation', async () => { await conversationsList(userAPage).getConversation('Test group').open(); await triggerApplicationMenu(app, ['Archive']); - await expect(conversationsList(app.page).getConversation(userB.fullName)).not.toBeVisible(); + await expect(conversationsList(app.page).getConversation(userB.fullName, {protocol: 'mls'})).not.toBeVisible(); await expect(conversationsList(app.page).items).toHaveCount(0); }); @@ -219,21 +219,9 @@ test.describe('Menu Bar', () => { await expect(callCell(page)).toBeVisible(); }, }, - { - name: 'Verify opening people popover with menu bar in the conversation', - tag: '@TC-11045', - menuItem: 'People', - expectedAccelerator: 'CmdOrCtrl+I', - verifyDirect: async (page: Page) => { - await expect(page.getByTestId('status-profile-picture')).toBeVisible(); - }, - verifyGroup: async (page: Page) => { - await expect(page.getByTestId('list-users')).toBeVisible(); - }, - }, ]; - testCases.forEach(({name, tag, menuItem, expectedAccelerator, verifyDirect, verifyGroup}) => { + testCases.forEach(({name, tag, menuItem, verifyDirect, verifyGroup}) => { test(name, {tag: [tag, '@regression']}, async ({app, createUser, createTeam, createPage}) => { const userB = await createUser(); const {owner: userA} = await createTeam('Test Team', {users: [userB]}); @@ -244,11 +232,8 @@ test.describe('Menu Bar', () => { await connectWithUser(userAPage, userB); await test.step('User A actions in 1:1 conversation', async () => { - await conversationsList(userAPage).getConversation(userB.fullName).open(); - const menuResult = await triggerApplicationMenu(app, [menuItem]); - if (expectedAccelerator) { - expect(menuResult?.accelerator).toBe(expectedAccelerator); - } + await conversationsList(userAPage).getConversation(userB.fullName, {protocol: 'mls'}).open(); + await triggerApplicationMenu(app, [menuItem]); await verifyDirect(app.page); }); @@ -260,4 +245,32 @@ test.describe('Menu Bar', () => { }); }); }); + + test( + 'Verify opening people popover with menu bar in the conversation', + {tag: ['@TC-11045', '@regression']}, + async ({app, createUser, createTeam, createPage}) => { + const userB = await createUser(); + const {owner: userA} = await createTeam('Test Team', {users: [userB]}); + const userAPage = app.page; + const userBPage = await createPage(); + + await Promise.all([loginUser(userAPage, userA), loginUser(userBPage, userB)]); + await connectWithUser(userAPage, userB); + + await test.step('User A can open people popover in 1:1 conversation', async () => { + await conversationsList(userAPage).getConversation(userB.fullName, {protocol: 'mls'}).open(); + const menuResult = await triggerApplicationMenu(app, ['People']); + expect(menuResult?.accelerator).toBe('CmdOrCtrl+I'); + await expect(app.page.getByTestId('status-profile-picture')).toBeVisible(); + }); + + await test.step('User A can open conversation details in group conversation', async () => { + await createGroup(app.page, 'Test group', [userB]); + await conversationsList(userAPage).getConversation('Test group').open(); + await triggerApplicationMenu(app, ['People']); + await expect(app.page.getByTestId('list-users')).toBeVisible(); + }); + }, + ); });