Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit e5d348a

Browse files
committed
Write additional test for both issues
- Thread dropdown should be shown if there is any thread, even if not participated - Thread list correctly updates after every change of the dropdown immediately
1 parent 05d6e15 commit e5d348a

File tree

1 file changed

+192
-7
lines changed

1 file changed

+192
-7
lines changed

test/components/structures/ThreadPanel-test.tsx

Lines changed: 192 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,23 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import React from "react";
18-
import { render, screen, fireEvent } from "@testing-library/react";
19-
import { mocked } from "jest-mock";
17+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
2018
import "focus-visible"; // to fix context menus
19+
import { mocked } from "jest-mock";
20+
import React from "react";
21+
import { MatrixClient, MatrixEvent, PendingEventOrdering, Room } from "matrix-js-sdk/src/matrix";
22+
import { FeatureSupport, Thread } from "matrix-js-sdk/src/models/thread";
2123

2224
import ThreadPanel, { ThreadFilterType, ThreadPanelHeader } from "../../../src/components/structures/ThreadPanel";
25+
import MatrixClientContext from "../../../src/contexts/MatrixClientContext";
26+
import RoomContext from "../../../src/contexts/RoomContext";
2327
import { _t } from "../../../src/languageHandler";
24-
import ResizeNotifier from "../../../src/utils/ResizeNotifier";
25-
import { RoomPermalinkCreator } from "../../../src/utils/permalinks/Permalinks";
26-
import { createTestClient, mkStubRoom } from "../../test-utils";
28+
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
2729
import { shouldShowFeedback } from "../../../src/utils/Feedback";
28-
import MatrixClientContext from "../../../src/contexts/MatrixClientContext";
30+
import { RoomPermalinkCreator } from "../../../src/utils/permalinks/Permalinks";
31+
import ResizeNotifier from "../../../src/utils/ResizeNotifier";
32+
import { createTestClient, getRoomContext, mkStubRoom, mockPlatformPeg, stubClient } from "../../test-utils";
33+
import { mkThread } from "../../test-utils/threads";
2934

3035
jest.mock("../../../src/utils/Feedback");
3136

@@ -122,4 +127,184 @@ describe("ThreadPanel", () => {
122127
expect(foundButton).toMatchSnapshot();
123128
});
124129
});
130+
131+
describe("Filtering", () => {
132+
const ROOM_ID = "!roomId:example.org";
133+
const SENDER = "@alice:example.org";
134+
135+
let mockClient: MatrixClient;
136+
let room: Room;
137+
138+
const TestThreadPanel = () => (
139+
<MatrixClientContext.Provider value={mockClient}>
140+
<RoomContext.Provider
141+
value={getRoomContext(room, {
142+
canSendMessages: true,
143+
})}
144+
>
145+
<ThreadPanel
146+
roomId={ROOM_ID}
147+
onClose={jest.fn()}
148+
resizeNotifier={new ResizeNotifier()}
149+
permalinkCreator={new RoomPermalinkCreator(room)}
150+
/>
151+
</RoomContext.Provider>
152+
</MatrixClientContext.Provider>
153+
);
154+
155+
beforeEach(async () => {
156+
jest.clearAllMocks();
157+
158+
stubClient();
159+
mockPlatformPeg();
160+
mockClient = mocked(MatrixClientPeg.get());
161+
Thread.setServerSideSupport(FeatureSupport.Stable);
162+
Thread.setServerSideListSupport(FeatureSupport.Stable);
163+
Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable);
164+
jest.spyOn(mockClient, "supportsExperimentalThreads").mockReturnValue(true);
165+
166+
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
167+
pendingEventOrdering: PendingEventOrdering.Detached,
168+
});
169+
jest.spyOn(room, "fetchRoomThreads").mockReturnValue(Promise.resolve());
170+
jest.spyOn(mockClient, "getRoom").mockReturnValue(room);
171+
await room.createThreadsTimelineSets();
172+
const [allThreads, myThreads] = room.threadsTimelineSets;
173+
jest.spyOn(room, "createThreadsTimelineSets")
174+
.mockReturnValue(Promise.resolve([allThreads, myThreads]));
175+
});
176+
177+
function toggleThreadFilter(container: HTMLElement, newFilter: ThreadFilterType) {
178+
fireEvent.click(container.querySelector(".mx_ThreadPanel_dropdown"));
179+
const found = screen.queryAllByRole("menuitemradio");
180+
expect(found).toHaveLength(2);
181+
182+
const allThreadsContent = `${_t("All threads")}${_t("Shows all threads from current room")}`;
183+
const myThreadsContent = `${_t("My threads")}${_t("Shows all threads you've participated in")}`;
184+
185+
const allThreadsOption = found.find(it => it.textContent === allThreadsContent);
186+
const myThreadsOption = found.find(it => it.textContent === myThreadsContent);
187+
expect(allThreadsOption).toBeTruthy();
188+
expect(myThreadsOption).toBeTruthy();
189+
190+
const toSelect = newFilter === ThreadFilterType.My ? myThreadsOption : allThreadsOption;
191+
fireEvent.click(toSelect);
192+
}
193+
194+
type EventData = { sender: string, content: string };
195+
196+
function findEvents(container: HTMLElement): EventData[] {
197+
return Array.from(container.querySelectorAll(".mx_EventTile")).map(el => {
198+
const sender = el.querySelector(".mx_DisambiguatedProfile_displayName").textContent;
199+
const content = el.querySelector(".mx_EventTile_body").textContent;
200+
return { sender, content };
201+
});
202+
}
203+
204+
function toEventData(event: MatrixEvent): EventData {
205+
return { sender: event.event.sender, content: event.event.content.body };
206+
}
207+
208+
it("correctly filters Thread List with multiple threads", async () => {
209+
const otherThread = mkThread({
210+
room,
211+
client: mockClient,
212+
authorId: SENDER,
213+
participantUserIds: [mockClient.getUserId()],
214+
});
215+
216+
const mixedThread = mkThread({
217+
room,
218+
client: mockClient,
219+
authorId: SENDER,
220+
participantUserIds: [SENDER, mockClient.getUserId()],
221+
});
222+
223+
const ownThread = mkThread({
224+
room,
225+
client: mockClient,
226+
authorId: mockClient.getUserId(),
227+
participantUserIds: [mockClient.getUserId()],
228+
});
229+
230+
const threadRoots = [otherThread.rootEvent, mixedThread.rootEvent, ownThread.rootEvent];
231+
jest.spyOn(mockClient, "fetchRoomEvent").mockImplementation(
232+
(_, eventId) => Promise.resolve(threadRoots.find(it => it.getId() === eventId).event),
233+
);
234+
const [allThreads, myThreads] = room.threadsTimelineSets;
235+
allThreads.addLiveEvent(otherThread.rootEvent);
236+
allThreads.addLiveEvent(mixedThread.rootEvent);
237+
allThreads.addLiveEvent(ownThread.rootEvent);
238+
myThreads.addLiveEvent(mixedThread.rootEvent);
239+
myThreads.addLiveEvent(ownThread.rootEvent);
240+
241+
let events: EventData[] = [];
242+
const renderResult = render(<TestThreadPanel />);
243+
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
244+
await waitFor(() => {
245+
events = findEvents(renderResult.container);
246+
expect(findEvents(renderResult.container)).toHaveLength(3);
247+
});
248+
expect(events[0]).toEqual(toEventData(otherThread.rootEvent));
249+
expect(events[1]).toEqual(toEventData(mixedThread.rootEvent));
250+
expect(events[2]).toEqual(toEventData(ownThread.rootEvent));
251+
await waitFor(() => expect(renderResult.container.querySelector(".mx_ThreadPanel_dropdown")).toBeTruthy());
252+
toggleThreadFilter(renderResult.container, ThreadFilterType.My);
253+
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
254+
await waitFor(() => {
255+
events = findEvents(renderResult.container);
256+
expect(findEvents(renderResult.container)).toHaveLength(2);
257+
});
258+
expect(events[0]).toEqual(toEventData(mixedThread.rootEvent));
259+
expect(events[1]).toEqual(toEventData(ownThread.rootEvent));
260+
toggleThreadFilter(renderResult.container, ThreadFilterType.All);
261+
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
262+
await waitFor(() => {
263+
events = findEvents(renderResult.container);
264+
expect(findEvents(renderResult.container)).toHaveLength(3);
265+
});
266+
expect(events[0]).toEqual(toEventData(otherThread.rootEvent));
267+
expect(events[1]).toEqual(toEventData(mixedThread.rootEvent));
268+
expect(events[2]).toEqual(toEventData(ownThread.rootEvent));
269+
});
270+
271+
it("correctly filters Thread List with a single, unparticipated thread", async () => {
272+
const otherThread = mkThread({
273+
room,
274+
client: mockClient,
275+
authorId: SENDER,
276+
participantUserIds: [mockClient.getUserId()],
277+
});
278+
279+
const threadRoots = [otherThread.rootEvent];
280+
jest.spyOn(mockClient, "fetchRoomEvent").mockImplementation(
281+
(_, eventId) => Promise.resolve(threadRoots.find(it => it.getId() === eventId).event),
282+
);
283+
const [allThreads] = room.threadsTimelineSets;
284+
allThreads.addLiveEvent(otherThread.rootEvent);
285+
286+
let events: EventData[] = [];
287+
const renderResult = render(<TestThreadPanel />);
288+
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
289+
await waitFor(() => {
290+
events = findEvents(renderResult.container);
291+
expect(findEvents(renderResult.container)).toHaveLength(1);
292+
});
293+
expect(events[0]).toEqual(toEventData(otherThread.rootEvent));
294+
await waitFor(() => expect(renderResult.container.querySelector(".mx_ThreadPanel_dropdown")).toBeTruthy());
295+
toggleThreadFilter(renderResult.container, ThreadFilterType.My);
296+
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
297+
await waitFor(() => {
298+
events = findEvents(renderResult.container);
299+
expect(findEvents(renderResult.container)).toHaveLength(0);
300+
});
301+
toggleThreadFilter(renderResult.container, ThreadFilterType.All);
302+
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
303+
await waitFor(() => {
304+
events = findEvents(renderResult.container);
305+
expect(findEvents(renderResult.container)).toHaveLength(1);
306+
});
307+
expect(events[0]).toEqual(toEventData(otherThread.rootEvent));
308+
});
309+
})
125310
});

0 commit comments

Comments
 (0)