Make tests more resilient for React 18 upgrade (#12861)
* Make tests more resilient for React 18 upgrade Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
@@ -30,7 +30,16 @@ import {
|
||||
ThreepidMedium,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||
import { act, fireEvent, getByTestId, render, screen, waitFor, within } from "@testing-library/react";
|
||||
import {
|
||||
act,
|
||||
fireEvent,
|
||||
getByTestId,
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
within,
|
||||
} from "@testing-library/react";
|
||||
import { mocked } from "jest-mock";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
@@ -244,7 +253,7 @@ describe("<Notifications />", () => {
|
||||
// get component, wait for async data and force a render
|
||||
const getComponentAndWait = async () => {
|
||||
const component = getComponent();
|
||||
await flushPromises();
|
||||
await waitForElementToBeRemoved(() => component.queryAllByRole("progressbar"));
|
||||
return component;
|
||||
};
|
||||
|
||||
@@ -527,7 +536,9 @@ describe("<Notifications />", () => {
|
||||
// oneToOneRule is set to 'on'
|
||||
// and is kind: 'underride'
|
||||
const offToggle = screen.getByTestId(section + oneToOneRule.rule_id).querySelector('input[type="radio"]')!;
|
||||
fireEvent.click(offToggle);
|
||||
await act(() => {
|
||||
fireEvent.click(offToggle);
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
|
||||
@@ -552,7 +563,9 @@ describe("<Notifications />", () => {
|
||||
// oneToOneRule is set to 'on'
|
||||
// and is kind: 'underride'
|
||||
const offToggle = screen.getByTestId(section + oneToOneRule.rule_id).querySelector('input[type="radio"]')!;
|
||||
fireEvent.click(offToggle);
|
||||
await act(() => {
|
||||
fireEvent.click(offToggle);
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
|
||||
@@ -576,7 +589,7 @@ describe("<Notifications />", () => {
|
||||
|
||||
await flushPromises();
|
||||
|
||||
// no error after after successful change
|
||||
// no error after successful change
|
||||
expect(
|
||||
within(oneToOneRuleElement).queryByText(
|
||||
"An error occurred when updating your notification preferences. Please try to toggle your option again.",
|
||||
@@ -716,7 +729,9 @@ describe("<Notifications />", () => {
|
||||
mockClient.setPushRuleActions.mockRejectedValue("oups");
|
||||
|
||||
const offToggle = oneToOneRuleElement.querySelector('input[type="radio"]')!;
|
||||
fireEvent.click(offToggle);
|
||||
await act(() => {
|
||||
fireEvent.click(offToggle);
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
|
||||
@@ -814,7 +829,9 @@ describe("<Notifications />", () => {
|
||||
|
||||
mockClient.setPushRuleEnabled.mockRejectedValueOnce("oups");
|
||||
|
||||
fireEvent.click(within(screen.getByTestId(section + keywordsRuleId)).getByLabelText("Off"));
|
||||
await act(() => {
|
||||
fireEvent.click(within(screen.getByTestId(section + keywordsRuleId)).getByLabelText("Off"));
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen, within } from "@testing-library/react";
|
||||
import { fireEvent, render, screen, waitFor, within } from "@testing-library/react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||
@@ -99,6 +99,6 @@ describe("SetIntegrationManager", () => {
|
||||
|
||||
expect(logger.error).toHaveBeenCalledWith("Error changing integration manager provisioning");
|
||||
expect(logger.error).toHaveBeenCalledWith("oups");
|
||||
expect(within(integrationSection).getByRole("switch")).not.toBeChecked();
|
||||
await waitFor(() => expect(within(integrationSection).getByRole("switch")).not.toBeChecked());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -108,7 +108,7 @@ describe("<DeviceDetailHeading />", () => {
|
||||
});
|
||||
|
||||
it("toggles out of editing mode when device name is saved successfully", async () => {
|
||||
const { getByTestId } = render(getComponent());
|
||||
const { getByTestId, findByTestId } = render(getComponent());
|
||||
|
||||
// start editing
|
||||
fireEvent.click(getByTestId("device-heading-rename-cta"));
|
||||
@@ -118,12 +118,12 @@ describe("<DeviceDetailHeading />", () => {
|
||||
await flushPromisesWithFakeTimers();
|
||||
|
||||
// read mode displayed
|
||||
expect(getByTestId("device-detail-heading")).toBeTruthy();
|
||||
await expect(findByTestId("device-detail-heading")).resolves.toBeTruthy();
|
||||
});
|
||||
|
||||
it("displays error when device name fails to save", async () => {
|
||||
const saveDeviceName = jest.fn().mockRejectedValueOnce("oups").mockResolvedValue({});
|
||||
const { getByTestId, queryByText, container } = render(getComponent({ saveDeviceName }));
|
||||
const { getByTestId, queryByText, findByText, container } = render(getComponent({ saveDeviceName }));
|
||||
|
||||
// start editing
|
||||
fireEvent.click(getByTestId("device-heading-rename-cta"));
|
||||
@@ -136,7 +136,7 @@ describe("<DeviceDetailHeading />", () => {
|
||||
await flushPromisesWithFakeTimers();
|
||||
|
||||
// error message displayed
|
||||
expect(queryByText("Failed to set session name")).toBeTruthy();
|
||||
await expect(findByText("Failed to set session name")).resolves.toBeTruthy();
|
||||
// spinner removed
|
||||
expect(container.getElementsByClassName("mx_Spinner").length).toBeFalsy();
|
||||
|
||||
|
||||
@@ -120,16 +120,15 @@ describe("<FilteredDeviceList />", () => {
|
||||
});
|
||||
|
||||
describe("filtering", () => {
|
||||
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) =>
|
||||
await act(async () => {
|
||||
const dropdown = container.querySelector('[aria-label="Filter devices"]');
|
||||
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) => {
|
||||
const dropdown = container.querySelector('[aria-label="Filter devices"]');
|
||||
|
||||
fireEvent.click(dropdown as Element);
|
||||
// tick to let dropdown render
|
||||
await flushPromises();
|
||||
fireEvent.click(dropdown as Element);
|
||||
// tick to let dropdown render
|
||||
await flushPromises();
|
||||
|
||||
fireEvent.click(container.querySelector(`#device-list-filter__${option}`) as Element);
|
||||
});
|
||||
fireEvent.click(container.querySelector(`#device-list-filter__${option}`) as Element);
|
||||
};
|
||||
|
||||
it("does not display filter description when filter is falsy", () => {
|
||||
const { container } = render(getComponent({ filter: undefined }));
|
||||
|
||||
@@ -104,6 +104,7 @@ describe("<EmailAddress/>", () => {
|
||||
"https://fake-url/",
|
||||
),
|
||||
);
|
||||
await expect(screen.findByText("Complete")).resolves.not.toHaveAttribute("aria-disabled", "true");
|
||||
fireEvent.click(screen.getByText("Complete"));
|
||||
|
||||
// Expect error dialog/modal to be shown. We have to wait for the UI to transition.
|
||||
@@ -120,6 +121,7 @@ describe("<EmailAddress/>", () => {
|
||||
it("Shows error dialog when share completion fails (UserFriendlyError)", async () => {
|
||||
const fakeErrorText = "Fake UserFriendlyError error in test" as TranslationKey;
|
||||
mockClient.bindThreePid.mockRejectedValue(new UserFriendlyError(fakeErrorText));
|
||||
await expect(screen.findByText("Complete")).resolves.not.toHaveAttribute("aria-disabled", "true");
|
||||
fireEvent.click(screen.getByText("Complete"));
|
||||
|
||||
// Expect error dialog/modal to be shown. We have to wait for the UI to transition.
|
||||
@@ -132,6 +134,7 @@ describe("<EmailAddress/>", () => {
|
||||
it("Shows error dialog when share completion fails (generic error)", async () => {
|
||||
const fakeErrorText = "Fake plain error in test";
|
||||
mockClient.bindThreePid.mockRejectedValue(new Error(fakeErrorText));
|
||||
await expect(screen.findByText("Complete")).resolves.not.toHaveAttribute("aria-disabled", "true");
|
||||
fireEvent.click(screen.getByText("Complete"));
|
||||
|
||||
// Expect error dialog/modal to be shown. We have to wait for the UI to transition.
|
||||
|
||||
@@ -15,7 +15,16 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { act, fireEvent, render, RenderResult, screen } from "@testing-library/react";
|
||||
import {
|
||||
act,
|
||||
fireEvent,
|
||||
render,
|
||||
RenderResult,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
within,
|
||||
} from "@testing-library/react";
|
||||
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { CryptoApi, DeviceVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api";
|
||||
@@ -146,7 +155,7 @@ describe("<SessionManagerTab />", () => {
|
||||
// open device detail
|
||||
const tile = getByTestId(`device-tile-${deviceId}`);
|
||||
const label = isOpen ? "Hide details" : "Show details";
|
||||
const toggle = tile.querySelector(`[aria-label="${label}"]`) as Element;
|
||||
const toggle = within(tile).getByLabelText(label);
|
||||
fireEvent.click(toggle);
|
||||
};
|
||||
|
||||
@@ -165,16 +174,14 @@ describe("<SessionManagerTab />", () => {
|
||||
return getByTestId(`device-tile-${deviceId}`);
|
||||
};
|
||||
|
||||
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) =>
|
||||
await act(async () => {
|
||||
const dropdown = container.querySelector('[aria-label="Filter devices"]');
|
||||
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) => {
|
||||
const dropdown = within(container).getByLabelText("Filter devices");
|
||||
|
||||
fireEvent.click(dropdown as Element);
|
||||
// tick to let dropdown render
|
||||
await flushPromises();
|
||||
fireEvent.click(dropdown);
|
||||
screen.getByRole("listbox");
|
||||
|
||||
fireEvent.click(container.querySelector(`#device-list-filter__${option}`) as Element);
|
||||
});
|
||||
fireEvent.click(screen.getByTestId(`filter-option-${option}`) as Element);
|
||||
};
|
||||
|
||||
const isDeviceSelected = (
|
||||
getByTestId: ReturnType<typeof render>["getByTestId"],
|
||||
@@ -920,37 +927,31 @@ describe("<SessionManagerTab />", () => {
|
||||
|
||||
it("deletes a device when interactive auth is not required", async () => {
|
||||
mockClient.deleteMultipleDevices.mockResolvedValue({});
|
||||
mockClient.getDevices
|
||||
.mockResolvedValueOnce({
|
||||
devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice],
|
||||
})
|
||||
// pretend it was really deleted on refresh
|
||||
.mockResolvedValueOnce({
|
||||
devices: [alicesDevice, alicesOlderMobileDevice],
|
||||
});
|
||||
|
||||
const { getByTestId } = render(getComponent());
|
||||
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
mockClient.getDevices.mockResolvedValue({
|
||||
devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice],
|
||||
});
|
||||
|
||||
toggleDeviceDetails(getByTestId, alicesMobileDevice.device_id);
|
||||
const { getByTestId, findByTestId } = render(getComponent());
|
||||
|
||||
const deviceDetails = getByTestId(`device-detail-${alicesMobileDevice.device_id}`);
|
||||
const signOutButton = deviceDetails.querySelector(
|
||||
'[data-testid="device-detail-sign-out-cta"]',
|
||||
) as Element;
|
||||
fireEvent.click(signOutButton);
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar"));
|
||||
await toggleDeviceDetails(getByTestId, alicesMobileDevice.device_id);
|
||||
|
||||
await confirmSignout(getByTestId);
|
||||
const signOutButton = await within(
|
||||
await findByTestId(`device-detail-${alicesMobileDevice.device_id}`),
|
||||
).findByTestId("device-detail-sign-out-cta");
|
||||
|
||||
// pretend it was really deleted on refresh
|
||||
mockClient.getDevices.mockResolvedValueOnce({
|
||||
devices: [alicesDevice, alicesOlderMobileDevice],
|
||||
});
|
||||
|
||||
// sign out button is disabled with spinner
|
||||
expect(
|
||||
(deviceDetails.querySelector('[data-testid="device-detail-sign-out-cta"]') as Element).getAttribute(
|
||||
"aria-disabled",
|
||||
),
|
||||
).toEqual("true");
|
||||
const prom = waitFor(() => expect(signOutButton).toHaveAttribute("aria-disabled", "true"));
|
||||
|
||||
fireEvent.click(signOutButton);
|
||||
await confirmSignout(getByTestId);
|
||||
await prom;
|
||||
|
||||
// delete called
|
||||
expect(mockClient.deleteMultipleDevices).toHaveBeenCalledWith(
|
||||
[alicesMobileDevice.device_id],
|
||||
@@ -1008,9 +1009,7 @@ describe("<SessionManagerTab />", () => {
|
||||
|
||||
const { getByTestId, getByLabelText } = render(getComponent());
|
||||
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
await act(flushPromises);
|
||||
|
||||
// reset mock count after initial load
|
||||
mockClient.getDevices.mockClear();
|
||||
@@ -1570,9 +1569,7 @@ describe("<SessionManagerTab />", () => {
|
||||
});
|
||||
const { getByTestId, container } = render(getComponent());
|
||||
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
await act(flushPromises);
|
||||
|
||||
// filter for inactive sessions
|
||||
await setFilter(container, DeviceSecurityVariation.Inactive);
|
||||
@@ -1765,6 +1762,7 @@ describe("<SessionManagerTab />", () => {
|
||||
await flushPromises();
|
||||
|
||||
fireEvent.click(getByText("Show QR code"));
|
||||
await waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar"));
|
||||
|
||||
await expect(findByTestId("login-with-qr")).resolves.toBeTruthy();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user