1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-08-07 21:23:00 +03:00
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2024-08-01 17:01:42 +01:00
parent 07670a75ce
commit 8d7f0aa3cc
17 changed files with 257 additions and 298 deletions

View File

@@ -16,7 +16,7 @@ limitations under the License.
import React from "react";
import { mocked } from "jest-mock";
import { act, render, RenderResult, screen, waitFor } from "@testing-library/react";
import { act, render, RenderResult, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MatrixClient, createClient } from "matrix-js-sdk/src/matrix";

View File

@@ -38,9 +38,7 @@ exports[`<DialogSidebar /> renders sidebar correctly with beacons 1`] = `
data-type="round"
role="presentation"
style="--cpd-avatar-size: 32px;"
>
</span>
/>
<div
class="mx_BeaconListItem_info"
>

View File

@@ -16,7 +16,7 @@ limitations under the License.
import React, { ComponentProps } from "react";
import { SecretStorage, MatrixClient } from "matrix-js-sdk/src/matrix";
import { act, fireEvent, render, screen } from "@testing-library/react";
import { act, fireEvent, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Mocked } from "jest-mock";
@@ -129,11 +129,13 @@ describe("AccessSecretStorageDialog", () => {
expect(screen.getByPlaceholderText("Security Phrase")).toHaveValue(securityKey);
await submitDialog();
await waitFor(() =>
expect(
screen.getByText(
"👎 Unable to access secret storage. Please verify that you entered the correct Security Phrase.",
),
).toBeInTheDocument();
).toBeInTheDocument(),
);
expect(screen.getByPlaceholderText("Security Phrase")).toHaveFocus();
});

View File

@@ -27,7 +27,7 @@ import {
} from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import sanitizeHtml from "sanitize-html";
import { fireEvent, render, screen } from "@testing-library/react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import SpotlightDialog from "../../../../src/components/views/dialogs/spotlight/SpotlightDialog";
import { Filter } from "../../../../src/components/views/dialogs/spotlight/Filter";
@@ -201,11 +201,13 @@ describe("Spotlight Dialog", () => {
expect(filterChip).toBeInTheDocument();
expect(filterChip.innerHTML).toContain("Public rooms");
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBe(1);
expect(options[0].innerHTML).toContain(testPublicRoom.name);
});
});
it("with people filter", async () => {
render(
@@ -223,12 +225,14 @@ describe("Spotlight Dialog", () => {
expect(filterChip).toBeInTheDocument();
expect(filterChip.innerHTML).toContain("People");
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(1);
expect(options[0]!.innerHTML).toContain(testPerson.display_name);
});
});
});
describe("when MSC3946 dynamic room predecessors is enabled", () => {
beforeEach(() => {
@@ -269,10 +273,12 @@ describe("Spotlight Dialog", () => {
expect(filterChip).toBeInTheDocument();
expect(filterChip.innerHTML).toContain("Public rooms");
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBe(1);
expect(options[0]!.innerHTML).toContain(testPublicRoom.name);
});
// assert that getVisibleRooms is called without MSC3946 dynamic room predecessors
expect(mockedClient.getVisibleRooms).toHaveBeenCalledWith(false);
@@ -292,12 +298,14 @@ describe("Spotlight Dialog", () => {
expect(filterChip).toBeInTheDocument();
expect(filterChip.innerHTML).toContain("People");
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(1);
expect(options[0]!.innerHTML).toContain(testPerson.display_name);
});
});
});
describe("should allow clearing filter manually", () => {
it("with public room filter", async () => {
@@ -380,12 +388,14 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(2);
expect(options[0]).toHaveTextContent("User Alpha");
expect(options[1]).toHaveTextContent("User Beta");
});
});
it("should not filter out users sent by the server even if a local suggestion gets filtered out", async () => {
const member = new RoomMember(testRoom.roomId, testPerson.user_id);
@@ -405,12 +415,14 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(2);
expect(options[0]).toHaveTextContent(testPerson.display_name!);
expect(options[1]).toHaveTextContent("User Beta");
});
});
it("show non-matching query members with DMs if they are present in the server search results", async () => {
mocked(mockedClient.searchUserDirectory).mockResolvedValue({
@@ -427,12 +439,14 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(2);
expect(options[0]).toHaveTextContent(testDMUserId);
expect(options[1]).toHaveTextContent("Bob Wonder");
});
});
it("don't sort the order of users sent by the server", async () => {
const serverList = [
@@ -449,12 +463,14 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(2);
expect(options[0]).toHaveTextContent("User Beta");
expect(options[1]).toHaveTextContent("User Alpha");
});
});
it("should start a DM when clicking a person", async () => {
render(
@@ -468,13 +484,14 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
const options = document.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBeGreaterThanOrEqual(1);
expect(options[0]!.innerHTML).toContain(testPerson.display_name);
fireEvent.click(options[0]!);
expect(startDmOnFirstMessage).toHaveBeenCalledWith(mockedClient, [new DirectoryMember(testPerson)]);
});
});
it("should pass via of the server being explored when joining room from directory", async () => {
SdkConfig.put({
@@ -489,6 +506,7 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
const content = document.querySelector("#mx_SpotlightDialog_content")!;
const options = content.querySelectorAll("li.mx_SpotlightDialog_option");
expect(options.length).toBe(1);
@@ -504,6 +522,7 @@ describe("Spotlight Dialog", () => {
}),
);
});
});
describe("nsfw public rooms filter", () => {
const nsfwNameRoom: IPublicRoomsChunkRoom = {
@@ -549,10 +568,12 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
expect(screen.getByText(potatoRoom.name!)).toBeInTheDocument();
expect(screen.queryByText(nsfwTopicRoom.name!)).not.toBeInTheDocument();
expect(screen.queryByText(nsfwTopicRoom.name!)).not.toBeInTheDocument();
});
});
it("displays rooms with nsfw keywords in results when showNsfwPublicRooms is truthy", async () => {
SettingsStore.setValue("SpotlightSearch.showNsfwPublicRooms", null, SettingLevel.DEVICE, true);
@@ -562,11 +583,13 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
await waitFor(() => {
expect(screen.getByText(nsfwTopicRoom.name!)).toBeInTheDocument();
expect(screen.getByText(nsfwNameRoom.name!)).toBeInTheDocument();
expect(screen.getByText(potatoRoom.name!)).toBeInTheDocument();
});
});
});
it("should show error if /publicRooms API failed", async () => {
mocked(mockedClient.publicRooms).mockRejectedValue(new ConnectionError("Failed to fetch"));
@@ -575,7 +598,7 @@ describe("Spotlight Dialog", () => {
jest.advanceTimersByTime(200);
await flushPromisesWithFakeTimers();
expect(screen.getByText("Failed to query public rooms")).toBeInTheDocument();
await waitFor(() => expect(screen.getByText("Failed to query public rooms")).toBeInTheDocument());
});
describe("knock rooms", () => {

View File

@@ -57,14 +57,9 @@ jest.mock("../../../../src/settings/SettingsStore", () => ({
settingIsOveriddenAtConfigLevel: jest.fn(),
}));
jest.mock("../../../../src/SdkConfig", () => ({
get: jest.fn(),
}));
describe("<UserSettingsDialog />", () => {
const userId = "@alice:server.org";
const mockSettingsStore = mocked(SettingsStore);
const mockSdkConfig = mocked(SdkConfig);
let mockClient!: MockedObject<MatrixClient>;
let sdkContext: SdkContextClass;
@@ -89,7 +84,8 @@ describe("<UserSettingsDialog />", () => {
mockSettingsStore.getValue.mockReturnValue(false);
mockSettingsStore.getValueAt.mockReturnValue(false);
mockSettingsStore.getFeatureSettingNames.mockReturnValue([]);
mockSdkConfig.get.mockReturnValue({ brand: "Test" });
SdkConfig.reset();
SdkConfig.put({ brand: "Test" });
});
const getActiveTabLabel = (container: Element) =>
@@ -115,6 +111,9 @@ describe("<UserSettingsDialog />", () => {
});
it("renders tabs correctly", () => {
SdkConfig.add({
show_labs_settings: true,
});
const { container } = render(getComponent());
expect(container.querySelectorAll(".mx_TabbedView_tabLabel")).toMatchSnapshot();
});
@@ -181,7 +180,7 @@ describe("<UserSettingsDialog />", () => {
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 }));
expect(getActiveTabLabel(container)).toEqual("Security & Privacy");
@@ -189,18 +188,8 @@ describe("<UserSettingsDialog />", () => {
});
it("renders with labs tab selected", () => {
// @ts-ignore I give up trying to get the types right here
// why do we have functions that return different things depending on what they're passed?
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;
}
SdkConfig.add({
show_labs_settings: true,
});
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", () => {
// @ts-ignore simplified test stub
mockSdkConfig.get.mockImplementation((configName) => configName === "show_labs_settings");
SdkConfig.add({
show_labs_settings: true,
});
const { getByTestId } = render(getComponent());
expect(getByTestId(`settings-tab-${UserTab.Labs}`)).toBeTruthy();
});

View File

@@ -211,7 +211,7 @@ describe("<MImageBody/>", () => {
it("should generate a thumbnail if one isn't included for animated media", async () => {
Object.defineProperty(global.Image.prototype, "src", {
set(src) {
window.setTimeout(() => this.onload());
window.setTimeout(() => this.onload?.());
},
});
Object.defineProperty(global.Image.prototype, "height", {

View File

@@ -375,6 +375,7 @@ describe("RoomHeader", () => {
jest.spyOn(CallStore.instance, "getCall").mockReturnValue({
widget,
on: () => {},
off: () => {},
} as unknown as Call);
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);
const { container } = render(<RoomHeader room={room} />, getWrapper());
@@ -393,6 +394,7 @@ describe("RoomHeader", () => {
jest.spyOn(CallStore.instance, "getCall").mockReturnValue({
widget,
on: () => {},
off: () => {},
} as unknown as Call);
jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]);

View File

@@ -17,7 +17,7 @@ limitations under the License.
import React from "react";
import { MockedObject } from "jest-mock";
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 { SDKContext, SdkContextClass } from "../../../../../src/contexts/SDKContext";
@@ -94,7 +94,7 @@ describe("<VideoRoomChatButton />", () => {
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();
// start in read state
const notificationState = mockRoomNotificationState(room, NotificationLevel.None);
@@ -108,10 +108,10 @@ describe("<VideoRoomChatButton />", () => {
notificationState.emit(NotificationStateEvents.Update);
// 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();
// start in unread state
const notificationState = mockRoomNotificationState(room, NotificationLevel.Highlight);
@@ -125,6 +125,6 @@ describe("<VideoRoomChatButton />", () => {
notificationState.emit(NotificationStateEvents.Update);
// unread marker cleared
expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeFalsy();
await waitFor(() => expect(screen.getByLabelText("Chat").hasAttribute("data-indicator")).toBeFalsy());
});
});

View File

@@ -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;
};

View File

@@ -39,7 +39,6 @@ exports[`<SecureBackupPanel /> handles error fetching backup 1`] = `
</th>
<td>
not found locally
</td>
</tr>
<tr>
@@ -75,20 +74,15 @@ exports[`<SecureBackupPanel /> suggests connecting session to key backup when ba
Back up your encryption keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Security Key.
</div>
<div
class="mx_SettingsSubsection_text"
class="mx_Spinner"
>
<span>
This session is
<b>
not backing up your keys
</b>
, but you do have an existing backup you can restore from and add to going forward.
</span>
</div>
<div
class="mx_SettingsSubsection_text"
>
Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.
aria-label="Loading…"
class="mx_Spinner_icon"
data-testid="spinner"
role="progressbar"
style="width: 32px; height: 32px;"
/>
</div>
<details>
<summary
@@ -117,7 +111,6 @@ exports[`<SecureBackupPanel /> suggests connecting session to key backup when ba
</th>
<td>
not found locally
</td>
</tr>
<tr>
@@ -140,54 +133,7 @@ exports[`<SecureBackupPanel /> suggests connecting session to key backup when ba
not ready
</td>
</tr>
<tr>
<th
scope="row"
>
Latest backup version on server:
</th>
<td>
1
(
Algorithm:
<code>
test
</code>
)
</td>
</tr>
<tr>
<th
scope="row"
>
Active backup version:
</th>
<td>
None
</td>
</tr>
</table>
<div />
</details>
<div
class="mx_SecureBackupPanel_buttonRow"
>
<div
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary_outline"
role="button"
tabindex="0"
>
Connect this session to Key Backup
</div>
<div
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger_outline"
role="button"
tabindex="0"
>
Delete Backup
</div>
</div>
</div>
`;

View File

@@ -15,7 +15,7 @@ limitations under the License.
*/
import React from "react";
import { fireEvent, render, RenderResult } from "@testing-library/react";
import { fireEvent, render, RenderResult, waitFor } from "@testing-library/react";
import { DeviceDetailHeading } from "../../../../../src/components/views/settings/devices/DeviceDetailHeading";
import { flushPromisesWithFakeTimers } from "../../../../test-utils";
@@ -118,7 +118,7 @@ describe("<DeviceDetailHeading />", () => {
await flushPromisesWithFakeTimers();
// read mode displayed
expect(getByTestId("device-detail-heading")).toBeTruthy();
await waitFor(() => expect(getByTestId("device-detail-heading")).toBeTruthy());
});
it("displays error when device name fails to save", async () => {
@@ -136,7 +136,7 @@ describe("<DeviceDetailHeading />", () => {
await flushPromisesWithFakeTimers();
// error message displayed
expect(queryByText("Failed to set session name")).toBeTruthy();
await waitFor(() => expect(queryByText("Failed to set session name")).toBeTruthy());
// spinner removed
expect(container.getElementsByClassName("mx_Spinner").length).toBeFalsy();

View File

@@ -120,8 +120,7 @@ describe("<FilteredDeviceList />", () => {
});
describe("filtering", () => {
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) =>
await act(async () => {
const setFilter = async (container: HTMLElement, option: DeviceSecurityVariation | string) => {
const dropdown = container.querySelector('[aria-label="Filter devices"]');
fireEvent.click(dropdown as Element);
@@ -129,7 +128,7 @@ describe("<FilteredDeviceList />", () => {
await flushPromises();
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 }));

View File

@@ -42,14 +42,14 @@ exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses an
>
<input
autocomplete="email"
id="mx_Field_27"
id="mx_Field_9"
label="Email Address"
placeholder="Email Address"
type="text"
value=""
/>
<label
for="mx_Field_27"
for="mx_Field_9"
>
Email Address
</label>
@@ -150,14 +150,14 @@ exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses an
</span>
<input
autocomplete="tel-national"
id="mx_Field_28"
id="mx_Field_10"
label="Phone Number"
placeholder="Phone Number"
type="text"
value=""
/>
<label
for="mx_Field_28"
for="mx_Field_10"
>
Phone Number
</label>

View File

@@ -2,7 +2,7 @@
exports[`ThreadsActivityCentre renders notifications matching the snapshot 1`] = `
<div
aria-labelledby="radix-16"
aria-labelledby="radix-:r2f:"
aria-orientation="vertical"
class="_menu_1x5h1_17"
data-align="start"
@@ -11,14 +11,14 @@ exports[`ThreadsActivityCentre renders notifications matching the snapshot 1`] =
data-side="top"
data-state="open"
dir="ltr"
id="radix-17"
id="radix-:r2g:"
role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1"
>
<h3
class="_typography_yh5dq_162 _font-body-sm-semibold_yh5dq_45 _title_1x5h1_83"
id=":r6:"
id=":r2l:"
>
Threads activity
</h3>
@@ -145,14 +145,14 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
class="mx_ThreadsActivityCentre_container"
>
<button
aria-controls="radix-3"
aria-controls="radix-:r15:"
aria-disabled="false"
aria-expanded="true"
aria-haspopup="menu"
aria-label="Threads"
class="_icon-button_bh2qc_17 mx_ThreadsActivityCentreButton"
data-state="open"
id="radix-2"
id="radix-:r14:"
role="button"
style="--cpd-icon-button-size: 32px;"
tabindex="0"
@@ -175,7 +175,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
style="position: fixed; left: 0px; top: 0px; transform: translate(0px, -8px); min-width: max-content; --radix-popper-available-width: 0px; --radix-popper-available-height: -8px; --radix-popper-anchor-width: 0px; --radix-popper-anchor-height: 0px; --radix-popper-transform-origin: 0% 0px;"
>
<div
aria-labelledby="radix-2"
aria-labelledby="radix-:r14:"
aria-orientation="vertical"
class="_menu_1x5h1_17"
data-align="start"
@@ -184,14 +184,14 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
data-side="top"
data-state="open"
dir="ltr"
id="radix-3"
id="radix-:r15:"
role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1"
>
<h3
class="_typography_yh5dq_162 _font-body-sm-semibold_yh5dq_45 _title_1x5h1_83"
id=":r1:"
id=":r1a:"
>
Threads activity
</h3>
@@ -218,7 +218,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
<div
aria-labelledby="radix-22"
aria-labelledby="radix-:r2v:"
aria-orientation="vertical"
class="_menu_1x5h1_17"
data-align="start"
@@ -227,14 +227,14 @@ exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
data-side="top"
data-state="open"
dir="ltr"
id="radix-23"
id="radix-:r30:"
role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1"
>
<h3
class="_typography_yh5dq_162 _font-body-sm-semibold_yh5dq_45 _title_1x5h1_83"
id=":r8:"
id=":r35:"
>
Threads activity
</h3>
@@ -252,7 +252,7 @@ exports[`ThreadsActivityCentre should match snapshot when empty 1`] = `
exports[`ThreadsActivityCentre should order the room with the same notification level by most recent 1`] = `
<div
aria-labelledby="radix-24"
aria-labelledby="radix-:r36:"
aria-orientation="vertical"
class="_menu_1x5h1_17"
data-align="start"
@@ -261,14 +261,14 @@ exports[`ThreadsActivityCentre should order the room with the same notification
data-side="top"
data-state="open"
dir="ltr"
id="radix-25"
id="radix-:r37:"
role="menu"
style="outline: none; --radix-dropdown-menu-content-transform-origin: var(--radix-popper-transform-origin); --radix-dropdown-menu-content-available-width: var(--radix-popper-available-width); --radix-dropdown-menu-content-available-height: var(--radix-popper-available-height); --radix-dropdown-menu-trigger-width: var(--radix-popper-anchor-width); --radix-dropdown-menu-trigger-height: var(--radix-popper-anchor-height); pointer-events: auto;"
tabindex="-1"
>
<h3
class="_typography_yh5dq_162 _font-body-sm-semibold_yh5dq_45 _title_1x5h1_83"
id=":r9:"
id=":r3c:"
>
Threads activity
</h3>
@@ -432,8 +432,8 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
class="mx_ThreadsActivityCentre_container"
>
<button
aria-controls=":r6:"
aria-describedby=":r6:"
aria-controls=":r8:"
aria-describedby=":r8:"
aria-expanded="true"
aria-haspopup="dialog"
aria-label="Threads"
@@ -459,7 +459,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
tabindex="0"
/>
<span
aria-owns=":r12:"
aria-owns=":re:"
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: fixed; white-space: nowrap; width: 1px; top: 0px; left: 0px;"
/>
<span
@@ -473,7 +473,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
</div>
<div
data-floating-ui-portal=""
id=":r12:"
id=":re:"
>
<span
data-floating-ui-focus-guard=""
@@ -484,10 +484,10 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
tabindex="0"
/>
<div
aria-describedby=":r5:"
aria-labelledby=":r4:"
aria-describedby=":r7:"
aria-labelledby=":r6:"
class="_content_1oa1y_17"
id=":r6:"
id=":r8:"
role="dialog"
style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);"
tabindex="-1"
@@ -505,7 +505,7 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
stroke="none"
/>
<clippath
id=":r13:"
id=":rf:"
>
<rect
height="20"
@@ -517,13 +517,13 @@ exports[`ThreadsActivityCentre should render the release announcement 1`] = `
</svg>
<h3
class="_typography_yh5dq_162 _font-body-lg-semibold_yh5dq_83 _header_1oa1y_46"
id=":r4:"
id=":r6:"
>
Threads Activity Centre
</h3>
<span
class="_typography_yh5dq_162 _font-body-sm-regular_yh5dq_40 _description_1oa1y_52"
id=":r5:"
id=":r7:"
>
Threads notifications have moved, find them here from now on.
</span>

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { act, renderHook, waitFor } from "@testing-library/react";
import { renderHook, waitFor } from "@testing-library/react";
import { IPushRules, MatrixClient, PushRuleKind, RuleId } from "matrix-js-sdk/src/matrix";
import { useNotificationSettings } from "../../src/hooks/useNotificationSettings";
@@ -67,16 +67,13 @@ describe("useNotificationSettings", () => {
});
it("correctly parses model", async () => {
await act(async () => {
const { result } = renderHook(() => useNotificationSettings(cli));
expect(result.current.model).toEqual(null);
await waitFor(() => expect(result.current.model).toEqual(expectedModel));
expect(result.current.hasPendingChanges).toBeFalsy();
});
});
it("correctly generates change calls", async () => {
await act(async () => {
const addPushRule = jest.fn(cli.addPushRule);
cli.addPushRule = addPushRule;
const deletePushRule = jest.fn(cli.deletePushRule);
@@ -113,12 +110,7 @@ describe("useNotificationSettings", () => {
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.DM, true);
expect(setPushRuleEnabled).toHaveBeenCalledWith(
"global",
PushRuleKind.Override,
RuleId.SuppressNotices,
false,
);
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Override, RuleId.SuppressNotices, false);
expect(setPushRuleEnabled).toHaveBeenCalledWith("global", PushRuleKind.Override, RuleId.InviteToSelf, true);
expect(setPushRuleActions).toHaveBeenCalledTimes(6);
expect(setPushRuleActions).toHaveBeenCalledWith(
@@ -158,5 +150,4 @@ describe("useNotificationSettings", () => {
StandardActions.ACTION_NOTIFY_DEFAULT_SOUND,
);
});
});
});

View File

@@ -22,6 +22,7 @@ import { mocked } from "jest-mock";
import { PredictableRandom } from "./predictableRandom"; // https://github.com/jsdom/jsdom/issues/2555
declare global {
// eslint-disable-next-line no-var
var IS_REACT_ACT_ENVIRONMENT: boolean;
}

View File

@@ -16,7 +16,7 @@ limitations under the License.
//
import React from "react";
import { act, render, RenderResult, screen } from "@testing-library/react";
import { act, render, RenderResult, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ClientEvent, MatrixClient, MatrixEvent, SyncState } from "matrix-js-sdk/src/matrix";
import { sleep } from "matrix-js-sdk/src/utils";
@@ -117,11 +117,9 @@ describe("VoiceBroadcastRecordingPip", () => {
describe("and selecting another input device", () => {
beforeEach(async () => {
await act(async () => {
await userEvent.click(screen.getByLabelText("Change input device"));
await userEvent.click(screen.getByText("Device 1"));
});
});
it("should select the device and pause and resume the broadcast", () => {
expect(MediaDeviceHandler.instance.setDevice).toHaveBeenCalledWith(
@@ -199,8 +197,8 @@ describe("VoiceBroadcastRecordingPip", () => {
client.emit(ClientEvent.Sync, SyncState.Catchup, SyncState.Error);
});
it("should render a paused recording", () => {
expect(screen.getByLabelText("resume voice broadcast")).toBeInTheDocument();
it("should render a paused recording", async () => {
await waitFor(() => expect(screen.getByLabelText("resume voice broadcast")).toBeInTheDocument());
});
});
});