Skip to content

Commit 1789e71

Browse files
committed
test(room list item menu): add tests for view model
1 parent 9b1ad6b commit 1789e71

File tree

2 files changed

+174
-1
lines changed

2 files changed

+174
-1
lines changed

test/test-utils/test-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ export function mkStubRoom(
603603
getState: (): RoomState | undefined => undefined,
604604
} as unknown as EventTimeline;
605605
return {
606-
canInvite: jest.fn(),
606+
canInvite: jest.fn().mockReturnValue(false),
607607
client,
608608
findThreadForEvent: jest.fn(),
609609
createThreadsTimelineSets: jest.fn().mockReturnValue(new Promise(() => {})),
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
import { renderHook } from "jest-matrix-react";
9+
import { mocked } from "jest-mock";
10+
import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix";
11+
12+
import { mkStubRoom, stubClient, withClientContextRenderOptions } from "../../../../test-utils";
13+
import { useRoomListItemMenuViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListItemMenuViewModel";
14+
import { hasAccessToOptionsMenu } from "../../../../../src/components/viewmodels/roomlist/utils";
15+
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
16+
import { DefaultTagID } from "../../../../../src/stores/room-list/models";
17+
import { useUnreadNotifications } from "../../../../../src/hooks/useUnreadNotifications";
18+
import { NotificationLevel } from "../../../../../src/stores/notifications/NotificationLevel";
19+
import { clearRoomNotification, setMarkedUnreadState } from "../../../../../src/utils/notifications";
20+
import { tagRoom } from "../../../../../src/utils/room/tagRoom";
21+
import dispatcher from "../../../../../src/dispatcher/dispatcher";
22+
23+
jest.mock("../../../../../src/components/viewmodels/roomlist/utils", () => ({
24+
hasAccessToOptionsMenu: jest.fn().mockReturnValue(false),
25+
}));
26+
27+
jest.mock("../../../../../src/hooks/useUnreadNotifications", () => ({
28+
useUnreadNotifications: jest.fn(),
29+
}));
30+
31+
jest.mock("../../../../../src/utils/notifications", () => ({
32+
clearRoomNotification: jest.fn(),
33+
setMarkedUnreadState: jest.fn(),
34+
}));
35+
36+
jest.mock("../../../../../src/utils/room/tagRoom", () => ({
37+
tagRoom: jest.fn(),
38+
}));
39+
40+
describe("RoomListItemMenuViewModel", () => {
41+
let matrixClient: MatrixClient;
42+
let room: Room;
43+
44+
beforeEach(() => {
45+
matrixClient = stubClient();
46+
room = mkStubRoom("roomId", "roomName", matrixClient);
47+
48+
DMRoomMap.makeShared(matrixClient);
49+
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(null);
50+
51+
mocked(useUnreadNotifications).mockReturnValue({ symbol: null, count: 0, level: NotificationLevel.None });
52+
jest.spyOn(dispatcher, "dispatch");
53+
});
54+
55+
afterEach(() => {
56+
jest.resetAllMocks();
57+
});
58+
59+
function render() {
60+
return renderHook(() => useRoomListItemMenuViewModel(room), withClientContextRenderOptions(matrixClient));
61+
}
62+
63+
it("default", () => {
64+
const { result } = render();
65+
expect(result.current.showMoreOptionsMenu).toBe(false);
66+
expect(result.current.canInvite).toBe(false);
67+
expect(result.current.isFavourite).toBe(false);
68+
expect(result.current.canCopyRoomLink).toBe(true);
69+
expect(result.current.canMarkAsRead).toBe(false);
70+
expect(result.current.canMarkAsUnread).toBe(true);
71+
});
72+
73+
it("should has showMoreOptionsMenu to be true", () => {
74+
mocked(hasAccessToOptionsMenu).mockReturnValue(true);
75+
const { result } = render();
76+
expect(result.current.showMoreOptionsMenu).toBe(true);
77+
});
78+
79+
it("should be able to invite", () => {
80+
jest.spyOn(room, "canInvite").mockReturnValue(true);
81+
const { result } = render();
82+
expect(result.current.canInvite).toBe(true);
83+
});
84+
85+
it("should be a favourite", () => {
86+
room.tags = { [DefaultTagID.Favourite]: { order: 0 } };
87+
const { result } = render();
88+
expect(result.current.isFavourite).toBe(true);
89+
});
90+
91+
it("should not be able to copy the room link", () => {
92+
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue("userId");
93+
const { result } = render();
94+
expect(result.current.canCopyRoomLink).toBe(false);
95+
});
96+
97+
it("should be able to mark as read", () => {
98+
// Add a notification
99+
mocked(useUnreadNotifications).mockReturnValue({
100+
symbol: null,
101+
count: 1,
102+
level: NotificationLevel.Notification,
103+
});
104+
const { result } = render();
105+
expect(result.current.canMarkAsRead).toBe(true);
106+
expect(result.current.canMarkAsUnread).toBe(false);
107+
});
108+
109+
// Actions
110+
111+
it("should mark as read", () => {
112+
const { result } = render();
113+
result.current.markAsRead(new Event("click"));
114+
expect(mocked(clearRoomNotification)).toHaveBeenCalledWith(room, matrixClient);
115+
});
116+
117+
it("should mark as unread", () => {
118+
const { result } = render();
119+
result.current.markAsUnread(new Event("click"));
120+
expect(mocked(setMarkedUnreadState)).toHaveBeenCalledWith(room, matrixClient, true);
121+
});
122+
123+
it("should tag a room as favourite", () => {
124+
const { result } = render();
125+
result.current.toggleFavorite(new Event("click"));
126+
expect(mocked(tagRoom)).toHaveBeenCalledWith(room, DefaultTagID.Favourite);
127+
});
128+
129+
it("should tag a room as low priority", () => {
130+
const { result } = render();
131+
result.current.toggleLowPriority();
132+
expect(mocked(tagRoom)).toHaveBeenCalledWith(room, DefaultTagID.LowPriority);
133+
});
134+
135+
it("should dispatch invite action", () => {
136+
const { result } = render();
137+
result.current.invite(new Event("click"));
138+
expect(dispatcher.dispatch).toHaveBeenCalledWith({
139+
action: "view_invite",
140+
roomId: room.roomId,
141+
});
142+
});
143+
144+
it("should dispatch a copy room action", () => {
145+
const { result } = render();
146+
result.current.copyRoomLink(new Event("click"));
147+
expect(dispatcher.dispatch).toHaveBeenCalledWith({
148+
action: "copy_room",
149+
room_id: room.roomId,
150+
});
151+
});
152+
153+
it("should dispatch forget room action", () => {
154+
// forget room is only available for archived rooms
155+
room.tags = { [DefaultTagID.Archived]: { order: 0 } };
156+
157+
const { result } = render();
158+
result.current.leaveRoom(new Event("click"));
159+
expect(dispatcher.dispatch).toHaveBeenCalledWith({
160+
action: "forget_room",
161+
room_id: room.roomId,
162+
});
163+
});
164+
165+
it("should dispatch leave room action", () => {
166+
const { result } = render();
167+
result.current.leaveRoom(new Event("click"));
168+
expect(dispatcher.dispatch).toHaveBeenCalledWith({
169+
action: "leave_room",
170+
room_id: room.roomId,
171+
});
172+
});
173+
});

0 commit comments

Comments
 (0)