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:
parent
4e4c5c7768
commit
8285283cc3
35 changed files with 313 additions and 290 deletions
|
@ -1380,7 +1380,6 @@ describe("<MatrixChat />", () => {
|
||||||
|
|
||||||
it("while we are checking the sync store", async () => {
|
it("while we are checking the sync store", async () => {
|
||||||
const rendered = getComponent({});
|
const rendered = getComponent({});
|
||||||
await flushPromises();
|
|
||||||
expect(rendered.getByTestId("spinner")).toBeInTheDocument();
|
expect(rendered.getByTestId("spinner")).toBeInTheDocument();
|
||||||
|
|
||||||
// now a third session starts
|
// now a third session starts
|
||||||
|
|
|
@ -128,7 +128,7 @@ describe("<UserMenu>", () => {
|
||||||
|
|
||||||
const spy = jest.spyOn(defaultDispatcher, "dispatch");
|
const spy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||||
screen.getByRole("button", { name: /User menu/i }).click();
|
screen.getByRole("button", { name: /User menu/i }).click();
|
||||||
screen.getByRole("menuitem", { name: /Sign out/i }).click();
|
(await screen.findByRole("menuitem", { name: /Sign out/i })).click();
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(spy).toHaveBeenCalledWith({ action: "logout" });
|
expect(spy).toHaveBeenCalledWith({ action: "logout" });
|
||||||
});
|
});
|
||||||
|
@ -152,7 +152,7 @@ describe("<UserMenu>", () => {
|
||||||
|
|
||||||
const spy = jest.spyOn(defaultDispatcher, "dispatch");
|
const spy = jest.spyOn(defaultDispatcher, "dispatch");
|
||||||
screen.getByRole("button", { name: /User menu/i }).click();
|
screen.getByRole("button", { name: /User menu/i }).click();
|
||||||
screen.getByRole("menuitem", { name: /Sign out/i }).click();
|
(await screen.findByRole("menuitem", { name: /Sign out/i })).click();
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(spy).toHaveBeenCalledWith({ action: "logout" });
|
expect(spy).toHaveBeenCalledWith({ action: "logout" });
|
||||||
});
|
});
|
||||||
|
@ -178,7 +178,7 @@ describe("<UserMenu>", () => {
|
||||||
|
|
||||||
const spy = jest.spyOn(Modal, "createDialog");
|
const spy = jest.spyOn(Modal, "createDialog");
|
||||||
screen.getByRole("button", { name: /User menu/i }).click();
|
screen.getByRole("button", { name: /User menu/i }).click();
|
||||||
screen.getByRole("menuitem", { name: /Sign out/i }).click();
|
(await screen.findByRole("menuitem", { name: /Sign out/i })).click();
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(spy).toHaveBeenCalledWith(LogoutDialog);
|
expect(spy).toHaveBeenCalledWith(LogoutDialog);
|
||||||
|
|
|
@ -129,11 +129,11 @@ describe("AccessSecretStorageDialog", () => {
|
||||||
expect(screen.getByPlaceholderText("Security Phrase")).toHaveValue(securityKey);
|
expect(screen.getByPlaceholderText("Security Phrase")).toHaveValue(securityKey);
|
||||||
await submitDialog();
|
await submitDialog();
|
||||||
|
|
||||||
expect(
|
await expect(
|
||||||
screen.getByText(
|
screen.findByText(
|
||||||
"👎 Unable to access secret storage. Please verify that you entered the correct Security Phrase.",
|
"👎 Unable to access secret storage. Please verify that you entered the correct Security Phrase.",
|
||||||
),
|
),
|
||||||
).toBeInTheDocument();
|
).resolves.toBeInTheDocument();
|
||||||
|
|
||||||
expect(screen.getByPlaceholderText("Security Phrase")).toHaveFocus();
|
expect(screen.getByPlaceholderText("Security Phrase")).toHaveFocus();
|
||||||
});
|
});
|
||||||
|
|
|
@ -429,7 +429,7 @@ describe("InviteDialog", () => {
|
||||||
|
|
||||||
describe("when clicking »Start DM anyway«", () => {
|
describe("when clicking »Start DM anyway«", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await userEvent.click(screen.getByRole("button", { name: "Start DM anyway", exact: true }));
|
await userEvent.click(screen.getByRole("button", { name: "Start DM anyway" }));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should start the DM", () => {
|
it("should start the DM", () => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { render, RenderResult } from "@testing-library/react";
|
import { render, RenderResult, waitForElementToBeRemoved } from "@testing-library/react";
|
||||||
import { EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import { EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import type { MatrixClient } from "matrix-js-sdk/src/matrix";
|
import type { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
|
@ -39,6 +39,7 @@ describe("<MessageEditHistory />", () => {
|
||||||
|
|
||||||
async function renderComponent(): Promise<RenderResult> {
|
async function renderComponent(): Promise<RenderResult> {
|
||||||
const result = render(<MessageEditHistoryDialog mxEvent={event} onFinished={jest.fn()} />);
|
const result = render(<MessageEditHistoryDialog mxEvent={event} onFinished={jest.fn()} />);
|
||||||
|
await waitForElementToBeRemoved(() => result.queryByRole("progressbar"));
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { fireEvent, render, screen } from "@testing-library/react";
|
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||||
import {
|
import {
|
||||||
EventTimeline,
|
EventTimeline,
|
||||||
EventType,
|
EventType,
|
||||||
|
@ -129,7 +129,7 @@ describe("<RoomSettingsDialog />", () => {
|
||||||
expect(screen.getByTestId("settings-tab-ROOM_PEOPLE_TAB")).toBeInTheDocument();
|
expect(screen.getByTestId("settings-tab-ROOM_PEOPLE_TAB")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("re-renders on room join rule changes", () => {
|
it("re-renders on room join rule changes", async () => {
|
||||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||||
(setting) => setting === "feature_ask_to_join",
|
(setting) => setting === "feature_ask_to_join",
|
||||||
);
|
);
|
||||||
|
@ -142,7 +142,9 @@ describe("<RoomSettingsDialog />", () => {
|
||||||
room.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
room.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
expect(screen.queryByTestId("settings-tab-ROOM_PEOPLE_TAB")).not.toBeInTheDocument();
|
await waitFor(() =>
|
||||||
|
expect(screen.queryByTestId("settings-tab-ROOM_PEOPLE_TAB")).not.toBeInTheDocument(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -57,14 +57,9 @@ jest.mock("../../../../src/settings/SettingsStore", () => ({
|
||||||
settingIsOveriddenAtConfigLevel: jest.fn(),
|
settingIsOveriddenAtConfigLevel: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock("../../../../src/SdkConfig", () => ({
|
|
||||||
get: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe("<UserSettingsDialog />", () => {
|
describe("<UserSettingsDialog />", () => {
|
||||||
const userId = "@alice:server.org";
|
const userId = "@alice:server.org";
|
||||||
const mockSettingsStore = mocked(SettingsStore);
|
const mockSettingsStore = mocked(SettingsStore);
|
||||||
const mockSdkConfig = mocked(SdkConfig);
|
|
||||||
let mockClient!: MockedObject<MatrixClient>;
|
let mockClient!: MockedObject<MatrixClient>;
|
||||||
|
|
||||||
let sdkContext: SdkContextClass;
|
let sdkContext: SdkContextClass;
|
||||||
|
@ -89,7 +84,8 @@ describe("<UserSettingsDialog />", () => {
|
||||||
mockSettingsStore.getValue.mockReturnValue(false);
|
mockSettingsStore.getValue.mockReturnValue(false);
|
||||||
mockSettingsStore.getValueAt.mockReturnValue(false);
|
mockSettingsStore.getValueAt.mockReturnValue(false);
|
||||||
mockSettingsStore.getFeatureSettingNames.mockReturnValue([]);
|
mockSettingsStore.getFeatureSettingNames.mockReturnValue([]);
|
||||||
mockSdkConfig.get.mockReturnValue({ brand: "Test" });
|
SdkConfig.reset();
|
||||||
|
SdkConfig.put({ brand: "Test" });
|
||||||
});
|
});
|
||||||
|
|
||||||
const getActiveTabLabel = (container: Element) =>
|
const getActiveTabLabel = (container: Element) =>
|
||||||
|
@ -115,6 +111,9 @@ describe("<UserSettingsDialog />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders tabs correctly", () => {
|
it("renders tabs correctly", () => {
|
||||||
|
SdkConfig.add({
|
||||||
|
show_labs_settings: true,
|
||||||
|
});
|
||||||
const { container } = render(getComponent());
|
const { container } = render(getComponent());
|
||||||
expect(container.querySelectorAll(".mx_TabbedView_tabLabel")).toMatchSnapshot();
|
expect(container.querySelectorAll(".mx_TabbedView_tabLabel")).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -181,7 +180,7 @@ describe("<UserSettingsDialog />", () => {
|
||||||
expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent("Settings: Voice & Video");
|
expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent("Settings: Voice & Video");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders with secutity tab selected", () => {
|
it("renders with security tab selected", () => {
|
||||||
const { container } = render(getComponent({ initialTabId: UserTab.Security }));
|
const { container } = render(getComponent({ initialTabId: UserTab.Security }));
|
||||||
|
|
||||||
expect(getActiveTabLabel(container)).toEqual("Security & Privacy");
|
expect(getActiveTabLabel(container)).toEqual("Security & Privacy");
|
||||||
|
@ -189,18 +188,8 @@ describe("<UserSettingsDialog />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders with labs tab selected", () => {
|
it("renders with labs tab selected", () => {
|
||||||
// @ts-ignore I give up trying to get the types right here
|
SdkConfig.add({
|
||||||
// why do we have functions that return different things depending on what they're passed?
|
show_labs_settings: true,
|
||||||
mockSdkConfig.get.mockImplementation((x) => {
|
|
||||||
const mockConfig = { show_labs_settings: true, brand: "Test" };
|
|
||||||
switch (x) {
|
|
||||||
case "show_labs_settings":
|
|
||||||
case "brand":
|
|
||||||
// @ts-ignore
|
|
||||||
return mockConfig[x];
|
|
||||||
default:
|
|
||||||
return mockConfig;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
const { container } = render(getComponent({ initialTabId: UserTab.Labs }));
|
const { container } = render(getComponent({ initialTabId: UserTab.Labs }));
|
||||||
|
|
||||||
|
@ -223,8 +212,9 @@ describe("<UserSettingsDialog />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders labs tab when show_labs_settings is enabled in config", () => {
|
it("renders labs tab when show_labs_settings is enabled in config", () => {
|
||||||
// @ts-ignore simplified test stub
|
SdkConfig.add({
|
||||||
mockSdkConfig.get.mockImplementation((configName) => configName === "show_labs_settings");
|
show_labs_settings: true,
|
||||||
|
});
|
||||||
const { getByTestId } = render(getComponent());
|
const { getByTestId } = render(getComponent());
|
||||||
expect(getByTestId(`settings-tab-${UserTab.Labs}`)).toBeTruthy();
|
expect(getByTestId(`settings-tab-${UserTab.Labs}`)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
@ -238,7 +228,7 @@ describe("<UserSettingsDialog />", () => {
|
||||||
expect(getByTestId(`settings-tab-${UserTab.Labs}`)).toBeTruthy();
|
expect(getByTestId(`settings-tab-${UserTab.Labs}`)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("watches settings", () => {
|
it("watches settings", async () => {
|
||||||
const watchSettingCallbacks: Record<string, CallbackFn> = {};
|
const watchSettingCallbacks: Record<string, CallbackFn> = {};
|
||||||
|
|
||||||
mockSettingsStore.watchSetting.mockImplementation((settingName, roomId, callback) => {
|
mockSettingsStore.watchSetting.mockImplementation((settingName, roomId, callback) => {
|
||||||
|
@ -247,7 +237,7 @@ describe("<UserSettingsDialog />", () => {
|
||||||
});
|
});
|
||||||
mockSettingsStore.getValue.mockReturnValue(false);
|
mockSettingsStore.getValue.mockReturnValue(false);
|
||||||
|
|
||||||
const { queryByTestId, unmount } = render(getComponent());
|
const { queryByTestId, findByTestId, unmount } = render(getComponent());
|
||||||
expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeFalsy();
|
expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeFalsy();
|
||||||
|
|
||||||
expect(mockSettingsStore.watchSetting).toHaveBeenCalledWith("feature_mjolnir", null, expect.anything());
|
expect(mockSettingsStore.watchSetting).toHaveBeenCalledWith("feature_mjolnir", null, expect.anything());
|
||||||
|
@ -257,7 +247,7 @@ describe("<UserSettingsDialog />", () => {
|
||||||
watchSettingCallbacks["feature_mjolnir"]("feature_mjolnir", "", SettingLevel.ACCOUNT, true, true);
|
watchSettingCallbacks["feature_mjolnir"]("feature_mjolnir", "", SettingLevel.ACCOUNT, true, true);
|
||||||
|
|
||||||
// tab is rendered now
|
// tab is rendered now
|
||||||
expect(queryByTestId(`settings-tab-${UserTab.Mjolnir}`)).toBeTruthy();
|
await expect(findByTestId(`settings-tab-${UserTab.Mjolnir}`)).resolves.toBeTruthy();
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { act, fireEvent, render, screen } from "@testing-library/react";
|
import { fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
|
||||||
import Field from "../../../../src/components/views/elements/Field";
|
import Field from "../../../../src/components/views/elements/Field";
|
||||||
|
|
||||||
|
@ -63,12 +63,10 @@ describe("Field", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// When invalid
|
// When invalid
|
||||||
await act(async () => {
|
|
||||||
fireEvent.focus(screen.getByRole("textbox"));
|
fireEvent.focus(screen.getByRole("textbox"));
|
||||||
});
|
|
||||||
|
|
||||||
// Expect 'alert' role
|
// Expect 'alert' role
|
||||||
expect(screen.queryByRole("alert")).toBeInTheDocument();
|
await expect(screen.findByRole("alert")).resolves.toBeInTheDocument();
|
||||||
|
|
||||||
// Close the feedback is Escape is pressed
|
// Close the feedback is Escape is pressed
|
||||||
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
|
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
|
||||||
|
@ -85,12 +83,10 @@ describe("Field", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// When valid
|
// When valid
|
||||||
await act(async () => {
|
|
||||||
fireEvent.focus(screen.getByRole("textbox"));
|
fireEvent.focus(screen.getByRole("textbox"));
|
||||||
});
|
|
||||||
|
|
||||||
// Expect 'status' role
|
// Expect 'status' role
|
||||||
expect(screen.queryByRole("status")).toBeInTheDocument();
|
await expect(screen.findByRole("status")).resolves.toBeInTheDocument();
|
||||||
|
|
||||||
// Close the feedback is Escape is pressed
|
// Close the feedback is Escape is pressed
|
||||||
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
|
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
|
||||||
|
@ -108,12 +104,10 @@ describe("Field", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// When valid or invalid and 'tooltipContent' set
|
// When valid or invalid and 'tooltipContent' set
|
||||||
await act(async () => {
|
|
||||||
fireEvent.focus(screen.getByRole("textbox"));
|
fireEvent.focus(screen.getByRole("textbox"));
|
||||||
});
|
|
||||||
|
|
||||||
// Expect 'tooltip' role
|
// Expect 'tooltip' role
|
||||||
expect(screen.queryByRole("tooltip")).toBeInTheDocument();
|
await expect(screen.findByRole("tooltip")).resolves.toBeInTheDocument();
|
||||||
|
|
||||||
// Close the feedback is Escape is pressed
|
// Close the feedback is Escape is pressed
|
||||||
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
|
fireEvent.keyDown(screen.getByRole("textbox"), { key: "Escape" });
|
||||||
|
|
|
@ -32,10 +32,10 @@ describe("<SearchWarning />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders with a logo by default", () => {
|
it("renders with a logo by default", () => {
|
||||||
const { asFragment, queryByRole } = render(
|
const { asFragment, getByRole } = render(
|
||||||
<SearchWarning isRoomEncrypted={true} kind={WarningKind.Search} />,
|
<SearchWarning isRoomEncrypted={true} kind={WarningKind.Search} />,
|
||||||
);
|
);
|
||||||
expect(queryByRole("img")).toBeInTheDocument();
|
expect(getByRole("img")).toHaveAttribute("src", "https://logo");
|
||||||
expect(asFragment()).toMatchSnapshot();
|
expect(asFragment()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,10 @@ import PlatformPeg from "../../../../src/PlatformPeg";
|
||||||
|
|
||||||
describe("<SpellCheckLanguagesDropdown />", () => {
|
describe("<SpellCheckLanguagesDropdown />", () => {
|
||||||
it("renders as expected", async () => {
|
it("renders as expected", async () => {
|
||||||
const platform: any = { getAvailableSpellCheckLanguages: jest.fn().mockResolvedValue(["en", "de", "qq"]) };
|
const platform: any = {
|
||||||
|
getAvailableSpellCheckLanguages: jest.fn().mockResolvedValue(["en", "de", "qq"]),
|
||||||
|
supportsSetting: jest.fn(),
|
||||||
|
};
|
||||||
PlatformPeg.set(platform);
|
PlatformPeg.set(platform);
|
||||||
|
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
|
|
|
@ -211,7 +211,7 @@ describe("<MImageBody/>", () => {
|
||||||
it("should generate a thumbnail if one isn't included for animated media", async () => {
|
it("should generate a thumbnail if one isn't included for animated media", async () => {
|
||||||
Object.defineProperty(global.Image.prototype, "src", {
|
Object.defineProperty(global.Image.prototype, "src", {
|
||||||
set(src) {
|
set(src) {
|
||||||
window.setTimeout(() => this.onload());
|
window.setTimeout(() => this.onload?.());
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Object.defineProperty(global.Image.prototype, "height", {
|
Object.defineProperty(global.Image.prototype, "height", {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { fireEvent, render, waitFor } from "@testing-library/react";
|
||||||
import { LocationAssetType, ClientEvent, RoomMember, SyncState } from "matrix-js-sdk/src/matrix";
|
import { LocationAssetType, ClientEvent, RoomMember, SyncState } from "matrix-js-sdk/src/matrix";
|
||||||
import * as maplibregl from "maplibre-gl";
|
import * as maplibregl from "maplibre-gl";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { sleep } from "matrix-js-sdk/src/utils";
|
||||||
|
|
||||||
import MLocationBody from "../../../../src/components/views/messages/MLocationBody";
|
import MLocationBody from "../../../../src/components/views/messages/MLocationBody";
|
||||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||||
|
@ -64,9 +65,11 @@ describe("MLocationBody", () => {
|
||||||
});
|
});
|
||||||
const component = getComponent();
|
const component = getComponent();
|
||||||
|
|
||||||
|
sleep(10).then(() => {
|
||||||
// simulate error initialising map in maplibregl
|
// simulate error initialising map in maplibregl
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
mockMap.emit("error", { status: 404 });
|
mockMap.emit("error", { status: 404 });
|
||||||
|
});
|
||||||
|
|
||||||
return component;
|
return component;
|
||||||
};
|
};
|
||||||
|
@ -100,9 +103,10 @@ describe("MLocationBody", () => {
|
||||||
expect(component.container.querySelector(".mx_EventTile_body")).toMatchSnapshot();
|
expect(component.container.querySelector(".mx_EventTile_body")).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("displays correct fallback content when map_style_url is misconfigured", () => {
|
it("displays correct fallback content when map_style_url is misconfigured", async () => {
|
||||||
const component = getMapErrorComponent();
|
const component = getMapErrorComponent();
|
||||||
expect(component.container.querySelector(".mx_EventTile_body")).toMatchSnapshot();
|
await waitFor(() => expect(component.container.querySelector(".mx_EventTile_body")).toBeTruthy());
|
||||||
|
await waitFor(() => expect(component.container.querySelector(".mx_EventTile_body")).toMatchSnapshot());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should clear the error on reconnect", () => {
|
it("should clear the error on reconnect", () => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { render } from "@testing-library/react";
|
import { render, waitFor } from "@testing-library/react";
|
||||||
import { EventTimeline, MatrixEvent, Room, M_TEXT } from "matrix-js-sdk/src/matrix";
|
import { EventTimeline, MatrixEvent, Room, M_TEXT } from "matrix-js-sdk/src/matrix";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -129,13 +129,12 @@ describe("<MPollEndBody />", () => {
|
||||||
describe("when poll start event does not exist in current timeline", () => {
|
describe("when poll start event does not exist in current timeline", () => {
|
||||||
it("fetches the related poll start event and displays a poll tile", async () => {
|
it("fetches the related poll start event and displays a poll tile", async () => {
|
||||||
await setupRoomWithEventsTimeline(pollEndEvent);
|
await setupRoomWithEventsTimeline(pollEndEvent);
|
||||||
const { container, getByTestId } = getComponent();
|
const { container, getByTestId, getByRole } = getComponent();
|
||||||
|
|
||||||
// while fetching event, only icon is shown
|
// while fetching event, only icon is shown
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
|
|
||||||
// flush the fetch event promise
|
await waitFor(() => expect(getByRole("progressbar")).toBeInTheDocument());
|
||||||
await flushPromises();
|
|
||||||
|
|
||||||
expect(mockClient.fetchRoomEvent).toHaveBeenCalledWith(roomId, pollStartEvent.getId());
|
expect(mockClient.fetchRoomEvent).toHaveBeenCalledWith(roomId, pollStartEvent.getId());
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import {
|
||||||
getMockClientWithEventEmitter,
|
getMockClientWithEventEmitter,
|
||||||
makePollEndEvent,
|
makePollEndEvent,
|
||||||
makePollStartEvent,
|
makePollStartEvent,
|
||||||
|
mockClientMethodsRooms,
|
||||||
mockClientMethodsUser,
|
mockClientMethodsUser,
|
||||||
mockIntlDateTimeFormat,
|
mockIntlDateTimeFormat,
|
||||||
setupRoomWithPollEvents,
|
setupRoomWithPollEvents,
|
||||||
|
@ -41,7 +42,7 @@ describe("<PollHistory />", () => {
|
||||||
const roomId = "!room:domain.org";
|
const roomId = "!room:domain.org";
|
||||||
const mockClient = getMockClientWithEventEmitter({
|
const mockClient = getMockClientWithEventEmitter({
|
||||||
...mockClientMethodsUser(userId),
|
...mockClientMethodsUser(userId),
|
||||||
getRoom: jest.fn(),
|
...mockClientMethodsRooms([]),
|
||||||
relations: jest.fn(),
|
relations: jest.fn(),
|
||||||
decryptEventIfNeeded: jest.fn(),
|
decryptEventIfNeeded: jest.fn(),
|
||||||
getOrCreateFilter: jest.fn(),
|
getOrCreateFilter: jest.fn(),
|
||||||
|
@ -117,7 +118,7 @@ describe("<PollHistory />", () => {
|
||||||
expect(getByText("Loading polls")).toBeInTheDocument();
|
expect(getByText("Loading polls")).toBeInTheDocument();
|
||||||
|
|
||||||
// flush filter creation request
|
// flush filter creation request
|
||||||
await flushPromises();
|
await act(flushPromises);
|
||||||
|
|
||||||
expect(liveTimeline.getPaginationToken).toHaveBeenCalledWith(EventTimeline.BACKWARDS);
|
expect(liveTimeline.getPaginationToken).toHaveBeenCalledWith(EventTimeline.BACKWARDS);
|
||||||
expect(mockClient.paginateEventTimeline).toHaveBeenCalledWith(liveTimeline, { backwards: true });
|
expect(mockClient.paginateEventTimeline).toHaveBeenCalledWith(liveTimeline, { backwards: true });
|
||||||
|
@ -147,7 +148,7 @@ describe("<PollHistory />", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// flush filter creation request
|
// flush filter creation request
|
||||||
await flushPromises();
|
await act(flushPromises);
|
||||||
// once per page
|
// once per page
|
||||||
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(3);
|
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
|
@ -182,7 +183,7 @@ describe("<PollHistory />", () => {
|
||||||
|
|
||||||
it("renders a no polls message when there are no active polls in the room", async () => {
|
it("renders a no polls message when there are no active polls in the room", async () => {
|
||||||
const { getByText } = getComponent();
|
const { getByText } = getComponent();
|
||||||
await flushPromises();
|
await act(flushPromises);
|
||||||
|
|
||||||
expect(getByText("There are no active polls in this room")).toBeTruthy();
|
expect(getByText("There are no active polls in this room")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -163,7 +163,7 @@ describe("<PollListItemEnded />", () => {
|
||||||
await setupRoomWithPollEvents([pollStartEvent], responses, [pollEndEvent], mockClient, room);
|
await setupRoomWithPollEvents([pollStartEvent], responses, [pollEndEvent], mockClient, room);
|
||||||
const poll = room.polls.get(pollId)!;
|
const poll = room.polls.get(pollId)!;
|
||||||
|
|
||||||
const { getByText, queryByText } = getComponent({ event: pollStartEvent, poll });
|
const { getByText, queryByText, findByText } = getComponent({ event: pollStartEvent, poll });
|
||||||
// fetch relations
|
// fetch relations
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ describe("<PollListItemEnded />", () => {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// updated with more responses
|
// updated with more responses
|
||||||
expect(getByText("Final result based on 3 votes")).toBeInTheDocument();
|
await expect(findByText("Final result based on 3 votes")).resolves.toBeInTheDocument();
|
||||||
expect(getByText("Nissan Silvia S15")).toBeInTheDocument();
|
expect(getByText("Nissan Silvia S15")).toBeInTheDocument();
|
||||||
expect(queryByText("Mitsubishi Lancer Evolution IX")).not.toBeInTheDocument();
|
expect(queryByText("Mitsubishi Lancer Evolution IX")).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { render } from "@testing-library/react";
|
import { render, waitFor } from "@testing-library/react";
|
||||||
import {
|
import {
|
||||||
MatrixEvent,
|
MatrixEvent,
|
||||||
MsgType,
|
MsgType,
|
||||||
|
@ -79,21 +79,23 @@ describe("LegacyRoomHeaderButtons-test.tsx", function () {
|
||||||
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
|
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("thread notification does change the thread button", () => {
|
it("thread notification does change the thread button", async () => {
|
||||||
const { container } = getComponent(room);
|
const { container } = getComponent(room);
|
||||||
expect(getThreadButton(container)!.className.includes("mx_LegacyRoomHeader_button--unread")).toBeFalsy();
|
expect(getThreadButton(container)!.className.includes("mx_LegacyRoomHeader_button--unread")).toBeFalsy();
|
||||||
|
|
||||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Total, 1);
|
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Total, 1);
|
||||||
|
await waitFor(() => {
|
||||||
expect(getThreadButton(container)!.className.includes("mx_LegacyRoomHeader_button--unread")).toBeTruthy();
|
expect(getThreadButton(container)!.className.includes("mx_LegacyRoomHeader_button--unread")).toBeTruthy();
|
||||||
expect(isIndicatorOfType(container, "notification")).toBe(true);
|
expect(isIndicatorOfType(container, "notification")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 1);
|
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 1);
|
||||||
expect(isIndicatorOfType(container, "highlight")).toBe(true);
|
await waitFor(() => expect(isIndicatorOfType(container, "highlight")).toBe(true));
|
||||||
|
|
||||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Total, 0);
|
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Total, 0);
|
||||||
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 0);
|
room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 0);
|
||||||
|
|
||||||
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
|
await waitFor(() => expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("thread activity does change the thread button", async () => {
|
it("thread activity does change the thread button", async () => {
|
||||||
|
@ -122,7 +124,7 @@ describe("LegacyRoomHeaderButtons-test.tsx", function () {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
room.addReceipt(receipt);
|
room.addReceipt(receipt);
|
||||||
expect(isIndicatorOfType(container, "activity")).toBe(true);
|
await waitFor(() => expect(isIndicatorOfType(container, "activity")).toBe(true));
|
||||||
|
|
||||||
// Sending the last event should clear the notification.
|
// Sending the last event should clear the notification.
|
||||||
let event = mkEvent({
|
let event = mkEvent({
|
||||||
|
@ -140,7 +142,7 @@ describe("LegacyRoomHeaderButtons-test.tsx", function () {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
room.addLiveEvents([event]);
|
room.addLiveEvents([event]);
|
||||||
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
|
await waitFor(() => expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull());
|
||||||
|
|
||||||
// Mark it as unread again.
|
// Mark it as unread again.
|
||||||
event = mkEvent({
|
event = mkEvent({
|
||||||
|
@ -158,7 +160,7 @@ describe("LegacyRoomHeaderButtons-test.tsx", function () {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
room.addLiveEvents([event]);
|
room.addLiveEvents([event]);
|
||||||
expect(isIndicatorOfType(container, "activity")).toBe(true);
|
await waitFor(() => expect(isIndicatorOfType(container, "activity")).toBe(true));
|
||||||
|
|
||||||
// Sending a read receipt on an earlier event shouldn't do anything.
|
// Sending a read receipt on an earlier event shouldn't do anything.
|
||||||
receipt = new MatrixEvent({
|
receipt = new MatrixEvent({
|
||||||
|
@ -173,7 +175,7 @@ describe("LegacyRoomHeaderButtons-test.tsx", function () {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
room.addReceipt(receipt);
|
room.addReceipt(receipt);
|
||||||
expect(isIndicatorOfType(container, "activity")).toBe(true);
|
await waitFor(() => expect(isIndicatorOfType(container, "activity")).toBe(true));
|
||||||
|
|
||||||
// Sending a receipt on the latest event should clear the notification.
|
// Sending a receipt on the latest event should clear the notification.
|
||||||
receipt = new MatrixEvent({
|
receipt = new MatrixEvent({
|
||||||
|
@ -188,6 +190,6 @@ describe("LegacyRoomHeaderButtons-test.tsx", function () {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
room.addReceipt(receipt);
|
room.addReceipt(receipt);
|
||||||
expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull();
|
await waitFor(() => expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -87,9 +87,7 @@ describe("<PinnedMessagesCard />", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const mountPins = async (room: Room): Promise<RenderResult> => {
|
const mountPins = async (room: Room): Promise<RenderResult> => {
|
||||||
let pins!: RenderResult;
|
const pins = render(
|
||||||
await act(async () => {
|
|
||||||
pins = render(
|
|
||||||
<MatrixClientContext.Provider value={cli}>
|
<MatrixClientContext.Provider value={cli}>
|
||||||
<PinnedMessagesCard
|
<PinnedMessagesCard
|
||||||
room={room}
|
room={room}
|
||||||
|
@ -99,8 +97,7 @@ describe("<PinnedMessagesCard />", () => {
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
// Wait a tick for state updates
|
// Wait a tick for state updates
|
||||||
await sleep(0);
|
await act(() => sleep(0));
|
||||||
});
|
|
||||||
|
|
||||||
return pins;
|
return pins;
|
||||||
};
|
};
|
||||||
|
@ -313,7 +310,6 @@ describe("<PinnedMessagesCard />", () => {
|
||||||
it("should show spinner whilst loading", async () => {
|
it("should show spinner whilst loading", async () => {
|
||||||
const room = mkRoom([], [pin1]);
|
const room = mkRoom([], [pin1]);
|
||||||
mountPins(room);
|
mountPins(room);
|
||||||
const spinner = await screen.findByTestId("spinner");
|
await waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar"));
|
||||||
await waitForElementToBeRemoved(spinner);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -287,10 +287,10 @@ describe("<UserInfo />", () => {
|
||||||
expect(spy).not.toHaveBeenCalled();
|
expect(spy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders close button correctly when encryption panel with a pending verification request", () => {
|
it("renders close button correctly when encryption panel with a pending verification request", async () => {
|
||||||
renderComponent({ phase: RightPanelPhases.EncryptionPanel, verificationRequest });
|
renderComponent({ phase: RightPanelPhases.EncryptionPanel, verificationRequest });
|
||||||
screen.getByTestId("base-card-close-button").focus();
|
screen.getByTestId("base-card-close-button").focus();
|
||||||
expect(screen.getByRole("tooltip")).toHaveTextContent("Cancel");
|
await expect(screen.findByRole("tooltip", { name: "Cancel" })).resolves.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,15 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { act, fireEvent, render, RenderResult, screen } from "@testing-library/react";
|
import {
|
||||||
|
act,
|
||||||
|
fireEvent,
|
||||||
|
render,
|
||||||
|
RenderResult,
|
||||||
|
screen,
|
||||||
|
waitFor,
|
||||||
|
waitForElementToBeRemoved,
|
||||||
|
} from "@testing-library/react";
|
||||||
import { Room, MatrixClient, RoomState, RoomMember, User, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import { Room, MatrixClient, RoomState, RoomMember, User, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||||
import { mocked, MockedObject } from "jest-mock";
|
import { mocked, MockedObject } from "jest-mock";
|
||||||
|
@ -30,6 +38,7 @@ import {
|
||||||
filterConsole,
|
filterConsole,
|
||||||
flushPromises,
|
flushPromises,
|
||||||
getMockClientWithEventEmitter,
|
getMockClientWithEventEmitter,
|
||||||
|
mockClientMethodsRooms,
|
||||||
mockClientMethodsUser,
|
mockClientMethodsUser,
|
||||||
} from "../../../test-utils";
|
} from "../../../test-utils";
|
||||||
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
|
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
|
||||||
|
@ -358,6 +367,7 @@ describe("MemberList", () => {
|
||||||
mocked(shouldShowComponent).mockReturnValue(true);
|
mocked(shouldShowComponent).mockReturnValue(true);
|
||||||
client = getMockClientWithEventEmitter({
|
client = getMockClientWithEventEmitter({
|
||||||
...mockClientMethodsUser(),
|
...mockClientMethodsUser(),
|
||||||
|
...mockClientMethodsRooms(),
|
||||||
getRoom: jest.fn(),
|
getRoom: jest.fn(),
|
||||||
hasLazyLoadMembersEnabled: jest.fn(),
|
hasLazyLoadMembersEnabled: jest.fn(),
|
||||||
});
|
});
|
||||||
|
@ -372,7 +382,7 @@ describe("MemberList", () => {
|
||||||
const renderComponent = () => {
|
const renderComponent = () => {
|
||||||
const context = new TestSdkContext();
|
const context = new TestSdkContext();
|
||||||
context.client = client;
|
context.client = client;
|
||||||
render(
|
return render(
|
||||||
<SDKContext.Provider value={context}>
|
<SDKContext.Provider value={context}>
|
||||||
<MemberList
|
<MemberList
|
||||||
searchQuery=""
|
searchQuery=""
|
||||||
|
@ -407,7 +417,10 @@ describe("MemberList", () => {
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
// button rendered but disabled
|
// button rendered but disabled
|
||||||
expect(screen.getByText("Invite to this room")).toHaveAttribute("aria-disabled", "true");
|
expect(screen.getByRole("button", { name: "Invite to this room" })).toHaveAttribute(
|
||||||
|
"aria-disabled",
|
||||||
|
"true",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders enabled invite button when current user is a member and has rights to invite", async () => {
|
it("renders enabled invite button when current user is a member and has rights to invite", async () => {
|
||||||
|
@ -425,10 +438,17 @@ describe("MemberList", () => {
|
||||||
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
||||||
jest.spyOn(room, "canInvite").mockReturnValue(true);
|
jest.spyOn(room, "canInvite").mockReturnValue(true);
|
||||||
|
|
||||||
renderComponent();
|
const { getByRole } = renderComponent();
|
||||||
await flushPromises();
|
await waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar"));
|
||||||
|
|
||||||
fireEvent.click(screen.getByText("Invite to this room"));
|
await waitFor(() =>
|
||||||
|
expect(getByRole("button", { name: "Invite to this room" })).not.toHaveAttribute(
|
||||||
|
"aria-disabled",
|
||||||
|
"true",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(getByRole("button", { name: "Invite to this room" }));
|
||||||
|
|
||||||
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({
|
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({
|
||||||
action: "view_invite",
|
action: "view_invite",
|
||||||
|
|
|
@ -345,6 +345,7 @@ describe("RoomHeader", () => {
|
||||||
jest.spyOn(CallStore.instance, "getCall").mockReturnValue({
|
jest.spyOn(CallStore.instance, "getCall").mockReturnValue({
|
||||||
widget,
|
widget,
|
||||||
on: () => {},
|
on: () => {},
|
||||||
|
off: () => {},
|
||||||
} as unknown as Call);
|
} as unknown as Call);
|
||||||
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);
|
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);
|
||||||
const { container } = render(<RoomHeader room={room} />, getWrapper());
|
const { container } = render(<RoomHeader room={room} />, getWrapper());
|
||||||
|
@ -363,6 +364,7 @@ describe("RoomHeader", () => {
|
||||||
jest.spyOn(CallStore.instance, "getCall").mockReturnValue({
|
jest.spyOn(CallStore.instance, "getCall").mockReturnValue({
|
||||||
widget,
|
widget,
|
||||||
on: () => {},
|
on: () => {},
|
||||||
|
off: () => {},
|
||||||
} as unknown as Call);
|
} as unknown as Call);
|
||||||
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);
|
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { MockedObject } from "jest-mock";
|
import { MockedObject } from "jest-mock";
|
||||||
import { Room } from "matrix-js-sdk/src/matrix";
|
import { Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { fireEvent, render, screen } from "@testing-library/react";
|
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||||
|
|
||||||
import { VideoRoomChatButton } from "../../../../../src/components/views/rooms/RoomHeader/VideoRoomChatButton";
|
import { VideoRoomChatButton } from "../../../../../src/components/views/rooms/RoomHeader/VideoRoomChatButton";
|
||||||
import { SDKContext, SdkContextClass } from "../../../../../src/contexts/SDKContext";
|
import { SDKContext, SdkContextClass } from "../../../../../src/contexts/SDKContext";
|
||||||
|
@ -94,7 +94,7 @@ describe("<VideoRoomChatButton />", () => {
|
||||||
expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeTruthy();
|
expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("adds unread marker when room notification state changes to unread", () => {
|
it("adds unread marker when room notification state changes to unread", async () => {
|
||||||
const room = makeRoom();
|
const room = makeRoom();
|
||||||
// start in read state
|
// start in read state
|
||||||
const notificationState = mockRoomNotificationState(room, NotificationLevel.None);
|
const notificationState = mockRoomNotificationState(room, NotificationLevel.None);
|
||||||
|
@ -108,10 +108,10 @@ describe("<VideoRoomChatButton />", () => {
|
||||||
notificationState.emit(NotificationStateEvents.Update);
|
notificationState.emit(NotificationStateEvents.Update);
|
||||||
|
|
||||||
// unread marker
|
// unread marker
|
||||||
expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeTruthy();
|
await waitFor(() => expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeTruthy());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("clears unread marker when room notification state changes to read", () => {
|
it("clears unread marker when room notification state changes to read", async () => {
|
||||||
const room = makeRoom();
|
const room = makeRoom();
|
||||||
// start in unread state
|
// start in unread state
|
||||||
const notificationState = mockRoomNotificationState(room, NotificationLevel.Highlight);
|
const notificationState = mockRoomNotificationState(room, NotificationLevel.Highlight);
|
||||||
|
@ -125,6 +125,6 @@ describe("<VideoRoomChatButton />", () => {
|
||||||
notificationState.emit(NotificationStateEvents.Update);
|
notificationState.emit(NotificationStateEvents.Update);
|
||||||
|
|
||||||
// unread marker cleared
|
// unread marker cleared
|
||||||
expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeFalsy();
|
await waitFor(() => expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeFalsy());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,10 +15,9 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ComponentProps } from "react";
|
import React, { ComponentProps } from "react";
|
||||||
import { render, fireEvent, RenderResult, waitFor } from "@testing-library/react";
|
import { render, fireEvent, RenderResult, waitFor, waitForElementToBeRemoved } from "@testing-library/react";
|
||||||
import { Room, RoomMember, MatrixError, IContent } from "matrix-js-sdk/src/matrix";
|
import { Room, RoomMember, MatrixError, IContent } from "matrix-js-sdk/src/matrix";
|
||||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||||
import { sleep } from "matrix-js-sdk/src/utils";
|
|
||||||
|
|
||||||
import { withClientContextRenderOptions, stubClient } from "../../../test-utils";
|
import { withClientContextRenderOptions, stubClient } from "../../../test-utils";
|
||||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
|
@ -374,8 +373,7 @@ describe("<RoomPreviewBar />", () => {
|
||||||
const onJoinClick = jest.fn();
|
const onJoinClick = jest.fn();
|
||||||
const onRejectClick = jest.fn();
|
const onRejectClick = jest.fn();
|
||||||
const component = getComponent({ ...props, onJoinClick, onRejectClick });
|
const component = getComponent({ ...props, onJoinClick, onRejectClick });
|
||||||
await sleep(0);
|
await waitFor(() => expect(getPrimaryActionButton(component)).toBeTruthy());
|
||||||
expect(getPrimaryActionButton(component)).toBeTruthy();
|
|
||||||
if (expectSecondaryButton) expect(getSecondaryActionButton(component)).toBeFalsy();
|
if (expectSecondaryButton) expect(getSecondaryActionButton(component)).toBeFalsy();
|
||||||
fireEvent.click(getPrimaryActionButton(component)!);
|
fireEvent.click(getPrimaryActionButton(component)!);
|
||||||
expect(onJoinClick).toHaveBeenCalled();
|
expect(onJoinClick).toHaveBeenCalled();
|
||||||
|
@ -388,7 +386,7 @@ describe("<RoomPreviewBar />", () => {
|
||||||
|
|
||||||
it("renders error message", async () => {
|
it("renders error message", async () => {
|
||||||
const component = getComponent({ inviterName, invitedEmail });
|
const component = getComponent({ inviterName, invitedEmail });
|
||||||
await sleep(0);
|
await waitForElementToBeRemoved(() => component.queryByRole("progressbar"));
|
||||||
|
|
||||||
expect(getMessage(component)).toMatchSnapshot();
|
expect(getMessage(component)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -405,7 +403,7 @@ describe("<RoomPreviewBar />", () => {
|
||||||
|
|
||||||
it("renders invite message with invited email", async () => {
|
it("renders invite message with invited email", async () => {
|
||||||
const component = getComponent({ inviterName, invitedEmail });
|
const component = getComponent({ inviterName, invitedEmail });
|
||||||
await sleep(0);
|
await waitForElementToBeRemoved(() => component.queryByRole("progressbar"));
|
||||||
|
|
||||||
expect(getMessage(component)).toMatchSnapshot();
|
expect(getMessage(component)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -421,7 +419,7 @@ describe("<RoomPreviewBar />", () => {
|
||||||
|
|
||||||
it("renders invite message with invited email", async () => {
|
it("renders invite message with invited email", async () => {
|
||||||
const component = getComponent({ inviterName, invitedEmail });
|
const component = getComponent({ inviterName, invitedEmail });
|
||||||
await sleep(0);
|
await waitForElementToBeRemoved(() => component.queryByRole("progressbar"));
|
||||||
|
|
||||||
expect(getMessage(component)).toMatchSnapshot();
|
expect(getMessage(component)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -439,7 +437,7 @@ describe("<RoomPreviewBar />", () => {
|
||||||
it("renders email mismatch message when invite email mxid doesnt match", async () => {
|
it("renders email mismatch message when invite email mxid doesnt match", async () => {
|
||||||
MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue({ mxid: "not userid" });
|
MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue({ mxid: "not userid" });
|
||||||
const component = getComponent({ inviterName, invitedEmail });
|
const component = getComponent({ inviterName, invitedEmail });
|
||||||
await sleep(0);
|
await waitForElementToBeRemoved(() => component.queryByRole("progressbar"));
|
||||||
|
|
||||||
expect(getMessage(component)).toMatchSnapshot();
|
expect(getMessage(component)).toMatchSnapshot();
|
||||||
expect(MatrixClientPeg.safeGet().lookupThreePid).toHaveBeenCalledWith(
|
expect(MatrixClientPeg.safeGet().lookupThreePid).toHaveBeenCalledWith(
|
||||||
|
@ -453,7 +451,7 @@ describe("<RoomPreviewBar />", () => {
|
||||||
it("renders invite message when invite email mxid match", async () => {
|
it("renders invite message when invite email mxid match", async () => {
|
||||||
MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue({ mxid: userId });
|
MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue({ mxid: userId });
|
||||||
const component = getComponent({ inviterName, invitedEmail });
|
const component = getComponent({ inviterName, invitedEmail });
|
||||||
await sleep(0);
|
await waitForElementToBeRemoved(() => component.queryByRole("progressbar"));
|
||||||
|
|
||||||
expect(getMessage(component)).toMatchSnapshot();
|
expect(getMessage(component)).toMatchSnapshot();
|
||||||
await testJoinButton({ inviterName, invitedEmail }, false)();
|
await testJoinButton({ inviterName, invitedEmail }, false)();
|
||||||
|
|
|
@ -30,7 +30,16 @@ import {
|
||||||
ThreepidMedium,
|
ThreepidMedium,
|
||||||
} from "matrix-js-sdk/src/matrix";
|
} from "matrix-js-sdk/src/matrix";
|
||||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
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 { mocked } from "jest-mock";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
|
|
||||||
|
@ -244,7 +253,7 @@ describe("<Notifications />", () => {
|
||||||
// get component, wait for async data and force a render
|
// get component, wait for async data and force a render
|
||||||
const getComponentAndWait = async () => {
|
const getComponentAndWait = async () => {
|
||||||
const component = getComponent();
|
const component = getComponent();
|
||||||
await flushPromises();
|
await waitForElementToBeRemoved(() => component.queryAllByRole("progressbar"));
|
||||||
return component;
|
return component;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -527,7 +536,9 @@ describe("<Notifications />", () => {
|
||||||
// oneToOneRule is set to 'on'
|
// oneToOneRule is set to 'on'
|
||||||
// and is kind: 'underride'
|
// and is kind: 'underride'
|
||||||
const offToggle = screen.getByTestId(section + oneToOneRule.rule_id).querySelector('input[type="radio"]')!;
|
const offToggle = screen.getByTestId(section + oneToOneRule.rule_id).querySelector('input[type="radio"]')!;
|
||||||
|
await act(() => {
|
||||||
fireEvent.click(offToggle);
|
fireEvent.click(offToggle);
|
||||||
|
});
|
||||||
|
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
|
@ -552,7 +563,9 @@ describe("<Notifications />", () => {
|
||||||
// oneToOneRule is set to 'on'
|
// oneToOneRule is set to 'on'
|
||||||
// and is kind: 'underride'
|
// and is kind: 'underride'
|
||||||
const offToggle = screen.getByTestId(section + oneToOneRule.rule_id).querySelector('input[type="radio"]')!;
|
const offToggle = screen.getByTestId(section + oneToOneRule.rule_id).querySelector('input[type="radio"]')!;
|
||||||
|
await act(() => {
|
||||||
fireEvent.click(offToggle);
|
fireEvent.click(offToggle);
|
||||||
|
});
|
||||||
|
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
|
@ -576,7 +589,7 @@ describe("<Notifications />", () => {
|
||||||
|
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
// no error after after successful change
|
// no error after successful change
|
||||||
expect(
|
expect(
|
||||||
within(oneToOneRuleElement).queryByText(
|
within(oneToOneRuleElement).queryByText(
|
||||||
"An error occurred when updating your notification preferences. Please try to toggle your option again.",
|
"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");
|
mockClient.setPushRuleActions.mockRejectedValue("oups");
|
||||||
|
|
||||||
const offToggle = oneToOneRuleElement.querySelector('input[type="radio"]')!;
|
const offToggle = oneToOneRuleElement.querySelector('input[type="radio"]')!;
|
||||||
|
await act(() => {
|
||||||
fireEvent.click(offToggle);
|
fireEvent.click(offToggle);
|
||||||
|
});
|
||||||
|
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
|
@ -814,7 +829,9 @@ describe("<Notifications />", () => {
|
||||||
|
|
||||||
mockClient.setPushRuleEnabled.mockRejectedValueOnce("oups");
|
mockClient.setPushRuleEnabled.mockRejectedValueOnce("oups");
|
||||||
|
|
||||||
|
await act(() => {
|
||||||
fireEvent.click(within(screen.getByTestId(section + keywordsRuleId)).getByLabelText("Off"));
|
fireEvent.click(within(screen.getByTestId(section + keywordsRuleId)).getByLabelText("Off"));
|
||||||
|
});
|
||||||
|
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
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 { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
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("Error changing integration manager provisioning");
|
||||||
expect(logger.error).toHaveBeenCalledWith("oups");
|
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 () => {
|
it("toggles out of editing mode when device name is saved successfully", async () => {
|
||||||
const { getByTestId } = render(getComponent());
|
const { getByTestId, findByTestId } = render(getComponent());
|
||||||
|
|
||||||
// start editing
|
// start editing
|
||||||
fireEvent.click(getByTestId("device-heading-rename-cta"));
|
fireEvent.click(getByTestId("device-heading-rename-cta"));
|
||||||
|
@ -118,12 +118,12 @@ describe("<DeviceDetailHeading />", () => {
|
||||||
await flushPromisesWithFakeTimers();
|
await flushPromisesWithFakeTimers();
|
||||||
|
|
||||||
// read mode displayed
|
// 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 () => {
|
it("displays error when device name fails to save", async () => {
|
||||||
const saveDeviceName = jest.fn().mockRejectedValueOnce("oups").mockResolvedValue({});
|
const saveDeviceName = jest.fn().mockRejectedValueOnce("oups").mockResolvedValue({});
|
||||||
const { getByTestId, queryByText, container } = render(getComponent({ saveDeviceName }));
|
const { getByTestId, queryByText, findByText, container } = render(getComponent({ saveDeviceName }));
|
||||||
|
|
||||||
// start editing
|
// start editing
|
||||||
fireEvent.click(getByTestId("device-heading-rename-cta"));
|
fireEvent.click(getByTestId("device-heading-rename-cta"));
|
||||||
|
@ -136,7 +136,7 @@ describe("<DeviceDetailHeading />", () => {
|
||||||
await flushPromisesWithFakeTimers();
|
await flushPromisesWithFakeTimers();
|
||||||
|
|
||||||
// error message displayed
|
// error message displayed
|
||||||
expect(queryByText("Failed to set session name")).toBeTruthy();
|
await expect(findByText("Failed to set session name")).resolves.toBeTruthy();
|
||||||
// spinner removed
|
// spinner removed
|
||||||
expect(container.getElementsByClassName("mx_Spinner").length).toBeFalsy();
|
expect(container.getElementsByClassName("mx_Spinner").length).toBeFalsy();
|
||||||
|
|
||||||
|
|
|
@ -120,8 +120,7 @@ describe("<FilteredDeviceList />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("filtering", () => {
|
describe("filtering", () => {
|
||||||
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) =>
|
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) => {
|
||||||
await act(async () => {
|
|
||||||
const dropdown = container.querySelector('[aria-label="Filter devices"]');
|
const dropdown = container.querySelector('[aria-label="Filter devices"]');
|
||||||
|
|
||||||
fireEvent.click(dropdown as Element);
|
fireEvent.click(dropdown as Element);
|
||||||
|
@ -129,7 +128,7 @@ describe("<FilteredDeviceList />", () => {
|
||||||
await flushPromises();
|
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", () => {
|
it("does not display filter description when filter is falsy", () => {
|
||||||
const { container } = render(getComponent({ filter: undefined }));
|
const { container } = render(getComponent({ filter: undefined }));
|
||||||
|
|
|
@ -104,6 +104,7 @@ describe("<EmailAddress/>", () => {
|
||||||
"https://fake-url/",
|
"https://fake-url/",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
await expect(screen.findByText("Complete")).resolves.not.toHaveAttribute("aria-disabled", "true");
|
||||||
fireEvent.click(screen.getByText("Complete"));
|
fireEvent.click(screen.getByText("Complete"));
|
||||||
|
|
||||||
// Expect error dialog/modal to be shown. We have to wait for the UI to transition.
|
// 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 () => {
|
it("Shows error dialog when share completion fails (UserFriendlyError)", async () => {
|
||||||
const fakeErrorText = "Fake UserFriendlyError error in test" as TranslationKey;
|
const fakeErrorText = "Fake UserFriendlyError error in test" as TranslationKey;
|
||||||
mockClient.bindThreePid.mockRejectedValue(new UserFriendlyError(fakeErrorText));
|
mockClient.bindThreePid.mockRejectedValue(new UserFriendlyError(fakeErrorText));
|
||||||
|
await expect(screen.findByText("Complete")).resolves.not.toHaveAttribute("aria-disabled", "true");
|
||||||
fireEvent.click(screen.getByText("Complete"));
|
fireEvent.click(screen.getByText("Complete"));
|
||||||
|
|
||||||
// Expect error dialog/modal to be shown. We have to wait for the UI to transition.
|
// 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 () => {
|
it("Shows error dialog when share completion fails (generic error)", async () => {
|
||||||
const fakeErrorText = "Fake plain error in test";
|
const fakeErrorText = "Fake plain error in test";
|
||||||
mockClient.bindThreePid.mockRejectedValue(new Error(fakeErrorText));
|
mockClient.bindThreePid.mockRejectedValue(new Error(fakeErrorText));
|
||||||
|
await expect(screen.findByText("Complete")).resolves.not.toHaveAttribute("aria-disabled", "true");
|
||||||
fireEvent.click(screen.getByText("Complete"));
|
fireEvent.click(screen.getByText("Complete"));
|
||||||
|
|
||||||
// Expect error dialog/modal to be shown. We have to wait for the UI to transition.
|
// 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 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 { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { CryptoApi, DeviceVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api";
|
import { CryptoApi, DeviceVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api";
|
||||||
|
@ -146,7 +155,7 @@ describe("<SessionManagerTab />", () => {
|
||||||
// open device detail
|
// open device detail
|
||||||
const tile = getByTestId(`device-tile-${deviceId}`);
|
const tile = getByTestId(`device-tile-${deviceId}`);
|
||||||
const label = isOpen ? "Hide details" : "Show details";
|
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);
|
fireEvent.click(toggle);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -165,16 +174,14 @@ describe("<SessionManagerTab />", () => {
|
||||||
return getByTestId(`device-tile-${deviceId}`);
|
return getByTestId(`device-tile-${deviceId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) =>
|
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) => {
|
||||||
await act(async () => {
|
const dropdown = within(container).getByLabelText("Filter devices");
|
||||||
const dropdown = container.querySelector('[aria-label="Filter devices"]');
|
|
||||||
|
|
||||||
fireEvent.click(dropdown as Element);
|
fireEvent.click(dropdown);
|
||||||
// tick to let dropdown render
|
screen.getByRole("listbox");
|
||||||
await flushPromises();
|
|
||||||
|
|
||||||
fireEvent.click(container.querySelector(`#device-list-filter__${option}`) as Element);
|
fireEvent.click(screen.getByTestId(`filter-option-${option}`) as Element);
|
||||||
});
|
};
|
||||||
|
|
||||||
const isDeviceSelected = (
|
const isDeviceSelected = (
|
||||||
getByTestId: ReturnType<typeof render>["getByTestId"],
|
getByTestId: ReturnType<typeof render>["getByTestId"],
|
||||||
|
@ -920,37 +927,31 @@ describe("<SessionManagerTab />", () => {
|
||||||
|
|
||||||
it("deletes a device when interactive auth is not required", async () => {
|
it("deletes a device when interactive auth is not required", async () => {
|
||||||
mockClient.deleteMultipleDevices.mockResolvedValue({});
|
mockClient.deleteMultipleDevices.mockResolvedValue({});
|
||||||
mockClient.getDevices
|
mockClient.getDevices.mockResolvedValue({
|
||||||
.mockResolvedValueOnce({
|
|
||||||
devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice],
|
devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice],
|
||||||
})
|
});
|
||||||
|
|
||||||
|
const { getByTestId, findByTestId } = render(getComponent());
|
||||||
|
|
||||||
|
await waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar"));
|
||||||
|
await toggleDeviceDetails(getByTestId, alicesMobileDevice.device_id);
|
||||||
|
|
||||||
|
const signOutButton = await within(
|
||||||
|
await findByTestId(`device-detail-${alicesMobileDevice.device_id}`),
|
||||||
|
).findByTestId("device-detail-sign-out-cta");
|
||||||
|
|
||||||
// pretend it was really deleted on refresh
|
// pretend it was really deleted on refresh
|
||||||
.mockResolvedValueOnce({
|
mockClient.getDevices.mockResolvedValueOnce({
|
||||||
devices: [alicesDevice, alicesOlderMobileDevice],
|
devices: [alicesDevice, alicesOlderMobileDevice],
|
||||||
});
|
});
|
||||||
|
|
||||||
const { getByTestId } = render(getComponent());
|
|
||||||
|
|
||||||
await act(async () => {
|
|
||||||
await flushPromises();
|
|
||||||
});
|
|
||||||
|
|
||||||
toggleDeviceDetails(getByTestId, alicesMobileDevice.device_id);
|
|
||||||
|
|
||||||
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 confirmSignout(getByTestId);
|
|
||||||
|
|
||||||
// sign out button is disabled with spinner
|
// sign out button is disabled with spinner
|
||||||
expect(
|
const prom = waitFor(() => expect(signOutButton).toHaveAttribute("aria-disabled", "true"));
|
||||||
(deviceDetails.querySelector('[data-testid="device-detail-sign-out-cta"]') as Element).getAttribute(
|
|
||||||
"aria-disabled",
|
fireEvent.click(signOutButton);
|
||||||
),
|
await confirmSignout(getByTestId);
|
||||||
).toEqual("true");
|
await prom;
|
||||||
|
|
||||||
// delete called
|
// delete called
|
||||||
expect(mockClient.deleteMultipleDevices).toHaveBeenCalledWith(
|
expect(mockClient.deleteMultipleDevices).toHaveBeenCalledWith(
|
||||||
[alicesMobileDevice.device_id],
|
[alicesMobileDevice.device_id],
|
||||||
|
@ -1008,9 +1009,7 @@ describe("<SessionManagerTab />", () => {
|
||||||
|
|
||||||
const { getByTestId, getByLabelText } = render(getComponent());
|
const { getByTestId, getByLabelText } = render(getComponent());
|
||||||
|
|
||||||
await act(async () => {
|
await act(flushPromises);
|
||||||
await flushPromises();
|
|
||||||
});
|
|
||||||
|
|
||||||
// reset mock count after initial load
|
// reset mock count after initial load
|
||||||
mockClient.getDevices.mockClear();
|
mockClient.getDevices.mockClear();
|
||||||
|
@ -1570,9 +1569,7 @@ describe("<SessionManagerTab />", () => {
|
||||||
});
|
});
|
||||||
const { getByTestId, container } = render(getComponent());
|
const { getByTestId, container } = render(getComponent());
|
||||||
|
|
||||||
await act(async () => {
|
await act(flushPromises);
|
||||||
await flushPromises();
|
|
||||||
});
|
|
||||||
|
|
||||||
// filter for inactive sessions
|
// filter for inactive sessions
|
||||||
await setFilter(container, DeviceSecurityVariation.Inactive);
|
await setFilter(container, DeviceSecurityVariation.Inactive);
|
||||||
|
@ -1765,6 +1762,7 @@ describe("<SessionManagerTab />", () => {
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
fireEvent.click(getByText("Show QR code"));
|
fireEvent.click(getByText("Show QR code"));
|
||||||
|
await waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar"));
|
||||||
|
|
||||||
await expect(findByTestId("login-with-qr")).resolves.toBeTruthy();
|
await expect(findByTestId("login-with-qr")).resolves.toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { act } from "@testing-library/react";
|
|
||||||
import { renderHook } from "@testing-library/react-hooks/dom";
|
import { renderHook } from "@testing-library/react-hooks/dom";
|
||||||
|
import { waitFor } from "@testing-library/react";
|
||||||
import { IPushRules, MatrixClient, PushRuleKind, RuleId } from "matrix-js-sdk/src/matrix";
|
import { IPushRules, MatrixClient, PushRuleKind, RuleId } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { useNotificationSettings } from "../../src/hooks/useNotificationSettings";
|
import { useNotificationSettings } from "../../src/hooks/useNotificationSettings";
|
||||||
|
@ -68,17 +68,13 @@ describe("useNotificationSettings", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("correctly parses model", async () => {
|
it("correctly parses model", async () => {
|
||||||
await act(async () => {
|
const { result } = renderHook(() => useNotificationSettings(cli));
|
||||||
const { result, waitForNextUpdate } = renderHook(() => useNotificationSettings(cli));
|
|
||||||
expect(result.current.model).toEqual(null);
|
expect(result.current.model).toEqual(null);
|
||||||
await waitForNextUpdate();
|
await waitFor(() => expect(result.current.model).toEqual(expectedModel));
|
||||||
expect(result.current.model).toEqual(expectedModel);
|
|
||||||
expect(result.current.hasPendingChanges).toBeFalsy();
|
expect(result.current.hasPendingChanges).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("correctly generates change calls", async () => {
|
it("correctly generates change calls", async () => {
|
||||||
await act(async () => {
|
|
||||||
const addPushRule = jest.fn(cli.addPushRule);
|
const addPushRule = jest.fn(cli.addPushRule);
|
||||||
cli.addPushRule = addPushRule;
|
cli.addPushRule = addPushRule;
|
||||||
const deletePushRule = jest.fn(cli.deletePushRule);
|
const deletePushRule = jest.fn(cli.deletePushRule);
|
||||||
|
@ -88,14 +84,12 @@ describe("useNotificationSettings", () => {
|
||||||
const setPushRuleActions = jest.fn(cli.setPushRuleActions);
|
const setPushRuleActions = jest.fn(cli.setPushRuleActions);
|
||||||
cli.setPushRuleActions = setPushRuleActions;
|
cli.setPushRuleActions = setPushRuleActions;
|
||||||
|
|
||||||
const { result, waitForNextUpdate } = renderHook(() => useNotificationSettings(cli));
|
const { result } = renderHook(() => useNotificationSettings(cli));
|
||||||
expect(result.current.model).toEqual(null);
|
expect(result.current.model).toEqual(null);
|
||||||
await waitForNextUpdate();
|
await waitFor(() => expect(result.current.model).toEqual(expectedModel));
|
||||||
expect(result.current.model).toEqual(expectedModel);
|
|
||||||
expect(result.current.hasPendingChanges).toBeFalsy();
|
expect(result.current.hasPendingChanges).toBeFalsy();
|
||||||
await result.current.reconcile(DefaultNotificationSettings);
|
await result.current.reconcile(DefaultNotificationSettings);
|
||||||
await waitForNextUpdate();
|
await waitFor(() => expect(result.current.hasPendingChanges).toBeFalsy());
|
||||||
expect(result.current.hasPendingChanges).toBeFalsy();
|
|
||||||
expect(addPushRule).toHaveBeenCalledTimes(0);
|
expect(addPushRule).toHaveBeenCalledTimes(0);
|
||||||
expect(deletePushRule).toHaveBeenCalledTimes(9);
|
expect(deletePushRule).toHaveBeenCalledTimes(9);
|
||||||
expect(deletePushRule).toHaveBeenCalledWith("global", PushRuleKind.ContentSpecific, "justjann3");
|
expect(deletePushRule).toHaveBeenCalledWith("global", PushRuleKind.ContentSpecific, "justjann3");
|
||||||
|
@ -117,12 +111,7 @@ describe("useNotificationSettings", () => {
|
||||||
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Underride, RuleId.Message, true);
|
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Underride, RuleId.Message, true);
|
||||||
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Underride, RuleId.EncryptedDM, true);
|
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Underride, RuleId.EncryptedDM, true);
|
||||||
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Underride, RuleId.DM, true);
|
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Underride, RuleId.DM, true);
|
||||||
expect(setPushRuleEnabled).toHaveBeenCalledWith(
|
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Override, RuleId.SuppressNotices, false);
|
||||||
"global",
|
|
||||||
PushRuleKind.Override,
|
|
||||||
RuleId.SuppressNotices,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Override, RuleId.InviteToSelf, true);
|
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Override, RuleId.InviteToSelf, true);
|
||||||
expect(setPushRuleActions).toHaveBeenCalledTimes(6);
|
expect(setPushRuleActions).toHaveBeenCalledTimes(6);
|
||||||
expect(setPushRuleActions).toHaveBeenCalledWith(
|
expect(setPushRuleActions).toHaveBeenCalledWith(
|
||||||
|
@ -163,4 +152,3 @@ describe("useNotificationSettings", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
|
@ -81,9 +81,11 @@ describe("useUserOnboardingTasks", () => {
|
||||||
});
|
});
|
||||||
const { result, rerender } = renderHook(() => useUserOnboardingTasks(context.result.current));
|
const { result, rerender } = renderHook(() => useUserOnboardingTasks(context.result.current));
|
||||||
expect(result.current[4].id).toBe("permission-notifications");
|
expect(result.current[4].id).toBe("permission-notifications");
|
||||||
await waitFor(() => expect(result.current[4].completed).toBe(false));
|
expect(result.current[4].completed).toBe(false);
|
||||||
result.current[4].action!.onClick!({ type: "click" } as any);
|
result.current[4].action!.onClick!({ type: "click" } as any);
|
||||||
|
await waitFor(() => {
|
||||||
rerender();
|
rerender();
|
||||||
await waitFor(() => expect(result.current[4].completed).toBe(true));
|
expect(result.current[4].completed).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,6 +32,8 @@ import {
|
||||||
TranslatedString,
|
TranslatedString,
|
||||||
UserFriendlyError,
|
UserFriendlyError,
|
||||||
TranslationKey,
|
TranslationKey,
|
||||||
|
IVariables,
|
||||||
|
Tags,
|
||||||
} from "../src/languageHandler";
|
} from "../src/languageHandler";
|
||||||
import { stubClient } from "./test-utils";
|
import { stubClient } from "./test-utils";
|
||||||
import { setupLanguageMock } from "./setup/setupLanguage";
|
import { setupLanguageMock } from "./setup/setupLanguage";
|
||||||
|
@ -214,13 +216,7 @@ describe("languageHandler JSX", function () {
|
||||||
const plurals = "common|and_n_others";
|
const plurals = "common|and_n_others";
|
||||||
const variableSub = "slash_command|ignore_dialog_description";
|
const variableSub = "slash_command|ignore_dialog_description";
|
||||||
|
|
||||||
type TestCase = [
|
type TestCase = [string, TranslationKey, IVariables, Tags | undefined, TranslatedString];
|
||||||
string,
|
|
||||||
TranslationKey,
|
|
||||||
Record<string, unknown>,
|
|
||||||
Record<string, unknown> | undefined,
|
|
||||||
TranslatedString,
|
|
||||||
];
|
|
||||||
const testCasesEn: TestCase[] = [
|
const testCasesEn: TestCase[] = [
|
||||||
// description of the test case, translationString, variables, tags, expected result
|
// description of the test case, translationString, variables, tags, expected result
|
||||||
["translates a basic string", basicString, {}, undefined, "Rooms"],
|
["translates a basic string", basicString, {}, undefined, "Rooms"],
|
||||||
|
|
|
@ -118,6 +118,9 @@ describe("ProxiedApiModule", () => {
|
||||||
describe("openDialog", () => {
|
describe("openDialog", () => {
|
||||||
it("should open dialog with a custom title and default options", async () => {
|
it("should open dialog with a custom title and default options", async () => {
|
||||||
class MyDialogContent extends DialogContent {
|
class MyDialogContent extends DialogContent {
|
||||||
|
public constructor(props: DialogProps) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
trySubmit = async () => ({ result: true });
|
trySubmit = async () => ({ result: true });
|
||||||
render = () => <p>This is my example content.</p>;
|
render = () => <p>This is my example content.</p>;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +150,9 @@ describe("ProxiedApiModule", () => {
|
||||||
|
|
||||||
it("should open dialog with custom options", async () => {
|
it("should open dialog with custom options", async () => {
|
||||||
class MyDialogContent extends DialogContent {
|
class MyDialogContent extends DialogContent {
|
||||||
|
public constructor(props: DialogProps) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
trySubmit = async () => ({ result: true });
|
trySubmit = async () => ({ result: true });
|
||||||
render = () => <p>This is my example content.</p>;
|
render = () => <p>This is my example content.</p>;
|
||||||
}
|
}
|
||||||
|
@ -178,6 +184,9 @@ describe("ProxiedApiModule", () => {
|
||||||
|
|
||||||
it("should update the options from the opened dialog", async () => {
|
it("should update the options from the opened dialog", async () => {
|
||||||
class MyDialogContent extends DialogContent {
|
class MyDialogContent extends DialogContent {
|
||||||
|
public constructor(props: DialogProps) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
trySubmit = async () => ({ result: true });
|
trySubmit = async () => ({ result: true });
|
||||||
render = () => {
|
render = () => {
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
|
@ -231,6 +240,9 @@ describe("ProxiedApiModule", () => {
|
||||||
|
|
||||||
it("should cancel the dialog from within the dialog", async () => {
|
it("should cancel the dialog from within the dialog", async () => {
|
||||||
class MyDialogContent extends DialogContent {
|
class MyDialogContent extends DialogContent {
|
||||||
|
public constructor(props: DialogProps) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
trySubmit = async () => ({ result: true });
|
trySubmit = async () => ({ result: true });
|
||||||
render = () => (
|
render = () => (
|
||||||
<button type="button" onClick={this.props.cancel}>
|
<button type="button" onClick={this.props.cancel}>
|
||||||
|
|
|
@ -181,4 +181,5 @@ export const mockClientMethodsCrypto = (): Partial<
|
||||||
export const mockClientMethodsRooms = (rooms: Room[] = []): Partial<Record<MethodLikeKeys<MatrixClient>, unknown>> => ({
|
export const mockClientMethodsRooms = (rooms: Room[] = []): Partial<Record<MethodLikeKeys<MatrixClient>, unknown>> => ({
|
||||||
getRooms: jest.fn().mockReturnValue(rooms),
|
getRooms: jest.fn().mockReturnValue(rooms),
|
||||||
getRoom: jest.fn((roomId) => rooms.find((r) => r.roomId === roomId) ?? null),
|
getRoom: jest.fn((roomId) => rooms.find((r) => r.roomId === roomId) ?? null),
|
||||||
|
isRoomEncrypted: jest.fn(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -109,11 +109,9 @@ describe("VoiceBroadcastPreRecordingPip", () => {
|
||||||
|
|
||||||
describe("and double clicking »Go live«", () => {
|
describe("and double clicking »Go live«", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await act(async () => {
|
|
||||||
await userEvent.click(screen.getByText("Go live"));
|
await userEvent.click(screen.getByText("Go live"));
|
||||||
await userEvent.click(screen.getByText("Go live"));
|
await userEvent.click(screen.getByText("Go live"));
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("should call start once", () => {
|
it("should call start once", () => {
|
||||||
expect(preRecording.start).toHaveBeenCalledTimes(1);
|
expect(preRecording.start).toHaveBeenCalledTimes(1);
|
||||||
|
|
|
@ -117,11 +117,9 @@ describe("VoiceBroadcastRecordingPip", () => {
|
||||||
|
|
||||||
describe("and selecting another input device", () => {
|
describe("and selecting another input device", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await act(async () => {
|
|
||||||
await userEvent.click(screen.getByLabelText("Change input device"));
|
await userEvent.click(screen.getByLabelText("Change input device"));
|
||||||
await userEvent.click(screen.getByText("Device 1"));
|
await userEvent.click(screen.getByText("Device 1"));
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("should select the device and pause and resume the broadcast", () => {
|
it("should select the device and pause and resume the broadcast", () => {
|
||||||
expect(MediaDeviceHandler.instance.setDevice).toHaveBeenCalledWith(
|
expect(MediaDeviceHandler.instance.setDevice).toHaveBeenCalledWith(
|
||||||
|
@ -199,8 +197,8 @@ describe("VoiceBroadcastRecordingPip", () => {
|
||||||
client.emit(ClientEvent.Sync, SyncState.Catchup, SyncState.Error);
|
client.emit(ClientEvent.Sync, SyncState.Catchup, SyncState.Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should render a paused recording", () => {
|
it("should render a paused recording", async () => {
|
||||||
expect(screen.getByLabelText("resume voice broadcast")).toBeInTheDocument();
|
await expect(screen.findByLabelText("resume voice broadcast")).resolves.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue