Fix flaky jest tests (#12486)

...and remove the code that causes them to be retried in CI. Most of
these were just lack of waiting for async things to happen, mostly
lazy loading components, hence whythey worked on the retry: because
the code had been loaded by then.
This commit is contained in:
David Baker 2024-05-02 15:53:35 +01:00 committed by GitHub
parent 7193d4c695
commit 374cee9080
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 36 additions and 27 deletions

View file

@ -197,7 +197,9 @@ describe("ThreadView", () => {
it("sets the correct thread in the room view store", async () => {
// expect(SdkContextClass.instance.roomViewStore.getThreadId()).toBeNull();
const { unmount } = await getComponent();
waitFor(() => {
expect(SdkContextClass.instance.roomViewStore.getThreadId()).toBe(rootEvent.getId());
});
unmount();
await waitFor(() => expect(SdkContextClass.instance.roomViewStore.getThreadId()).toBeNull());

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import React from "react";
import { act, render, screen } from "@testing-library/react";
import { act, render, screen, waitFor } from "@testing-library/react";
import * as maplibregl from "maplibre-gl";
import { Beacon, Room, RoomMember, MatrixEvent, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix";
@ -111,14 +111,16 @@ describe("<BeaconMarker />", () => {
expect(screen.queryByTestId("avatar-img")).not.toBeInTheDocument();
});
it("renders marker when beacon has location", () => {
it("renders marker when beacon has location", async () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent));
beacon?.addLocations([location1]);
const { asFragment } = renderComponent({ beacon });
expect(asFragment()).toMatchSnapshot();
await waitFor(() => {
expect(screen.getByTestId("avatar-img")).toBeInTheDocument();
});
expect(asFragment()).toMatchSnapshot();
});
it("updates with new locations", () => {
const lonLat1 = { lon: 41, lat: 51 };

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import React from "react";
import { act, fireEvent, render, RenderResult } from "@testing-library/react";
import { act, fireEvent, render, RenderResult, waitFor } from "@testing-library/react";
import { MatrixClient, MatrixEvent, Room, RoomMember, getBeaconInfoIdentifier } from "matrix-js-sdk/src/matrix";
import * as maplibregl from "maplibre-gl";
import { mocked } from "jest-mock";
@ -92,7 +92,7 @@ describe("<BeaconViewDialog />", () => {
jest.clearAllMocks();
});
it("renders a map with markers", () => {
it("renders a map with markers", async () => {
const room = setupRoom([defaultEvent]);
const beacon = room.currentState.beacons.get(getBeaconInfoIdentifier(defaultEvent))!;
beacon.addLocations([location1]);
@ -103,8 +103,10 @@ describe("<BeaconViewDialog />", () => {
lat: 51,
});
// marker added
await waitFor(() => {
expect(mockMarker.addTo).toHaveBeenCalledWith(mockMap);
});
});
it("does not render any own beacon status when user is not live sharing", () => {
// default event belongs to alice, we are bob

View file

@ -130,9 +130,9 @@ describe("ForwardDialog", () => {
expect(container.querySelectorAll(".mx_ForwardList_entry")).toHaveLength(3);
const searchInput = getByTestId(container, "searchbox-input");
act(() => userEvent.type(searchInput, "a"));
await userEvent.type(searchInput, "a");
expect(container.querySelectorAll(".mx_ForwardList_entry")).toHaveLength(3);
expect(container.querySelectorAll(".mx_ForwardList_entry")).toHaveLength(2);
});
it("should be navigable using arrow keys", async () => {

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import React, { ComponentProps } from "react";
import { fireEvent, render } from "@testing-library/react";
import { fireEvent, render, waitFor } from "@testing-library/react";
import { LocationAssetType, ClientEvent, RoomMember, SyncState } from "matrix-js-sdk/src/matrix";
import * as maplibregl from "maplibre-gl";
import { logger } from "matrix-js-sdk/src/logger";
@ -90,8 +90,13 @@ describe("MLocationBody", () => {
jest.spyOn(logger, "error").mockRestore();
});
it("displays correct fallback content without error style when map_style_url is not configured", () => {
it("displays correct fallback content without error style when map_style_url is not configured", async () => {
const component = getComponent();
// The map code needs to be lazy loaded so this will take some time to appear
await waitFor(() =>
expect(component.container.querySelector(".mx_EventTile_body")).toBeInTheDocument(),
);
expect(component.container.querySelector(".mx_EventTile_body")).toMatchSnapshot();
});

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import React from "react";
import { render, screen } from "@testing-library/react";
import { render, screen, waitFor } from "@testing-library/react";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import RoomContext from "../../../../src/contexts/RoomContext";
@ -82,7 +82,7 @@ describe("MessageComposerButtons", () => {
expect(getButtonLabels()).toEqual(["Emoji", "Attachment", "More options"]);
});
it("Renders other buttons in menu in wide mode", () => {
it("Renders other buttons in menu in wide mode", async () => {
wrapAndRender(
<MessageComposerButtons
{...mockProps}
@ -94,6 +94,9 @@ describe("MessageComposerButtons", () => {
false,
);
// The location code is lazy loaded, so the button will take a little while
// to appear, so we need to wait.
await waitFor(() => {
expect(getButtonLabels()).toEqual([
"Emoji",
"Attachment",
@ -101,6 +104,7 @@ describe("MessageComposerButtons", () => {
["Sticker", "Voice Message", "Poll", "Location"],
]);
});
});
it("Renders only some buttons in narrow mode", () => {
wrapAndRender(

View file

@ -30,7 +30,7 @@ import {
ThreepidMedium,
} from "matrix-js-sdk/src/matrix";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { act, fireEvent, getByTestId, render, screen, within } from "@testing-library/react";
import { act, fireEvent, getByTestId, render, screen, waitFor, within } from "@testing-library/react";
import { mocked } from "jest-mock";
import userEvent from "@testing-library/user-event";
@ -907,6 +907,7 @@ describe("<Notifications />", () => {
fireEvent.click(clearNotificationEl);
expect(clearNotificationEl.className).toContain("mx_AccessibleButton_disabled");
await waitFor(() => expect(clearNotificationEl.className).not.toContain("mx_AccessibleButton_disabled"));
expect(mockClient.sendReadReceipt).toHaveBeenCalled();
});
});

View file

@ -37,13 +37,6 @@ beforeEach(() => {
});
});
// Retry to work around our flaky app & tests
if (process.env.CI) {
jest.retryTimes(2, {
logErrorsBeforeRetry: true,
});
}
// Very carefully enable the mocks for everything else in
// a specific order. We use this order to ensure we properly
// establish an application state that actually works.