RoomList: move room list header to shared components (#31675)
* chore: ignore jest-sonar.xml in gitconfig * chore: add missing rtl types to shared component * chore: add `symbol` to `Disposables.trackListener` * feat: add room list header view to shared components * fix: change `Space Settings` to `Space settings` * feat: add room list header view model * chore: remove old room list header * chore: update i18n * test: fix Room-test * test: update playwright screenshot * fix: remove extra margin at the top of Sort title in room options * test: fix room status bar test * fix: change for correct copyright * refactor: use `Disposables#track` instead of manually disposing the listener * refactor: avoid to recompute all the snapshot of `RoomListHeaderViewModel` * wip * fix: make header buttons the same size than figma * test: update shared component snapshots * test: update shared component screenshots * test: update EW screenshots
This commit is contained in:
@@ -658,6 +658,9 @@ export function mkStubRoom(
|
||||
getEvents: (): MatrixEvent[] => [],
|
||||
getState: (): RoomState | undefined => state,
|
||||
} as unknown as EventTimeline;
|
||||
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
return {
|
||||
canInvite: jest.fn().mockReturnValue(false),
|
||||
client,
|
||||
@@ -728,9 +731,11 @@ export function mkStubRoom(
|
||||
myUserId: client?.getUserId(),
|
||||
name,
|
||||
normalizedName: normalize(name || ""),
|
||||
off: jest.fn(),
|
||||
on: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
on: eventEmitter.on.bind(eventEmitter),
|
||||
once: eventEmitter.once.bind(eventEmitter),
|
||||
off: eventEmitter.off.bind(eventEmitter),
|
||||
removeListener: eventEmitter.removeListener.bind(eventEmitter),
|
||||
emit: eventEmitter.emit.bind(eventEmitter),
|
||||
roomId,
|
||||
setBlacklistUnverifiedDevices: jest.fn(),
|
||||
setUnreadNotificationCount: jest.fn(),
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* 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 { renderHook, act } from "jest-matrix-react";
|
||||
import { JoinRule, type MatrixClient, type Room, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
import { range } from "lodash";
|
||||
|
||||
import { useRoomListHeaderViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel";
|
||||
import SpaceStore from "../../../../../src/stores/spaces/SpaceStore";
|
||||
import { mkStubRoom, stubClient, withClientContextRenderOptions } from "../../../../test-utils";
|
||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||
import defaultDispatcher from "../../../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../../../src/dispatcher/actions";
|
||||
import {
|
||||
shouldShowSpaceSettings,
|
||||
showCreateNewRoom,
|
||||
showSpaceInvite,
|
||||
showSpacePreferences,
|
||||
showSpaceSettings,
|
||||
} from "../../../../../src/utils/space";
|
||||
import { createRoom, hasCreateRoomRights } from "../../../../../src/components/viewmodels/roomlist/utils";
|
||||
import RoomListStoreV3 from "../../../../../src/stores/room-list-v3/RoomListStoreV3";
|
||||
import { SortOption } from "../../../../../src/components/viewmodels/roomlist/useSorter";
|
||||
import { SortingAlgorithm } from "../../../../../src/stores/room-list-v3/skip-list/sorters";
|
||||
|
||||
jest.mock("../../../../../src/components/viewmodels/roomlist/utils", () => ({
|
||||
hasCreateRoomRights: jest.fn().mockReturnValue(false),
|
||||
createRoom: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../../../../../src/utils/space", () => ({
|
||||
shouldShowSpaceSettings: jest.fn(),
|
||||
showCreateNewRoom: jest.fn(),
|
||||
showSpaceInvite: jest.fn(),
|
||||
showSpacePreferences: jest.fn(),
|
||||
showSpaceSettings: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("useRoomListHeaderViewModel", () => {
|
||||
let matrixClient: MatrixClient;
|
||||
let space: Room;
|
||||
|
||||
beforeEach(() => {
|
||||
matrixClient = stubClient();
|
||||
space = mkStubRoom("spaceId", "spaceName", matrixClient);
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((name: string): any => {
|
||||
if (name === "RoomList.preferredSorting") return SortingAlgorithm.Recency;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
function render() {
|
||||
return renderHook(() => useRoomListHeaderViewModel(), withClientContextRenderOptions(matrixClient));
|
||||
}
|
||||
|
||||
describe("title", () => {
|
||||
it("should return Home as title", () => {
|
||||
const { result } = render();
|
||||
expect(result.current.title).toStrictEqual("Home");
|
||||
});
|
||||
|
||||
it("should return the current space name as title", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const { result } = render();
|
||||
|
||||
expect(result.current.title).toStrictEqual("spaceName");
|
||||
});
|
||||
});
|
||||
|
||||
it("should be displayComposeMenu=true and canCreateRoom=true if the user can creates room", () => {
|
||||
mocked(hasCreateRoomRights).mockReturnValue(false);
|
||||
const { result, rerender } = render();
|
||||
expect(result.current.displayComposeMenu).toBe(false);
|
||||
expect(result.current.canCreateRoom).toBe(false);
|
||||
|
||||
mocked(hasCreateRoomRights).mockReturnValue(true);
|
||||
rerender();
|
||||
expect(result.current.displayComposeMenu).toBe(true);
|
||||
expect(result.current.canCreateRoom).toBe(true);
|
||||
});
|
||||
|
||||
it("should be displaySpaceMenu=true if the user is in a space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const { result } = render();
|
||||
expect(result.current.displaySpaceMenu).toBe(true);
|
||||
});
|
||||
|
||||
it("should be canInviteInSpace=true if the space join rule is public", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
jest.spyOn(space, "getJoinRule").mockReturnValue(JoinRule.Public);
|
||||
|
||||
const { result } = render();
|
||||
expect(result.current.displaySpaceMenu).toBe(true);
|
||||
});
|
||||
|
||||
it("should be canInviteInSpace=true if the user has the right", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
jest.spyOn(space, "canInvite").mockReturnValue(true);
|
||||
|
||||
const { result } = render();
|
||||
expect(result.current.displaySpaceMenu).toBe(true);
|
||||
});
|
||||
|
||||
it("should be canAccessSpaceSettings=true if the user has the right", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
mocked(shouldShowSpaceSettings).mockReturnValue(true);
|
||||
|
||||
const { result } = render();
|
||||
expect(result.current.canAccessSpaceSettings).toBe(true);
|
||||
});
|
||||
|
||||
it("should be canCreateVideoRoom=true if feature_video_rooms is enabled and can create room", () => {
|
||||
mocked(hasCreateRoomRights).mockReturnValue(true);
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
|
||||
|
||||
const { result } = render();
|
||||
expect(result.current.canCreateVideoRoom).toBe(true);
|
||||
});
|
||||
|
||||
it("should fire Action.CreateChat when createChatRoom is called", () => {
|
||||
const spy = jest.spyOn(defaultDispatcher, "fire");
|
||||
const { result } = render();
|
||||
result.current.createChatRoom(new Event("click"));
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(Action.CreateChat);
|
||||
});
|
||||
|
||||
it("should call createRoom from utils when createRoom is called", () => {
|
||||
const { result } = render();
|
||||
result.current.createRoom(new Event("click"));
|
||||
|
||||
expect(createRoom).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call createRoom from utils when createRoom is called in a space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const { result } = render();
|
||||
result.current.createRoom(new Event("click"));
|
||||
|
||||
expect(createRoom).toHaveBeenCalledWith(space);
|
||||
});
|
||||
|
||||
it("should fire Action.CreateRoom with RoomType.UnstableCall when createVideoRoom is called and feature_element_call_video_rooms is enabled", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
|
||||
const spy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||
const { result } = render();
|
||||
result.current.createVideoRoom();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith({ action: Action.CreateRoom, type: RoomType.UnstableCall });
|
||||
});
|
||||
|
||||
it("should fire Action.CreateRoom with RoomType.ElementVideo when createVideoRoom is called and feature_element_call_video_rooms is disabled", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
const spy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||
const { result } = render();
|
||||
result.current.createVideoRoom();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith({ action: Action.CreateRoom, type: RoomType.ElementVideo });
|
||||
});
|
||||
|
||||
it("should call showCreateNewRoom when createVideoRoom is called in a space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const { result } = render();
|
||||
result.current.createVideoRoom();
|
||||
|
||||
expect(showCreateNewRoom).toHaveBeenCalledWith(space, RoomType.ElementVideo);
|
||||
});
|
||||
|
||||
it("should fire Action.ViewRoom when openSpaceHome is called in a space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const spy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||
const { result } = render();
|
||||
result.current.openSpaceHome();
|
||||
|
||||
expect(spy).toHaveBeenCalledWith({ action: Action.ViewRoom, room_id: space.roomId, metricsTrigger: undefined });
|
||||
});
|
||||
|
||||
it("should call showSpaceInvite when inviteInSpace is called in a space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const { result } = render();
|
||||
result.current.inviteInSpace();
|
||||
|
||||
expect(showSpaceInvite).toHaveBeenCalledWith(space);
|
||||
});
|
||||
|
||||
it("should call showSpacePreferences when openSpacePreferences is called in a space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const { result } = render();
|
||||
result.current.openSpacePreferences();
|
||||
|
||||
expect(showSpacePreferences).toHaveBeenCalledWith(space);
|
||||
});
|
||||
|
||||
it("should call showSpaceSettings when openSpaceSettings is called in a space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(space);
|
||||
const { result } = render();
|
||||
result.current.openSpaceSettings();
|
||||
|
||||
expect(showSpaceSettings).toHaveBeenCalledWith(space);
|
||||
});
|
||||
|
||||
describe("Sorting", () => {
|
||||
function mockAndCreateRooms() {
|
||||
const rooms = range(10).map((i) => mkStubRoom(`foo${i}:matrix.org`, `Foo ${i}`, undefined));
|
||||
const fn = jest
|
||||
.spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace")
|
||||
.mockImplementation(() => ({ spaceId: "home", rooms: [...rooms] }));
|
||||
return { rooms, fn };
|
||||
}
|
||||
|
||||
it("should change sort order", () => {
|
||||
mockAndCreateRooms();
|
||||
const { result: vm } = render();
|
||||
|
||||
const resort = jest.spyOn(RoomListStoreV3.instance, "resort").mockImplementation(() => {});
|
||||
|
||||
// Change the sort option
|
||||
act(() => {
|
||||
vm.current.sort(SortOption.AToZ);
|
||||
});
|
||||
|
||||
// Resort method in RLS must have been called
|
||||
expect(resort).toHaveBeenCalledWith(SortingAlgorithm.Alphabetic);
|
||||
});
|
||||
|
||||
it("should set activeSortOption based on value from settings", () => {
|
||||
// Let's say that the user's preferred sorting is alphabetic
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(() => SortingAlgorithm.Alphabetic);
|
||||
|
||||
mockAndCreateRooms();
|
||||
const { result: vm } = render();
|
||||
expect(vm.current.activeSortOption).toEqual(SortOption.AToZ);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* 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 { mocked } from "jest-mock";
|
||||
import { render, screen } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import {
|
||||
type RoomListHeaderViewState,
|
||||
useRoomListHeaderViewModel,
|
||||
} from "../../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel";
|
||||
import { RoomListHeaderView } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListHeaderView";
|
||||
import { SortOption } from "../../../../../../src/components/viewmodels/roomlist/useSorter";
|
||||
|
||||
jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel", () => ({
|
||||
useRoomListHeaderViewModel: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("<RoomListHeaderView />", () => {
|
||||
const defaultValue: RoomListHeaderViewState = {
|
||||
title: "title",
|
||||
displayComposeMenu: true,
|
||||
displaySpaceMenu: true,
|
||||
canCreateRoom: true,
|
||||
canCreateVideoRoom: true,
|
||||
canInviteInSpace: true,
|
||||
canAccessSpaceSettings: true,
|
||||
sort: jest.fn(),
|
||||
activeSortOption: SortOption.Activity,
|
||||
createRoom: jest.fn(),
|
||||
createVideoRoom: jest.fn(),
|
||||
createChatRoom: jest.fn(),
|
||||
openSpaceHome: jest.fn(),
|
||||
inviteInSpace: jest.fn(),
|
||||
openSpacePreferences: jest.fn(),
|
||||
openSpaceSettings: jest.fn(),
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it("should render 'room options' button", async () => {
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue(defaultValue);
|
||||
const { asFragment } = render(<RoomListHeaderView />);
|
||||
expect(screen.getByRole("button", { name: "Room Options" })).toBeInTheDocument();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("compose menu", () => {
|
||||
it("should display the compose menu", () => {
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue(defaultValue);
|
||||
|
||||
const { asFragment } = render(<RoomListHeaderView />);
|
||||
expect(screen.queryByRole("button", { name: "New conversation" })).toBeInTheDocument();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not display the compose menu", async () => {
|
||||
const user = userEvent.setup();
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue({ ...defaultValue, displayComposeMenu: false });
|
||||
|
||||
const { asFragment } = render(<RoomListHeaderView />);
|
||||
expect(screen.queryByRole("button", { name: "New conversation" })).toBeInTheDocument();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "New conversation" }));
|
||||
expect(defaultValue.createChatRoom).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should display all the buttons when the menu is opened", async () => {
|
||||
const user = userEvent.setup();
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue(defaultValue);
|
||||
render(<RoomListHeaderView />);
|
||||
const openMenu = screen.getByRole("button", { name: "New conversation" });
|
||||
await user.click(openMenu);
|
||||
|
||||
await user.click(screen.getByRole("menuitem", { name: "Start chat" }));
|
||||
expect(defaultValue.createChatRoom).toHaveBeenCalled();
|
||||
|
||||
await user.click(openMenu);
|
||||
await user.click(screen.getByRole("menuitem", { name: "New room" }));
|
||||
expect(defaultValue.createRoom).toHaveBeenCalled();
|
||||
|
||||
await user.click(openMenu);
|
||||
await user.click(screen.getByRole("menuitem", { name: "New video room" }));
|
||||
expect(defaultValue.createVideoRoom).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should display only the new message button", async () => {
|
||||
const user = userEvent.setup();
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue({
|
||||
...defaultValue,
|
||||
canCreateRoom: false,
|
||||
canCreateVideoRoom: false,
|
||||
});
|
||||
|
||||
render(<RoomListHeaderView />);
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
describe("space menu", () => {
|
||||
it("should display the space menu", () => {
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue(defaultValue);
|
||||
|
||||
const { asFragment } = render(<RoomListHeaderView />);
|
||||
expect(screen.queryByRole("button", { name: "Open space menu" })).toBeInTheDocument();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not display the space menu", () => {
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue({ ...defaultValue, displaySpaceMenu: false });
|
||||
|
||||
const { asFragment } = render(<RoomListHeaderView />);
|
||||
expect(screen.queryByRole("button", { name: "Open space menu" })).toBeNull();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should display all the buttons when the space menu is opened", async () => {
|
||||
const user = userEvent.setup();
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue(defaultValue);
|
||||
render(<RoomListHeaderView />);
|
||||
const openMenu = screen.getByRole("button", { name: "Open space menu" });
|
||||
await user.click(openMenu);
|
||||
|
||||
await user.click(screen.getByRole("menuitem", { name: "Space home" }));
|
||||
expect(defaultValue.openSpaceHome).toHaveBeenCalled();
|
||||
|
||||
await user.click(openMenu);
|
||||
await user.click(screen.getByRole("menuitem", { name: "Invite" }));
|
||||
expect(defaultValue.inviteInSpace).toHaveBeenCalled();
|
||||
|
||||
await user.click(openMenu);
|
||||
await user.click(screen.getByRole("menuitem", { name: "Preferences" }));
|
||||
expect(defaultValue.openSpacePreferences).toHaveBeenCalled();
|
||||
|
||||
await user.click(openMenu);
|
||||
await user.click(screen.getByRole("menuitem", { name: "Space Settings" }));
|
||||
expect(defaultValue.openSpaceSettings).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should display only the home and preference buttons", async () => {
|
||||
const user = userEvent.setup();
|
||||
mocked(useRoomListHeaderViewModel).mockReturnValue({
|
||||
...defaultValue,
|
||||
canInviteInSpace: false,
|
||||
canAccessSpaceSettings: false,
|
||||
});
|
||||
|
||||
render(<RoomListHeaderView />);
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* 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 RoomListHeaderViewState } from "../../../../../../src/components/viewmodels/roomlist/RoomListHeaderViewModel";
|
||||
|
||||
describe("<RoomListOptionsMenu />", () => {
|
||||
it("should match snapshot", () => {
|
||||
const vm = {
|
||||
sort: jest.fn(),
|
||||
} as unknown as RoomListHeaderViewState;
|
||||
|
||||
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 RoomListHeaderViewState;
|
||||
|
||||
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 RoomListHeaderViewState;
|
||||
|
||||
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 RoomListHeaderViewState;
|
||||
|
||||
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 RoomListHeaderViewState;
|
||||
|
||||
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");
|
||||
});
|
||||
});
|
||||
@@ -1,653 +0,0 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<RoomListHeaderView /> compose menu should display the compose menu 1`] = `
|
||||
<DocumentFragment>
|
||||
<header
|
||||
aria-label="Room options"
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView"
|
||||
data-testid="room-list-header"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView_title"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<h1
|
||||
title="title"
|
||||
>
|
||||
title
|
||||
</h1>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Open space menu"
|
||||
class="_icon-button_1215g_8 mx_SpaceMenu_button"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_i_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 20px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="_flex_4dswl_9"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Room Options"
|
||||
aria-labelledby="_r_m_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_k_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
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>
|
||||
</div>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-labelledby="_r_t_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_r_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<RoomListHeaderView /> compose menu should not display the compose menu 1`] = `
|
||||
<DocumentFragment>
|
||||
<header
|
||||
aria-label="Room options"
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView"
|
||||
data-testid="room-list-header"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView_title"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<h1
|
||||
title="title"
|
||||
>
|
||||
title
|
||||
</h1>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Open space menu"
|
||||
class="_icon-button_1215g_8 mx_SpaceMenu_button"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_14_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 20px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="_flex_4dswl_9"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Room Options"
|
||||
aria-labelledby="_r_18_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_16_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
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>
|
||||
</div>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-labelledby="_r_1d_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<RoomListHeaderView /> should render 'room options' button 1`] = `
|
||||
<DocumentFragment>
|
||||
<header
|
||||
aria-label="Room options"
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView"
|
||||
data-testid="room-list-header"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView_title"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<h1
|
||||
title="title"
|
||||
>
|
||||
title
|
||||
</h1>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Open space menu"
|
||||
class="_icon-button_1215g_8 mx_SpaceMenu_button"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_0_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 20px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="_flex_4dswl_9"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Room Options"
|
||||
aria-labelledby="_r_4_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_2_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
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>
|
||||
</div>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-labelledby="_r_b_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_9_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<RoomListHeaderView /> space menu should display the space menu 1`] = `
|
||||
<DocumentFragment>
|
||||
<header
|
||||
aria-label="Room options"
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView"
|
||||
data-testid="room-list-header"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView_title"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<h1
|
||||
title="title"
|
||||
>
|
||||
title
|
||||
</h1>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Open space menu"
|
||||
class="_icon-button_1215g_8 mx_SpaceMenu_button"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_36_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 20px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="_flex_4dswl_9"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Room Options"
|
||||
aria-labelledby="_r_3a_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_38_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
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>
|
||||
</div>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-labelledby="_r_3h_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_3f_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<RoomListHeaderView /> space menu should not display the space menu 1`] = `
|
||||
<DocumentFragment>
|
||||
<header
|
||||
aria-label="Room options"
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView"
|
||||
data-testid="room-list-header"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="_flex_4dswl_9 mx_RoomListHeaderView_title"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-1x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<h1
|
||||
title="title"
|
||||
>
|
||||
title
|
||||
</h1>
|
||||
</div>
|
||||
<div
|
||||
class="_flex_4dswl_9"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Room Options"
|
||||
aria-labelledby="_r_3q_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_3o_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
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>
|
||||
</div>
|
||||
<div
|
||||
class="mx_RoomListHeaderView_ReleaseAnnouncementAnchor"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-labelledby="_r_41_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_3v_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M16.937 2.82a2 2 0 0 1 2.828 0l1.415 1.414a2 2 0 0 1 0 2.829l-7.071 7.07c-.195.196-.42.342-.66.44a1 1 0 0 1-.168.072l-3.993 1.331a1 1 0 0 1-1.265-1.265l1.331-3.992q.03-.09.073-.168m10.338-4.903-6.717 6.718-1.414-1.414 6.717-6.718z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M3 5a2 2 0 0 1 2-2h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
@@ -1,39 +0,0 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<RoomListOptionsMenu /> should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="Room Options"
|
||||
aria-labelledby="_r_2_"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_0_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
color="var(--cpd-color-icon-secondary)"
|
||||
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>
|
||||
`;
|
||||
@@ -39,12 +39,14 @@ describe("Room", () => {
|
||||
|
||||
const room = new Room(sdkRoom);
|
||||
const fn = jest.fn();
|
||||
const onSpy = jest.spyOn(sdkRoom, "on");
|
||||
const offSpy = jest.spyOn(sdkRoom, "off");
|
||||
|
||||
room.name.watch(fn);
|
||||
expect(sdkRoom.on).toHaveBeenCalledTimes(1);
|
||||
expect(onSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
room.name.unwatch(fn);
|
||||
expect(sdkRoom.off).toHaveBeenCalledTimes(1);
|
||||
expect(offSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
272
test/viewmodels/room-list/RoomListHeaderViewModel-test.ts
Normal file
272
test/viewmodels/room-list/RoomListHeaderViewModel-test.ts
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright 2026 Element Creations 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 { mocked } from "jest-mock";
|
||||
import { JoinRule, type MatrixClient, type Room, RoomEvent, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { RoomListHeaderViewModel } from "../../../src/viewmodels/room-list/RoomListHeaderViewModel";
|
||||
import { MetaSpace, UPDATE_HOME_BEHAVIOUR, UPDATE_SELECTED_SPACE } from "../../../src/stores/spaces";
|
||||
import SpaceStore from "../../../src/stores/spaces/SpaceStore";
|
||||
import defaultDispatcher from "../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../src/dispatcher/actions";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import { SortingAlgorithm } from "../../../src/stores/room-list-v3/skip-list/sorters";
|
||||
import RoomListStoreV3 from "../../../src/stores/room-list-v3/RoomListStoreV3";
|
||||
import {
|
||||
shouldShowSpaceSettings,
|
||||
showCreateNewRoom,
|
||||
showSpaceInvite,
|
||||
showSpacePreferences,
|
||||
showSpaceSettings,
|
||||
} from "../../../src/utils/space";
|
||||
import { createRoom, hasCreateRoomRights } from "../../../src/components/viewmodels/roomlist/utils";
|
||||
import { createTestClient, mkSpace } from "../../test-utils";
|
||||
|
||||
jest.mock("../../../src/PosthogTrackers", () => ({
|
||||
trackInteraction: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../../../src/utils/space", () => ({
|
||||
shouldShowSpaceSettings: jest.fn(),
|
||||
showCreateNewRoom: jest.fn(),
|
||||
showSpaceInvite: jest.fn(),
|
||||
showSpacePreferences: jest.fn(),
|
||||
showSpaceSettings: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../../../src/components/viewmodels/roomlist/utils", () => ({
|
||||
createRoom: jest.fn(),
|
||||
hasCreateRoomRights: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("RoomListHeaderViewModel", () => {
|
||||
let matrixClient: MatrixClient;
|
||||
let mockSpace: Room;
|
||||
let vm: RoomListHeaderViewModel;
|
||||
|
||||
beforeEach(() => {
|
||||
matrixClient = createTestClient();
|
||||
|
||||
mockSpace = mkSpace(matrixClient, "!space:server");
|
||||
|
||||
mocked(hasCreateRoomRights).mockReturnValue(true);
|
||||
mocked(shouldShowSpaceSettings).mockReturnValue(true);
|
||||
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
||||
if (settingName === "RoomList.preferredSorting") return SortingAlgorithm.Recency;
|
||||
if (settingName === "feature_video_rooms") return true;
|
||||
if (settingName === "feature_element_call_video_rooms") return true;
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
vm.dispose();
|
||||
});
|
||||
|
||||
describe("snapshot", () => {
|
||||
it("should compute snapshot for Home space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(MetaSpace.Home);
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(null);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
const snapshot = vm.getSnapshot();
|
||||
expect(snapshot.title).toBe("Home");
|
||||
expect(snapshot.displayComposeMenu).toBe(true);
|
||||
expect(snapshot.displaySpaceMenu).toBe(false);
|
||||
expect(snapshot.canCreateRoom).toBe(true);
|
||||
expect(snapshot.canCreateVideoRoom).toBe(true);
|
||||
expect(snapshot.activeSortOption).toBe("recent");
|
||||
});
|
||||
|
||||
it("should compute snapshot for active space", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
const snapshot = vm.getSnapshot();
|
||||
expect(snapshot.title).toBe(mockSpace.roomId);
|
||||
});
|
||||
|
||||
it("should hide video room option when feature is disabled", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
||||
if (settingName === "feature_video_rooms") return false;
|
||||
return false;
|
||||
});
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
expect(vm.getSnapshot().canCreateVideoRoom).toBe(false);
|
||||
});
|
||||
|
||||
it("should show alphabetical sort option when RoomList.preferredSorting is Alphabetic", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
||||
if (settingName === "RoomList.preferredSorting") return SortingAlgorithm.Alphabetic;
|
||||
return false;
|
||||
});
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
expect(vm.getSnapshot().activeSortOption).toBe("alphabetical");
|
||||
});
|
||||
|
||||
it("should hide compose menu when user cannot create rooms", () => {
|
||||
mocked(hasCreateRoomRights).mockReturnValue(false);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
const snapshot = vm.getSnapshot();
|
||||
expect(snapshot.displayComposeMenu).toBe(false);
|
||||
expect(snapshot.canCreateRoom).toBe(false);
|
||||
});
|
||||
|
||||
it("should show invite option when space is public", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
|
||||
jest.spyOn(mockSpace, "getJoinRule").mockReturnValue(JoinRule.Public);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
expect(vm.getSnapshot().canInviteInSpace).toBe(true);
|
||||
});
|
||||
|
||||
it("should hide invite option when user cannot invite", () => {
|
||||
mocked(mockSpace.canInvite).mockReturnValue(false);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
expect(vm.getSnapshot().canInviteInSpace).toBe(false);
|
||||
});
|
||||
|
||||
it("should hide space settings when user cannot access them", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
||||
mocked(shouldShowSpaceSettings).mockReturnValue(false);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
expect(vm.getSnapshot().canAccessSpaceSettings).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("event listeners", () => {
|
||||
it.each([UPDATE_SELECTED_SPACE, UPDATE_HOME_BEHAVIOUR])(
|
||||
"should update snapshot when %s event is emitted",
|
||||
(event) => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(MetaSpace.Home);
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(null);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
|
||||
SpaceStore.instance.emit(event);
|
||||
|
||||
expect(vm.getSnapshot().title).toBe(mockSpace.roomId);
|
||||
},
|
||||
);
|
||||
|
||||
it("should update snapshot when space name changes", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
mockSpace.name = "new name";
|
||||
mockSpace.emit(RoomEvent.Name, mockSpace);
|
||||
|
||||
expect(vm.getSnapshot().title).toBe("new name");
|
||||
});
|
||||
});
|
||||
|
||||
describe("actions", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpace", "get").mockReturnValue(mockSpace.roomId);
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(mockSpace);
|
||||
});
|
||||
|
||||
it("should fire CreateChat action when createChatRoom is called", () => {
|
||||
const fireSpy = jest.spyOn(defaultDispatcher, "fire");
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
|
||||
vm.createChatRoom(new Event("click"));
|
||||
expect(fireSpy).toHaveBeenCalledWith(Action.CreateChat);
|
||||
});
|
||||
|
||||
it("should call createRoom with active space when in a space", () => {
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.createRoom(new Event("click"));
|
||||
|
||||
expect(createRoom).toHaveBeenCalledWith(mockSpace);
|
||||
});
|
||||
|
||||
it("should show create video room dialog for space when createVideoRoom is called", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
||||
if (settingName === "feature_element_call_video_rooms") return false;
|
||||
return false;
|
||||
});
|
||||
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.createVideoRoom();
|
||||
expect(showCreateNewRoom).toHaveBeenCalledWith(mockSpace, RoomType.ElementVideo);
|
||||
});
|
||||
|
||||
it("should use UnstableCall type when element_call_video_rooms is enabled", () => {
|
||||
jest.spyOn(SpaceStore.instance, "activeSpaceRoom", "get").mockReturnValue(null);
|
||||
|
||||
const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.createVideoRoom();
|
||||
|
||||
expect(dispatchSpy).toHaveBeenCalledWith({
|
||||
action: Action.CreateRoom,
|
||||
type: RoomType.UnstableCall,
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch ViewRoom action when openSpaceHome is called", () => {
|
||||
const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.openSpaceHome();
|
||||
|
||||
expect(dispatchSpy).toHaveBeenCalledWith({
|
||||
action: Action.ViewRoom,
|
||||
room_id: "!space:server",
|
||||
metricsTrigger: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("should show space invite dialog when inviteInSpace is called", () => {
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.inviteInSpace();
|
||||
|
||||
expect(showSpaceInvite).toHaveBeenCalledWith(mockSpace);
|
||||
});
|
||||
|
||||
it("should show space preferences dialog when openSpacePreferences is called", () => {
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.openSpacePreferences();
|
||||
|
||||
expect(showSpacePreferences).toHaveBeenCalledWith(mockSpace);
|
||||
});
|
||||
|
||||
it("should show space settings dialog when openSpaceSettings is called", () => {
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.openSpaceSettings();
|
||||
|
||||
expect(showSpaceSettings).toHaveBeenCalledWith(mockSpace);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["recent" as const, SortingAlgorithm.Recency],
|
||||
["alphabetical" as const, SortingAlgorithm.Alphabetic],
|
||||
])("should resort when sort is called with '%s'", (option, expectedAlgorithm) => {
|
||||
const resortSpy = jest.spyOn(RoomListStoreV3.instance, "resort").mockImplementation(jest.fn());
|
||||
vm = new RoomListHeaderViewModel({ matrixClient, spaceStore: SpaceStore.instance });
|
||||
vm.sort(option);
|
||||
|
||||
expect(resortSpy).toHaveBeenCalledWith(expectedAlgorithm);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -43,7 +43,7 @@ describe("RoomStatusBarViewModel", () => {
|
||||
beforeEach(() => {
|
||||
client = stubClient() as MockedObject<MatrixClient>;
|
||||
room = mkRoom(client, "!example");
|
||||
room.on.mockImplementationOnce((_event, fn) => {
|
||||
jest.spyOn(room, "on").mockImplementationOnce((_event, fn) => {
|
||||
roomEmitFn = fn as any;
|
||||
return room;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user