From 04800c15af67bb084d94787e34e43d481e6572b1 Mon Sep 17 00:00:00 2001 From: Aditya Cherukuru <145639927+aditya-cherukuru@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:13:20 +0530 Subject: [PATCH] Fix flaky MemberListView tests (#31707) Replace unreliable setTimeout(1000) with proper waitFor() patterns for async assertions. Fixes element-hq/element-web#31251 Fixes element-hq/element-web#31582 Signed-off-by: aditya-cherukuru --- .../memberlist/MemberListHeaderView-test.tsx | 11 +++++-- .../rooms/memberlist/MemberListView-test.tsx | 32 ++++++++++++------- .../views/rooms/memberlist/common.tsx | 1 - 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/test/unit-tests/components/views/rooms/memberlist/MemberListHeaderView-test.tsx b/test/unit-tests/components/views/rooms/memberlist/MemberListHeaderView-test.tsx index f072a0360e..b9904edf21 100644 --- a/test/unit-tests/components/views/rooms/memberlist/MemberListHeaderView-test.tsx +++ b/test/unit-tests/components/views/rooms/memberlist/MemberListHeaderView-test.tsx @@ -71,7 +71,7 @@ describe("MemberListHeaderView", () => { memberListRoom.currentState.members[newMember.userId] = newMember; } await reRender(); - expect(screen.queryByPlaceholderText("Search room members")).toBeVisible(); + await waitFor(() => expect(screen.queryByPlaceholderText("Search room members")).toBeVisible()); }); describe("Invite button functionality", () => { @@ -84,7 +84,9 @@ describe("MemberListHeaderView", () => { jest.spyOn(memberListRoom, "getMyMembership").mockReturnValue(KnownMembership.Join); jest.spyOn(memberListRoom, "canInvite").mockReturnValue(false); await reRender(); - expect(screen.getByRole("button", { name: "Invite" })).toHaveAttribute("aria-disabled", "true"); + await waitFor(() => + expect(screen.getByRole("button", { name: "Invite" })).toHaveAttribute("aria-disabled", "true"), + ); }); it("Renders enabled invite button when current user is a member and has rights to invite", async () => { @@ -92,7 +94,9 @@ describe("MemberListHeaderView", () => { jest.spyOn(memberListRoom, "getMyMembership").mockReturnValue(KnownMembership.Join); jest.spyOn(memberListRoom, "canInvite").mockReturnValue(true); await reRender(); - expect(screen.getByRole("button", { name: "Invite" })).not.toHaveAttribute("aria-disabled", "true"); + await waitFor(() => + expect(screen.getByRole("button", { name: "Invite" })).not.toHaveAttribute("aria-disabled", "true"), + ); }); it("Opens room inviter on button click", async () => { @@ -101,6 +105,7 @@ describe("MemberListHeaderView", () => { jest.spyOn(memberListRoom, "canInvite").mockReturnValue(true); await reRender(); + await waitFor(() => expect(screen.getByRole("button", { name: "Invite" })).not.toBeDisabled()); fireEvent.click(screen.getByRole("button", { name: "Invite" })); expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: "view_invite", diff --git a/test/unit-tests/components/views/rooms/memberlist/MemberListView-test.tsx b/test/unit-tests/components/views/rooms/memberlist/MemberListView-test.tsx index 228bc0e9e1..bf4f0326d7 100644 --- a/test/unit-tests/components/views/rooms/memberlist/MemberListView-test.tsx +++ b/test/unit-tests/components/views/rooms/memberlist/MemberListView-test.tsx @@ -191,20 +191,24 @@ describe("MemberListView and MemberlistHeaderView", () => { u.user!.presence = "offline"; }); - await act(reRender); + await reRender(); - const tiles = root.container.querySelectorAll(".mx_MemberTileView"); - expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + await waitFor(() => { + const tiles = root.container.querySelectorAll(".mx_MemberTileView"); + expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + }); }); it("by power level", async () => { const { reRender, root, memberListRoom } = rendered; // We already have admin, moderator, and default users so leave them alone - await act(reRender); + await reRender(); - const tiles = root.container.querySelectorAll(".mx_EntityTile"); - expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + await waitFor(() => { + const tiles = root.container.querySelectorAll(".mx_EntityTile"); + expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + }); }); it("by last active timestamp", async () => { @@ -229,10 +233,12 @@ describe("MemberListView and MemberlistHeaderView", () => { u.user!.lastActiveAgo = 100; }); - await act(reRender); + await reRender(); - const tiles = root.container.querySelectorAll(".mx_EntityTile"); - expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + await waitFor(() => { + const tiles = root.container.querySelectorAll(".mx_EntityTile"); + expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + }); }); it("by name", async () => { @@ -247,10 +253,12 @@ describe("MemberListView and MemberlistHeaderView", () => { u.powerLevel = 100; }); - await act(reRender); + await reRender(); - const tiles = root.container.querySelectorAll(".mx_EntityTile"); - expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + await waitFor(() => { + const tiles = root.container.querySelectorAll(".mx_EntityTile"); + expectOrderedByPresenceAndPowerLevel(memberListRoom, tiles, enablePresence); + }); }); }); }); diff --git a/test/unit-tests/components/views/rooms/memberlist/common.tsx b/test/unit-tests/components/views/rooms/memberlist/common.tsx index 30ea7e9c81..292b983e2c 100644 --- a/test/unit-tests/components/views/rooms/memberlist/common.tsx +++ b/test/unit-tests/components/views/rooms/memberlist/common.tsx @@ -163,6 +163,5 @@ function createReRenderFunction(client: MatrixClient, memberListRoom: Room): Ren getRoomId: () => memberListRoom.roomId, }); }); - await new Promise((r) => setTimeout(r, 1000)); }; }