Files
Florian Duros 1c66f0ba01 Room list: extract getTagsForRoom from old room list store (#32716)
* refactor: extract `getTagsForRoom` from old rls

`getTagsForRoom` doesn't rely on the rls state. We can extract it safely
to an external function.

The function is not moved into the rls v3 because the rls is for the
room list and not for other ui elements.

* refactor: remove dead code

* test: add more tests for `getTagsForRoom`

* refactor: `getTagsForRoom` in old rls

* doc: add missing tsdoc for `room`
2026-03-04 17:14:48 +00:00

183 lines
6.6 KiB
TypeScript

/*
Copyright 2024 New Vector Ltd.
Copyright 2022, 2023 The Matrix.org Foundation C.I.C.
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 { fireEvent, getByLabelText, render, screen } from "jest-matrix-react";
import { mocked } from "jest-mock";
import { ReceiptType, type MatrixClient, PendingEventOrdering, Room } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import React from "react";
import userEvent from "@testing-library/user-event";
import { sleep } from "matrix-js-sdk/src/utils";
import { ChevronFace } from "../../../../../src/components/structures/ContextMenu";
import {
RoomGeneralContextMenu,
type RoomGeneralContextMenuProps,
} from "../../../../../src/components/views/context_menus/RoomGeneralContextMenu";
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
import { DefaultTagID } from "../../../../../src/stores/room-list-v3/skip-list/tag";
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
import { mkMessage, stubClient } from "../../../../test-utils/test-utils";
import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents";
import { UIComponent } from "../../../../../src/settings/UIFeature";
import SettingsStore from "../../../../../src/settings/SettingsStore";
import { clearAllModals } from "../../../../test-utils";
import * as getTagsForRoomUtils from "../../../../../src/utils/room/getTagsForRoom";
jest.mock("../../../../../src/customisations/helpers/UIComponents", () => ({
shouldShowComponent: jest.fn(),
}));
describe("RoomGeneralContextMenu", () => {
const ROOM_ID = "!123:matrix.org";
let room: Room;
let mockClient: MatrixClient;
let onFinished: () => void;
function getComponent(props?: Partial<RoomGeneralContextMenuProps>) {
return render(
<MatrixClientContext.Provider value={mockClient}>
<RoomGeneralContextMenu
room={room}
onFinished={onFinished}
{...props}
managed={true}
mountAsChild={true}
left={1}
top={1}
chevronFace={ChevronFace.Left}
/>
</MatrixClientContext.Provider>,
);
}
beforeEach(() => {
jest.clearAllMocks();
stubClient();
mockClient = mocked(MatrixClientPeg.safeGet());
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
pendingEventOrdering: PendingEventOrdering.Detached,
});
const dmRoomMap = {
getUserIdForRoomId: jest.fn(),
} as unknown as DMRoomMap;
DMRoomMap.setShared(dmRoomMap);
jest.spyOn(getTagsForRoomUtils, "getTagsForRoom").mockReturnValueOnce([
DefaultTagID.DM,
DefaultTagID.Favourite,
]);
onFinished = jest.fn();
});
afterEach(async () => {
await clearAllModals();
});
it("renders an empty context menu for archived rooms", async () => {
jest.spyOn(getTagsForRoomUtils, "getTagsForRoom").mockReturnValueOnce([DefaultTagID.Archived]);
const { container } = getComponent({});
expect(container).toMatchSnapshot();
});
it("renders the default context menu", async () => {
const { container } = getComponent({});
expect(container).toMatchSnapshot();
});
it("does not render invite menu item when UIComponent customisations disable room invite", () => {
room.updateMyMembership(KnownMembership.Join);
jest.spyOn(room, "canInvite").mockReturnValue(true);
mocked(shouldShowComponent).mockReturnValue(false);
getComponent({});
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.InviteUsers);
expect(screen.queryByRole("menuitem", { name: "Invite" })).not.toBeInTheDocument();
});
it("renders invite menu item when UIComponent customisations enables room invite", () => {
room.updateMyMembership(KnownMembership.Join);
jest.spyOn(room, "canInvite").mockReturnValue(true);
mocked(shouldShowComponent).mockReturnValue(true);
getComponent({});
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.InviteUsers);
expect(screen.getByRole("menuitem", { name: "Invite" })).toBeInTheDocument();
});
it("marks the room as read", async () => {
const event = mkMessage({
event: true,
room: "!room:id",
user: "@user:id",
ts: 1000,
});
room.addLiveEvents([event], { addToState: true });
const { container } = getComponent({});
const markAsReadBtn = getByLabelText(container, "Mark as read");
fireEvent.click(markAsReadBtn);
await sleep(0);
expect(mockClient.sendReadReceipt).toHaveBeenCalledWith(event, ReceiptType.Read, true);
expect(onFinished).toHaveBeenCalled();
});
it("marks the room as unread", async () => {
room.updateMyMembership("join");
const { container } = getComponent({});
const markAsUnreadBtn = getByLabelText(container, "Mark as unread");
fireEvent.click(markAsUnreadBtn);
await sleep(0);
expect(mockClient.setRoomAccountData).toHaveBeenCalledWith(ROOM_ID, "m.marked_unread", {
unread: true,
});
expect(onFinished).toHaveBeenCalled();
});
it("when developer mode is disabled, it should not render the developer tools option", () => {
getComponent();
expect(screen.queryByText("Developer tools")).not.toBeInTheDocument();
});
describe("when developer mode is enabled", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => setting === "developerMode");
getComponent();
});
it("should render the developer tools option", async () => {
const developerToolsItem = screen.getByRole("menuitem", { name: "Developer tools" });
expect(developerToolsItem).toBeInTheDocument();
// click open developer tools dialog
await userEvent.click(developerToolsItem);
// assert that the dialog is displayed by searching some if its contents
expect(await screen.findByText("Toolbox")).toBeInTheDocument();
expect(await screen.findByText(`Room ID: ${ROOM_ID}`)).toBeInTheDocument();
});
});
});