* Move Room List to ListView - Also remove Space/Enter handing from keyboard navigation we can just leave the default behaviour of those keys and handle via onClick * Update rooms when the primary filter changes Otherwise when changing spaces, the filter does not reset until the next update to the RVS is made. * Fix stickyRow/scrollIntoView when switiching space or changing filters - Also remove the rest of space/enter keyboard handling use * Remove the rest of space/enter keyboard handling use * Remove useCombinedRef and add @radix-ui/react-compose-refs as we already depend on it - Also remove eact-virtualized dep * Update RoomList unit test * Update snapshots and unit tests * Fix e2e tests * Remove react-virtualized from tests * Fix e2e flake * Update more screenshots * Fix e2e test case where were should scroll to the top when the active room is no longer in the list * Move from gitpkg to package-patch * Update to latest react virtuoso release/api. Also pass spaceId to the room list and scroll the activeIndex into view when spaceId or primaryFilter change. * Use listbox/option roles to improve ScreenReader experience * Change onKeyDown e.stopPropogation to cover context menu * lint * Remove unneeded exposure of the listView ref Also move scrollIntoViewOnChange to useCallback * Update unit test and snapshot * Fix e2e tests and update screenshots * Fix unit test and snapshot * Update more unit tests * Fix keyboard shortcuts and e2e test * Fix another e2e and unit test * lint * Improve the naming for RoomResult and the documentation on it's fields meaning. Also update the login in RoomList to check for any change in filters, this is a bit more future proof for when we introduce multi select than using activePrimaryFilter. * Put back and fix landmark tests * Fix test import * Add comment regarding context object getting rendered. * onKeyDown should be optional * Use SpaceKey type on RoomResult * lint
112 lines
4.9 KiB
TypeScript
112 lines
4.9 KiB
TypeScript
/*
|
|
Copyright 2024 New Vector Ltd.
|
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
|
|
|
|
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 { act, fireEvent, screen, waitFor } from "jest-matrix-react";
|
|
import { RoomMember, User, RoomEvent } from "matrix-js-sdk/src/matrix";
|
|
import { KnownMembership } from "matrix-js-sdk/src/types";
|
|
import { mocked } from "jest-mock";
|
|
|
|
import { shouldShowComponent } from "../../../../../../src/customisations/helpers/UIComponents";
|
|
import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher";
|
|
import { type Rendered, renderMemberList } from "./common";
|
|
|
|
jest.mock("../../../../../../src/customisations/helpers/UIComponents", () => ({
|
|
shouldShowComponent: jest.fn(),
|
|
}));
|
|
|
|
jest.spyOn(HTMLElement.prototype, "offsetHeight", "get").mockReturnValue(1500);
|
|
jest.spyOn(HTMLElement.prototype, "offsetWidth", "get").mockReturnValue(1500);
|
|
|
|
describe("Does not render invite button in memberlist header", () => {
|
|
it("when user is not a member", async () => {
|
|
await renderMemberList(true, (room) => room.updateMyMembership(KnownMembership.Leave));
|
|
expect(screen.queryByRole("button", { name: "Invite" })).toBeNull();
|
|
});
|
|
|
|
it("when UI customisation hides invites", async () => {
|
|
mocked(shouldShowComponent).mockReturnValue(false);
|
|
const { client, memberListRoom } = await renderMemberList(true);
|
|
// Needs this specific event...
|
|
act(() => {
|
|
client.emit(RoomEvent.MyMembership, memberListRoom, KnownMembership.Join, KnownMembership.Invite);
|
|
});
|
|
await waitFor(() => expect(screen.queryByRole("button", { name: "Invite" })).toBeNull());
|
|
});
|
|
});
|
|
|
|
describe("MemberListHeaderView", () => {
|
|
let rendered: Rendered;
|
|
|
|
beforeEach(async function () {
|
|
mocked(shouldShowComponent).mockReturnValue(true);
|
|
rendered = await renderMemberList(true);
|
|
});
|
|
|
|
it("Shows the correct member count", async () => {
|
|
expect(await screen.findByText("6 Members")).toBeVisible();
|
|
});
|
|
|
|
it("Does not show search box when there's less than 20 members", async () => {
|
|
expect(screen.queryByPlaceholderText("Search room members")).toBeNull();
|
|
});
|
|
|
|
it("Shows search box when there's more than 20 members", async () => {
|
|
const { memberListRoom, client, reRender } = rendered;
|
|
// Memberlist already has 6 members, add 14 more to make the total 20
|
|
for (let i = 0; i < 14; ++i) {
|
|
const newMember = new RoomMember(memberListRoom.roomId, `@new${i}:localhost`);
|
|
newMember.membership = KnownMembership.Join;
|
|
newMember.powerLevel = 0;
|
|
newMember.user = User.createUser(newMember.userId, client);
|
|
newMember.user.currentlyActive = true;
|
|
newMember.user.presence = "online";
|
|
newMember.user.lastPresenceTs = 1000;
|
|
newMember.user.lastActiveAgo = 10;
|
|
memberListRoom.currentState.members[newMember.userId] = newMember;
|
|
}
|
|
await reRender();
|
|
expect(screen.queryByPlaceholderText("Search room members")).toBeVisible();
|
|
});
|
|
|
|
describe("Invite button functionality", () => {
|
|
afterEach(() => {
|
|
jest.restoreAllMocks();
|
|
});
|
|
|
|
it("Renders disabled invite button when current user is a member but does not have rights to invite", async () => {
|
|
const { memberListRoom, reRender } = rendered;
|
|
jest.spyOn(memberListRoom, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
|
jest.spyOn(memberListRoom, "canInvite").mockReturnValue(false);
|
|
await reRender();
|
|
expect(screen.getByRole("button", { name: "Invite" })).toHaveAttribute("aria-disabled", "true");
|
|
});
|
|
|
|
it("Renders enabled invite button when current user is a member and has rights to invite", async () => {
|
|
const { memberListRoom, reRender } = rendered;
|
|
jest.spyOn(memberListRoom, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
|
jest.spyOn(memberListRoom, "canInvite").mockReturnValue(true);
|
|
await reRender();
|
|
expect(screen.getByRole("button", { name: "Invite" })).not.toHaveAttribute("aria-disabled", "true");
|
|
});
|
|
|
|
it("Opens room inviter on button click", async () => {
|
|
const { memberListRoom, reRender } = rendered;
|
|
jest.spyOn(defaultDispatcher, "dispatch");
|
|
jest.spyOn(memberListRoom, "canInvite").mockReturnValue(true);
|
|
await reRender();
|
|
|
|
fireEvent.click(screen.getByRole("button", { name: "Invite" }));
|
|
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({
|
|
action: "view_invite",
|
|
roomId: memberListRoom.roomId,
|
|
});
|
|
});
|
|
});
|
|
});
|