1
0
mirror of https://github.com/element-hq/element-web.git synced 2025-08-06 16:22:46 +03:00
Files
element-web/test/unit-tests/components/viewmodels/right_panel/RoomSummaryCardViewModel-test.tsx
Marc b07225eb60 Mvvm RoomSummaryCard (#29674)
* feat: create roomsummarycard viewmodel

* feat: use roomsummurycard vm in component

* test: jest unit RoomSummaryCard and RoomSummaryCardViewModel

* chore: rename to roomsummarycardview

* feat: reput room topic without vm

* test: roomSummaryCard and roomSummaryCardVM tests

* chore: add comments on roomsummarycardVM

* fix: merge conflict with roomsummarytopic, and move to vm right_panel

* fix(roomsummarycard): remove usetransition for search update

* fix: merged file that should be deleted

* fix: roomsummurycard not well merge with roomtopic

* test: update snapshots
2025-05-15 14:17:21 +00:00

266 lines
9.4 KiB
TypeScript

/*
* 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 { act, renderHook, waitFor } from "jest-matrix-react";
import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix";
import { useRoomSummaryCardViewModel } from "../../../../../src/components/viewmodels/right_panel/RoomSummaryCardViewModel";
import { mkStubRoom, stubClient, withClientContextRenderOptions } from "../../../../test-utils";
import defaultDispatcher from "../../../../../src/dispatcher/dispatcher";
import RoomListStore from "../../../../../src/stores/room-list/RoomListStore";
import { DefaultTagID } from "../../../../../src/stores/room-list/models";
import RightPanelStore from "../../../../../src/stores/right-panel/RightPanelStore";
import { RightPanelPhases } from "../../../../../src/stores/right-panel/RightPanelStorePhases";
import Modal from "../../../../../src/Modal";
import { ShareDialog } from "../../../../../src/components/views/dialogs/ShareDialog";
import ExportDialog from "../../../../../src/components/views/dialogs/ExportDialog";
import { PollHistoryDialog } from "../../../../../src/components/views/dialogs/PollHistoryDialog";
import { ReportRoomDialog } from "../../../../../src/components/views/dialogs/ReportRoomDialog";
import { inviteToRoom } from "../../../../../src/utils/room/inviteToRoom";
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
import * as hooks from "../../../../../src/hooks/useAccountData";
jest.mock("../../../../../src/utils/room/inviteToRoom", () => ({
inviteToRoom: jest.fn(),
}));
describe("useRoomSummaryCardViewModel", () => {
let matrixClient: MatrixClient;
let room: Room;
let permalinkCreator: any;
const onSearchCancel = jest.fn();
beforeEach(() => {
matrixClient = stubClient();
room = mkStubRoom("roomId", "roomName", matrixClient);
permalinkCreator = {};
DMRoomMap.setShared({
getUserIdForRoomId: jest.fn(),
} as unknown as DMRoomMap);
jest.spyOn(RoomListStore.instance, "getTagsForRoom").mockReturnValue([]);
});
afterEach(() => {
jest.resetAllMocks();
});
function render() {
return renderHook(
() => useRoomSummaryCardViewModel(room, permalinkCreator, onSearchCancel),
withClientContextRenderOptions(matrixClient),
);
}
it("should return correct initial state", () => {
const { result } = render();
expect(result.current.isDirectMessage).toBe(false);
expect(result.current.isRoomEncrypted).toBe(false);
expect(result.current.isVideoRoom).toBe(false);
expect(result.current.isFavorite).toBe(false);
expect(result.current.pinCount).toBe(0);
expect(result.current.searchInputRef.current).toBe(null);
});
it("should handle room members click", () => {
const spy = jest.spyOn(RightPanelStore.instance, "pushCard");
const { result } = render();
result.current.onRoomMembersClick();
expect(spy).toHaveBeenCalledWith({ phase: RightPanelPhases.MemberList }, true);
});
it("should handle room settings click", () => {
const spy = jest.spyOn(defaultDispatcher, "dispatch");
const { result } = render();
result.current.onRoomSettingsClick(new Event("click"));
expect(spy).toHaveBeenCalledWith({ action: "open_room_settings" });
});
it("should handle leave room click", () => {
const spy = jest.spyOn(defaultDispatcher, "dispatch");
const { result } = render();
result.current.onLeaveRoomClick();
expect(spy).toHaveBeenCalledWith({
action: "leave_room",
room_id: room.roomId,
});
});
it("should handle room threads click", () => {
const spy = jest.spyOn(RightPanelStore.instance, "pushCard");
const { result } = render();
result.current.onRoomThreadsClick();
expect(spy).toHaveBeenCalledWith({ phase: RightPanelPhases.ThreadPanel }, true);
});
it("should handle room files click", () => {
const spy = jest.spyOn(RightPanelStore.instance, "pushCard");
const { result } = render();
result.current.onRoomFilesClick();
expect(spy).toHaveBeenCalledWith({ phase: RightPanelPhases.FilePanel }, true);
});
it("should handle room extensions click", () => {
const spy = jest.spyOn(RightPanelStore.instance, "pushCard");
const { result } = render();
result.current.onRoomExtensionsClick();
expect(spy).toHaveBeenCalledWith({ phase: RightPanelPhases.Extensions }, true);
});
it("should handle room pins click", () => {
const spy = jest.spyOn(RightPanelStore.instance, "pushCard");
const { result } = render();
result.current.onRoomPinsClick();
expect(spy).toHaveBeenCalledWith({ phase: RightPanelPhases.PinnedMessages }, true);
});
it("should handle room invite click", () => {
const { result } = render();
result.current.onInviteToRoomClick();
expect(inviteToRoom).toHaveBeenCalledWith(room);
});
describe("action that trigger a dialog", () => {
let createDialogSpy: jest.SpyInstance;
beforeEach(() => {
createDialogSpy = jest.spyOn(Modal, "createDialog").mockImplementation(() => ({
finished: Promise.resolve([false]),
close: jest.fn(),
}));
});
afterEach(() => {
createDialogSpy.mockRestore();
});
it("should handle room export click", async () => {
const { result } = render();
await act(async () => {
await result.current.onRoomExportClick();
});
expect(createDialogSpy).toHaveBeenCalledWith(ExportDialog, { room });
});
it("should handle room poll history click", async () => {
const { result } = render();
await act(async () => {
await result.current.onRoomPollHistoryClick();
});
expect(createDialogSpy).toHaveBeenCalledWith(PollHistoryDialog, {
room,
matrixClient,
permalinkCreator,
});
});
it("should handle room report click", async () => {
const { result } = render();
await act(async () => {
await result.current.onReportRoomClick();
});
expect(createDialogSpy).toHaveBeenCalledWith(ReportRoomDialog, { roomId: room.roomId });
});
it("should handle share room click", async () => {
const { result } = render();
await act(async () => {
await result.current.onShareRoomClick();
});
expect(createDialogSpy).toHaveBeenCalledWith(ShareDialog, {
target: room,
});
});
});
describe("favorite room state", () => {
it("should identify favorite rooms", () => {
jest.spyOn(RoomListStore.instance, "getTagsForRoom").mockReturnValue([DefaultTagID.Favourite]);
const { result } = render();
expect(result.current.isFavorite).toBe(true);
});
it("should identify non-favorite rooms", () => {
jest.spyOn(RoomListStore.instance, "getTagsForRoom").mockReturnValue([]);
const { result } = render();
expect(result.current.isFavorite).toBe(false);
});
});
describe("direct message state", () => {
it("should identify direct message rooms", async () => {
// Mock the direct rooms account data
const directRoomsList = {
"@user:domain.com": [room.roomId],
};
// Mock the useAccountData hook result
jest.spyOn(hooks, "useAccountData").mockReturnValue(directRoomsList);
const { result } = render();
await waitFor(() => {
expect(result.current.isDirectMessage).toBe(true);
});
});
it("should identify non-direct message rooms", async () => {
// Mock the direct rooms account data
const directRoomsList = {};
// Mock the useAccountData hook result
jest.spyOn(hooks, "useAccountData").mockReturnValue(directRoomsList);
const { result } = render();
await waitFor(() => {
expect(result.current.isDirectMessage).toBe(false);
});
});
});
describe("search input", () => {
it("should handle search input escape key", () => {
const directRoomsList = {};
jest.spyOn(hooks, "useAccountData").mockReturnValue(directRoomsList);
const { result } = render();
// Create a mock input element and set it as the current ref value
const mockInputElement = document.createElement("input");
mockInputElement.value = "some search text";
result.current.searchInputRef.current = mockInputElement;
const event = {
key: "Escape",
preventDefault: jest.fn(),
stopPropagation: jest.fn(),
};
result.current.onUpdateSearchInput(event as any);
expect(onSearchCancel).toHaveBeenCalled();
expect(mockInputElement?.value).toBe("");
});
});
});