Add more functionality to the room list vm (#29402)
* Add more vm functionality - Listen for updates from the store - Provide a method to open rooms * Write test
This commit is contained in:
@@ -5,14 +5,26 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { useCallback, useState } from "react";
|
||||
|
||||
import type { Room } from "matrix-js-sdk/src/matrix";
|
||||
import type { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import RoomListStoreV3 from "../../../stores/room-list-v3/RoomListStoreV3";
|
||||
import { useEventEmitter } from "../../../hooks/useEventEmitter";
|
||||
import { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
||||
import dispatcher from "../../../dispatcher/dispatcher";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
|
||||
export interface RoomListViewState {
|
||||
/**
|
||||
* A list of rooms to be displayed in the left panel.
|
||||
*/
|
||||
rooms: Room[];
|
||||
|
||||
/**
|
||||
* Open the room having given roomId.
|
||||
*/
|
||||
openRoom: (roomId: string) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,6 +32,20 @@ export interface RoomListViewState {
|
||||
* @see {@link RoomListViewState} for more information about what this view model returns.
|
||||
*/
|
||||
export function useRoomListViewModel(): RoomListViewState {
|
||||
const rooms = RoomListStoreV3.instance.getSortedRooms();
|
||||
return { rooms };
|
||||
const [rooms, setRooms] = useState(RoomListStoreV3.instance.getSortedRoomsInActiveSpace());
|
||||
|
||||
useEventEmitter(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, () => {
|
||||
const newRooms = RoomListStoreV3.instance.getSortedRoomsInActiveSpace();
|
||||
setRooms(newRooms);
|
||||
});
|
||||
|
||||
const openRoom = useCallback((roomId: string): void => {
|
||||
dispatcher.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: roomId,
|
||||
metricsTrigger: "RoomList",
|
||||
});
|
||||
}, []);
|
||||
|
||||
return { rooms, openRoom };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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 { range } from "lodash";
|
||||
import { act, renderHook, waitFor } from "jest-matrix-react";
|
||||
|
||||
import RoomListStoreV3 from "../../../../../src/stores/room-list-v3/RoomListStoreV3";
|
||||
import { mkStubRoom } from "../../../../test-utils";
|
||||
import { LISTS_UPDATE_EVENT } from "../../../../../src/stores/room-list/SlidingRoomListStore";
|
||||
import { useRoomListViewModel } from "../../../../../src/components/viewmodels/roomlist/RoomListViewModel";
|
||||
import dispatcher from "../../../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../../../src/dispatcher/actions";
|
||||
|
||||
describe("RoomListViewModel", () => {
|
||||
function mockAndCreateRooms() {
|
||||
const rooms = range(10).map((i) => mkStubRoom(`foo${i}:matrix.org`, `Foo ${i}`, undefined));
|
||||
jest.spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace").mockImplementation(() => [...rooms]);
|
||||
return rooms;
|
||||
}
|
||||
|
||||
it("should return a list of rooms", async () => {
|
||||
const rooms = mockAndCreateRooms();
|
||||
const { result: vm } = renderHook(() => useRoomListViewModel());
|
||||
|
||||
expect(vm.current.rooms).toHaveLength(10);
|
||||
for (const room of rooms) {
|
||||
expect(vm.current.rooms).toContain(room);
|
||||
}
|
||||
});
|
||||
|
||||
it("should update list of rooms on event from room list store", async () => {
|
||||
const rooms = mockAndCreateRooms();
|
||||
const { result: vm } = renderHook(() => useRoomListViewModel());
|
||||
|
||||
const newRoom = mkStubRoom("bar:matrix.org", "Bar", undefined);
|
||||
rooms.push(newRoom);
|
||||
act(() => RoomListStoreV3.instance.emit(LISTS_UPDATE_EVENT));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(vm.current.rooms).toContain(newRoom);
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch view room action on openRoom", async () => {
|
||||
const rooms = mockAndCreateRooms();
|
||||
const { result: vm } = renderHook(() => useRoomListViewModel());
|
||||
|
||||
const fn = jest.spyOn(dispatcher, "dispatch");
|
||||
act(() => vm.current.openRoom(rooms[7].roomId));
|
||||
expect(fn).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: Action.ViewRoom,
|
||||
room_id: rooms[7].roomId,
|
||||
metricsTrigger: "RoomList",
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user