From cdedcc0b5ac72a1d3e319800df5ade31461b636a Mon Sep 17 00:00:00 2001 From: byteplow <53381068+byteplow@users.noreply.github.com> Date: Fri, 21 Nov 2025 17:42:44 +0100 Subject: [PATCH] Adds tooltip for compose menu (#31122) * Adds tooltip for compose menu button * fix tests * prettier * tweak aria attributes --- playwright/e2e/crypto/backups-mas.spec.ts | 10 ++++- playwright/e2e/crypto/crypto.spec.ts | 2 +- playwright/e2e/crypto/toasts.spec.ts | 10 ++++- playwright/e2e/crypto/utils.ts | 2 +- playwright/e2e/invite/invite-dialog.spec.ts | 5 ++- .../room-list-panel/room-list-header.spec.ts | 4 +- .../room-list-panel/room-list.spec.ts | 5 ++- playwright/e2e/room/create-room.spec.ts | 2 +- playwright/e2e/voip/element-call.spec.ts | 5 ++- playwright/pages/ElementAppPage.ts | 5 ++- .../RoomListPanel/RoomListHeaderView.tsx | 8 ++-- src/i18n/strings/en_EN.json | 1 + .../RoomListPanel/RoomListHeaderView-test.tsx | 12 +++--- .../RoomListHeaderView-test.tsx.snap | 43 +++++++++++-------- 14 files changed, 72 insertions(+), 42 deletions(-) diff --git a/playwright/e2e/crypto/backups-mas.spec.ts b/playwright/e2e/crypto/backups-mas.spec.ts index 4cada7a49b..f048bc6a2b 100644 --- a/playwright/e2e/crypto/backups-mas.spec.ts +++ b/playwright/e2e/crypto/backups-mas.spec.ts @@ -49,7 +49,10 @@ test.describe("Encryption state after registration", () => { "Pa$sW0rD!", ); - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await page.getByRole("menuitem", { name: "New room" }).click(); await page.getByRole("textbox", { name: "Name" }).fill("test room"); await page.getByRole("button", { name: "Create room" }).click(); @@ -78,7 +81,10 @@ test.describe("Key backup reset from elsewhere", () => { await page.getByRole("button", { name: "Continue" }).click(); await registerAccountMas(page, mailpitClient, testUsername, `${testUsername}@email.com`, testPassword); - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await page.getByRole("menuitem", { name: "New room" }).click(); await page.getByRole("textbox", { name: "Name" }).fill("test room"); await page.getByRole("button", { name: "Create room" }).click(); diff --git a/playwright/e2e/crypto/crypto.spec.ts b/playwright/e2e/crypto/crypto.spec.ts index 71a4e381d1..ae4db1b0c3 100644 --- a/playwright/e2e/crypto/crypto.spec.ts +++ b/playwright/e2e/crypto/crypto.spec.ts @@ -21,7 +21,7 @@ const checkDMRoom = async (page: Page) => { }; const startDMWithBob = async (page: Page, bob: Bot) => { - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "New conversation" }).click(); await page.getByRole("menuitem", { name: "Start chat" }).click(); await page.getByTestId("invite-dialog-input").fill(bob.credentials.userId); await page.getByRole("option", { name: bob.credentials.displayName }).click(); diff --git a/playwright/e2e/crypto/toasts.spec.ts b/playwright/e2e/crypto/toasts.spec.ts index 7c455e5658..5e1dedfdc7 100644 --- a/playwright/e2e/crypto/toasts.spec.ts +++ b/playwright/e2e/crypto/toasts.spec.ts @@ -23,7 +23,10 @@ test.describe("Key storage out of sync toast", () => { await deleteCachedSecrets(page); // We won't be prompted for crypto setup unless we have an e2e room, so make one - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await page.getByRole("menuitem", { name: "New room" }).click(); await page.getByRole("textbox", { name: "Name" }).fill("Test room"); await page.getByRole("button", { name: "Create room" }).click(); @@ -68,7 +71,10 @@ test.describe("'Turn on key storage' toast", () => { await logIntoElementAndVerify(page, credentials, recoveryKey.encodedPrivateKey); // We won't be prompted for crypto setup unless we have an e2e room, so make one - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await page.getByRole("menuitem", { name: "New room" }).click(); await page.getByRole("textbox", { name: "Name" }).fill("Test room"); await page.getByRole("button", { name: "Create room" }).click(); diff --git a/playwright/e2e/crypto/utils.ts b/playwright/e2e/crypto/utils.ts index cf395c31dd..8b677ed4cb 100644 --- a/playwright/e2e/crypto/utils.ts +++ b/playwright/e2e/crypto/utils.ts @@ -438,7 +438,7 @@ export async function sendMessageInCurrentRoom(page: Page, message: string): Pro * @param isEncrypted - Whether the room should be encrypted */ export async function createRoom(page: Page, roomName: string, isEncrypted: boolean): Promise { - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "New conversation" }).click(); await page.getByRole("menuitem", { name: "New room" }).click(); const dialog = page.locator(".mx_Dialog"); diff --git a/playwright/e2e/invite/invite-dialog.spec.ts b/playwright/e2e/invite/invite-dialog.spec.ts index 49139af334..42588f37c7 100644 --- a/playwright/e2e/invite/invite-dialog.spec.ts +++ b/playwright/e2e/invite/invite-dialog.spec.ts @@ -73,7 +73,10 @@ test.describe("Invite dialog", function () { "should support inviting a user to Direct Messages", { tag: "@screenshot" }, async ({ page, app, user, bot }) => { - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await page.getByRole("menuitem", { name: "Start chat" }).click(); const other = page.locator(".mx_InviteDialog_other"); diff --git a/playwright/e2e/left-panel/room-list-panel/room-list-header.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list-header.spec.ts index ed7a24fff8..96e0ca8597 100644 --- a/playwright/e2e/left-panel/room-list-panel/room-list-header.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list-header.spec.ts @@ -30,7 +30,7 @@ test.describe("Header section of the room list", () => { const roomListHeader = getHeaderSection(page); await expect(roomListHeader).toMatchScreenshot("room-list-header.png"); - const composeMenu = roomListHeader.getByRole("button", { name: "Add" }); + const composeMenu = roomListHeader.getByRole("button", { name: "New conversation" }); await composeMenu.click(); await expect(page.getByRole("menu")).toMatchScreenshot("room-list-header-compose-menu.png"); @@ -55,7 +55,7 @@ test.describe("Header section of the room list", () => { await expect(roomListHeader).toMatchScreenshot("room-list-space-header.png"); await expect(roomListHeader.getByRole("heading", { name: "MySpace" })).toBeVisible(); - await expect(roomListHeader.getByRole("button", { name: "Add" })).toBeVisible(); + await expect(roomListHeader.getByRole("button", { name: "New conversation" })).toBeVisible(); const spaceMenu = roomListHeader.getByRole("button", { name: "Open space menu" }); await spaceMenu.click(); diff --git a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts index f1247b038b..6578904fdc 100644 --- a/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts +++ b/playwright/e2e/left-panel/room-list-panel/room-list.spec.ts @@ -315,7 +315,10 @@ test.describe("Room list", () => { }); test("should be a video room", { tag: "@screenshot" }, async ({ page, app, user }) => { - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await page.getByRole("menuitem", { name: "New video room" }).click(); await page.getByRole("textbox", { name: "Name" }).fill("video room"); await page.getByRole("button", { name: "Create video room" }).click(); diff --git a/playwright/e2e/room/create-room.spec.ts b/playwright/e2e/room/create-room.spec.ts index 9424ee4e32..750256e211 100644 --- a/playwright/e2e/room/create-room.spec.ts +++ b/playwright/e2e/room/create-room.spec.ts @@ -45,7 +45,7 @@ test.describe("Create Room", () => { ); test("should allow us to start a chat and show encryption state", async ({ page, user, app }) => { - await page.getByRole("button", { name: "Add", exact: true }).click(); + await page.getByRole("button", { name: "New conversation", exact: true }).click(); await page.getByRole("menuitem", { name: "Start chat" }).click(); await page.getByTestId("invite-dialog-input").fill(user.userId); diff --git a/playwright/e2e/voip/element-call.spec.ts b/playwright/e2e/voip/element-call.spec.ts index b3c31be7ac..846fd5d2ba 100644 --- a/playwright/e2e/voip/element-call.spec.ts +++ b/playwright/e2e/voip/element-call.spec.ts @@ -398,7 +398,10 @@ test.describe("Element Call", () => { }, }); test("should be able to create and join a video room", async ({ page, user }) => { - await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await page.getByRole("menuitem", { name: "New video room" }).click(); await page.getByRole("textbox", { name: "Name" }).fill("Test room"); await page.getByRole("button", { name: "Create video room" }).click(); diff --git a/playwright/pages/ElementAppPage.ts b/playwright/pages/ElementAppPage.ts index d53aec8081..e51ed7b5d4 100644 --- a/playwright/pages/ElementAppPage.ts +++ b/playwright/pages/ElementAppPage.ts @@ -53,7 +53,10 @@ export class ElementAppPage { */ public async openCreateRoomDialog(roomKindname: "New room" | "New video room" = "New room"): Promise { - await this.page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click(); + await this.page + .getByRole("navigation", { name: "Room list" }) + .getByRole("button", { name: "New conversation" }) + .click(); await this.page.getByRole("menuitem", { name: roomKindname }).click(); return this.page.locator(".mx_CreateRoomDialog"); } diff --git a/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx b/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx index 7ce6f28321..6519328ab5 100644 --- a/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx +++ b/src/components/views/rooms/RoomListPanel/RoomListHeaderView.tsx @@ -70,10 +70,10 @@ export function RoomListHeaderView(): JSX.Element { ) : ( vm.createChatRoom(e.nativeEvent)} + tooltip={_t("action|new_conversation")} > - + )} @@ -163,8 +163,8 @@ function ComposeMenu({ vm }: ComposeMenuProps): JSX.Element { side="right" align="start" trigger={ - - + + } > diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 847c9b3f20..f1f4f4dc7c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -93,6 +93,7 @@ "maximise": "Maximise", "mention": "Mention", "minimise": "Minimise", + "new_conversation": "New conversation", "new_room": "New room", "new_video_room": "New video room", "next": "Next", diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListHeaderView-test.tsx b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListHeaderView-test.tsx index 298ca9eae3..8a8c441246 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/RoomListHeaderView-test.tsx +++ b/test/unit-tests/components/views/rooms/RoomListPanel/RoomListHeaderView-test.tsx @@ -57,7 +57,7 @@ describe("", () => { mocked(useRoomListHeaderViewModel).mockReturnValue(defaultValue); const { asFragment } = render(); - expect(screen.queryByRole("button", { name: "Add" })).toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "New conversation" })).toBeInTheDocument(); expect(asFragment()).toMatchSnapshot(); }); @@ -66,10 +66,10 @@ describe("", () => { mocked(useRoomListHeaderViewModel).mockReturnValue({ ...defaultValue, displayComposeMenu: false }); const { asFragment } = render(); - expect(screen.queryByRole("button", { name: "Add" })).toBeNull(); + expect(screen.queryByRole("button", { name: "New conversation" })).toBeInTheDocument(); expect(asFragment()).toMatchSnapshot(); - await user.click(screen.getByRole("button", { name: "Start chat" })); + await user.click(screen.getByRole("button", { name: "New conversation" })); expect(defaultValue.createChatRoom).toHaveBeenCalled(); }); @@ -77,7 +77,7 @@ describe("", () => { const user = userEvent.setup(); mocked(useRoomListHeaderViewModel).mockReturnValue(defaultValue); render(); - const openMenu = screen.getByRole("button", { name: "Add" }); + const openMenu = screen.getByRole("button", { name: "New conversation" }); await user.click(openMenu); await user.click(screen.getByRole("menuitem", { name: "Start chat" })); @@ -101,7 +101,7 @@ describe("", () => { }); render(); - await user.click(screen.getByRole("button", { name: "Add" })); + await user.click(screen.getByRole("button", { name: "New conversation" })); expect(screen.queryByRole("menuitem", { name: "New room" })).toBeNull(); expect(screen.queryByRole("menuitem", { name: "New video room" })).toBeNull(); @@ -157,7 +157,7 @@ describe("", () => { }); render(); - await user.click(screen.getByRole("button", { name: "Add" })); + await user.click(screen.getByRole("button", { name: "Open space menu" })); expect(screen.queryByRole("menuitem", { name: "Invite" })).toBeNull(); expect(screen.queryByRole("menuitem", { name: "Space Setting" })).toBeNull(); diff --git a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap index 50b1119080..99a01c4d47 100644 --- a/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap +++ b/test/unit-tests/components/views/rooms/RoomListPanel/__snapshots__/RoomListHeaderView-test.tsx.snap @@ -25,7 +25,7 @@ exports[` compose menu should display the compose menu 1`] class="_icon-button_1pz9o_8 mx_SpaceMenu_button" data-kind="primary" data-state="closed" - id="radix-_r_k_" + id="radix-_r_q_" role="button" style="--cpd-icon-button-size: 20px;" tabindex="0" @@ -63,11 +63,11 @@ exports[` compose menu should display the compose menu 1`] aria-expanded="false" aria-haspopup="menu" aria-label="Room Options" - aria-labelledby="_r_s_" + aria-labelledby="_r_12_" class="_icon-button_1pz9o_8" data-kind="primary" data-state="closed" - id="radix-_r_q_" + id="radix-_r_10_" role="button" style="--cpd-icon-button-size: 32px;" tabindex="0" @@ -100,11 +100,11 @@ exports[` compose menu should display the compose menu 1`] aria-disabled="false" aria-expanded="false" aria-haspopup="menu" - aria-label="Add" + aria-labelledby="_r_1d_" class="_icon-button_1pz9o_8" data-kind="primary" data-state="closed" - id="radix-_r_15_" + id="radix-_r_1b_" role="button" style="--cpd-icon-button-size: 32px;" tabindex="0" @@ -115,6 +115,7 @@ exports[` compose menu should display the compose menu 1`] style="--cpd-icon-button-size: 100%;" > compose menu should not display the compose menu class="_icon-button_1pz9o_8 mx_SpaceMenu_button" data-kind="primary" data-state="closed" - id="radix-_r_18_" + id="radix-_r_1k_" role="button" style="--cpd-icon-button-size: 20px;" tabindex="0" @@ -202,11 +203,11 @@ exports[` compose menu should not display the compose menu aria-expanded="false" aria-haspopup="menu" aria-label="Room Options" - aria-labelledby="_r_1g_" + aria-labelledby="_r_1s_" class="_icon-button_1pz9o_8" data-kind="primary" data-state="closed" - id="radix-_r_1e_" + id="radix-_r_1q_" role="button" style="--cpd-icon-button-size: 32px;" tabindex="0" @@ -236,7 +237,7 @@ exports[` compose menu should not display the compose menu class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor" >