New room list: add notification options menu (#29639)

* feat: add `utils.hasAccessToNotificationMenu`

* feat(room list item view model): use `hasAccessToNotificationMenu` to compute `showHoverMenu`

* feat(room list item menu view model): add notification options menu attributes

* feat(room list item menu view): add notification options

* test: add tests for `utils.hasAccessToNotificationMenu`

* test(room list item view model): add test for `showHoverMenu`

* test(room list item menu view model): add tests for new attributes

* test(room list item menu view): add tests for notification options menu

* chore: update i18n

* test(e2e): update screenshots

* test(e2e): add tests for notification options menu
This commit is contained in:
Florian Duros
2025-04-02 14:30:27 +02:00
committed by GitHub
parent 31a59a5fa3
commit 817d7b78b8
16 changed files with 448 additions and 23 deletions
@@ -17,6 +17,7 @@ import {
import type { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
import { mkRoom, stubClient } from "../../../../../test-utils";
import { RoomListItemMenuView } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListItemMenuView";
import { RoomNotifState } from "../../../../../../src/RoomNotifs";
jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListItemMenuViewModel", () => ({
useRoomListItemMenuViewModel: jest.fn(),
@@ -25,11 +26,16 @@ jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListItemMenu
describe("<RoomListItemMenuView />", () => {
const defaultValue: RoomListItemMenuViewState = {
showMoreOptionsMenu: true,
showNotificationMenu: true,
isFavourite: true,
canInvite: true,
canMarkAsUnread: true,
canMarkAsRead: true,
canCopyRoomLink: true,
isNotificationAllMessage: true,
isNotificationMentionOnly: true,
isNotificationAllMessageLoud: true,
isNotificationMute: true,
copyRoomLink: jest.fn(),
markAsUnread: jest.fn(),
markAsRead: jest.fn(),
@@ -37,6 +43,7 @@ describe("<RoomListItemMenuView />", () => {
toggleLowPriority: jest.fn(),
toggleFavorite: jest.fn(),
invite: jest.fn(),
setRoomNotifState: jest.fn(),
};
let matrixClient: MatrixClient;
@@ -58,22 +65,37 @@ describe("<RoomListItemMenuView />", () => {
expect(asFragment()).toMatchSnapshot();
});
it("should render the notification options menu", () => {
const { asFragment } = renderMenu();
expect(screen.getByRole("button", { name: "Notification options" })).toBeInTheDocument();
expect(asFragment()).toMatchSnapshot();
});
it("should not render the more options menu when showMoreOptionsMenu is false", () => {
mocked(useRoomListItemMenuViewModel).mockReturnValue({ ...defaultValue, showMoreOptionsMenu: false });
renderMenu();
expect(screen.queryByRole("button", { name: "More Options" })).toBeNull();
});
it("should call setMenuOpen when the menu is opened", async () => {
const user = userEvent.setup();
const setMenuOpen = jest.fn();
renderMenu(setMenuOpen);
await user.click(screen.getByRole("button", { name: "More Options" }));
expect(setMenuOpen).toHaveBeenCalledWith(true);
it("should not render the notification options menu when showNotificationMenu is false", () => {
mocked(useRoomListItemMenuViewModel).mockReturnValue({ ...defaultValue, showNotificationMenu: false });
renderMenu();
expect(screen.queryByRole("button", { name: "Notification options" })).toBeNull();
});
it("should display all the buttons and have the actions linked", async () => {
it.each([["More Options"], ["Notification options"]])(
"should call setMenuOpen when the menu is opened for %s menu",
async (label) => {
const user = userEvent.setup();
const setMenuOpen = jest.fn();
renderMenu(setMenuOpen);
await user.click(screen.getByRole("button", { name: label }));
expect(setMenuOpen).toHaveBeenCalledWith(true);
},
);
it("should display all the buttons and have the actions linked for the more options menu", async () => {
const user = userEvent.setup();
renderMenu();
@@ -107,4 +129,27 @@ describe("<RoomListItemMenuView />", () => {
await user.click(screen.getByRole("menuitem", { name: "Leave room" }));
expect(defaultValue.leaveRoom).toHaveBeenCalled();
});
it("should display all the buttons and have the actions linked for the notification options menu", async () => {
const user = userEvent.setup();
renderMenu();
const openMenu = screen.getByRole("button", { name: "Notification options" });
await user.click(openMenu);
await user.click(screen.getByRole("menuitem", { name: "Match default settings" }));
expect(defaultValue.setRoomNotifState).toHaveBeenCalledWith(RoomNotifState.AllMessages);
await user.click(openMenu);
await user.click(screen.getByRole("menuitem", { name: "All messages" }));
expect(defaultValue.setRoomNotifState).toHaveBeenCalledWith(RoomNotifState.AllMessagesLoud);
await user.click(openMenu);
await user.click(screen.getByRole("menuitem", { name: "Mentions and keywords" }));
expect(defaultValue.setRoomNotifState).toHaveBeenCalledWith(RoomNotifState.MentionsOnly);
await user.click(openMenu);
await user.click(screen.getByRole("menuitem", { name: "Mute room" }));
expect(defaultValue.setRoomNotifState).toHaveBeenCalledWith(RoomNotifState.Mute);
});
});