Add room list sorting (#29951)

* Add room list sorting

* Prettier

* Unit test

* Playwright test

* Lint

* Use released compound

* No tooltip wrapper needed
This commit is contained in:
David Baker
2025-05-15 09:27:33 +01:00
committed by GitHub
parent 76d7f6ab43
commit 1b48269db5
7 changed files with 228 additions and 7 deletions

View File

@@ -0,0 +1,138 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { render, screen } from "jest-matrix-react";
import userEvent from "@testing-library/user-event";
import { RoomListOptionsMenu } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListOptionsMenu";
import { type RoomListViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListViewModel";
describe("<RoomListOptionsMenu />", () => {
it("should match snapshot", () => {
const vm = {
sort: jest.fn(),
} as unknown as RoomListViewState;
const { asFragment } = render(<RoomListOptionsMenu vm={vm} />);
expect(asFragment()).toMatchSnapshot();
});
it("should show A to Z selected if activeSortOption is Alphabetic", async () => {
const user = userEvent.setup();
const vm = {
sort: jest.fn(),
activeSortOption: "Alphabetic",
} as unknown as RoomListViewState;
render(<RoomListOptionsMenu vm={vm} />);
// Open the menu
const button = screen.getByRole("button", { name: "Room Options" });
await user.click(button);
expect(screen.getByRole("menuitemradio", { name: "A-Z" })).toBeChecked();
expect(screen.getByRole("menuitemradio", { name: "Activity" })).not.toBeChecked();
});
it("should show Activity selected if activeSortOption is Recency", async () => {
const user = userEvent.setup();
const vm = {
sort: jest.fn(),
activeSortOption: "Recency",
} as unknown as RoomListViewState;
render(<RoomListOptionsMenu vm={vm} />);
// Open the menu
const button = screen.getByRole("button", { name: "Room Options" });
await user.click(button);
expect(screen.getByRole("menuitemradio", { name: "A-Z" })).not.toBeChecked();
expect(screen.getByRole("menuitemradio", { name: "Activity" })).toBeChecked();
});
it("should sort A to Z", async () => {
const user = userEvent.setup();
const vm = {
sort: jest.fn(),
} as unknown as RoomListViewState;
render(<RoomListOptionsMenu vm={vm} />);
await user.click(screen.getByRole("button", { name: "Room Options" }));
await user.click(screen.getByRole("menuitemradio", { name: "A-Z" }));
expect(vm.sort).toHaveBeenCalledWith("Alphabetic");
});
it("should sort by activity", async () => {
const user = userEvent.setup();
const vm = {
sort: jest.fn(),
activeSortOption: "Alphabetic",
} as unknown as RoomListViewState;
render(<RoomListOptionsMenu vm={vm} />);
await user.click(screen.getByRole("button", { name: "Room Options" }));
await user.click(screen.getByRole("menuitemradio", { name: "Activity" }));
expect(vm.sort).toHaveBeenCalledWith("Recency");
});
it("should show message previews disabled", async () => {
const user = userEvent.setup();
const vm = {
shouldShowMessagePreview: false,
} as unknown as RoomListViewState;
render(<RoomListOptionsMenu vm={vm} />);
await user.click(screen.getByRole("button", { name: "Room Options" }));
expect(screen.getByRole("menuitemcheckbox", { name: "Show message previews" })).not.toBeChecked();
});
it("should show message previews enabled", async () => {
const user = userEvent.setup();
const vm = {
shouldShowMessagePreview: true,
} as unknown as RoomListViewState;
render(<RoomListOptionsMenu vm={vm} />);
await user.click(screen.getByRole("button", { name: "Room Options" }));
expect(screen.getByRole("menuitemcheckbox", { name: "Show message previews" })).toBeChecked();
});
it("should toggle message previews", async () => {
const user = userEvent.setup();
const vm = {
toggleMessagePreview: jest.fn(),
} as unknown as RoomListViewState;
render(<RoomListOptionsMenu vm={vm} />);
await user.click(screen.getByRole("button", { name: "Room Options" }));
await user.click(screen.getByRole("menuitemcheckbox", { name: "Show message previews" }));
expect(vm.toggleMessagePreview).toHaveBeenCalled();
});
});

View File

@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<RoomListOptionsMenu /> should match snapshot 1`] = `
<DocumentFragment>
<button
aria-disabled="false"
aria-expanded="false"
aria-haspopup="menu"
aria-label="Room Options"
aria-labelledby="«r2»"
class="_icon-button_m2erp_8 mx_RoomListSecondaryFilters_roomOptionsButton"
data-state="closed"
id="radix-«r0»"
role="button"
style="--cpd-icon-button-size: 32px;"
tabindex="0"
type="button"
>
<div
class="_indicator-icon_zr2a0_17"
style="--cpd-icon-button-size: 100%;"
>
<svg
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
/>
</svg>
</div>
</button>
</DocumentFragment>
`;