Migrate to React 18 createRoot API (#28256)
* Migrate to React 18 createRoot API 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> * 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> * Discard changes to src/components/views/settings/devices/DeviceDetails.tsx * 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> * Attempt to stabilise test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * legacyRoot? 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> * Fix tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve coverage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve coverage 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> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
48fd330dd9
commit
ca33d9165a
44 changed files with 719 additions and 731 deletions
|
@ -260,7 +260,7 @@ describe("EventTile", () => {
|
|||
} as EventEncryptionInfo);
|
||||
|
||||
const { container } = getComponent();
|
||||
await act(flushPromises);
|
||||
await flushPromises();
|
||||
|
||||
const eventTiles = container.getElementsByClassName("mx_EventTile");
|
||||
expect(eventTiles).toHaveLength(1);
|
||||
|
@ -285,7 +285,7 @@ describe("EventTile", () => {
|
|||
} as EventEncryptionInfo);
|
||||
|
||||
const { container } = getComponent();
|
||||
await act(flushPromises);
|
||||
await flushPromises();
|
||||
|
||||
const eventTiles = container.getElementsByClassName("mx_EventTile");
|
||||
expect(eventTiles).toHaveLength(1);
|
||||
|
@ -314,7 +314,7 @@ describe("EventTile", () => {
|
|||
} as EventEncryptionInfo);
|
||||
|
||||
const { container } = getComponent();
|
||||
await act(flushPromises);
|
||||
await flushPromises();
|
||||
|
||||
const e2eIcons = container.getElementsByClassName("mx_EventTile_e2eIcon");
|
||||
expect(e2eIcons).toHaveLength(1);
|
||||
|
@ -346,7 +346,7 @@ describe("EventTile", () => {
|
|||
await mxEvent.attemptDecryption(mockCrypto);
|
||||
|
||||
const { container } = getComponent();
|
||||
await act(flushPromises);
|
||||
await flushPromises();
|
||||
|
||||
const eventTiles = container.getElementsByClassName("mx_EventTile");
|
||||
expect(eventTiles).toHaveLength(1);
|
||||
|
@ -400,7 +400,7 @@ describe("EventTile", () => {
|
|||
const roomContext = getRoomContext(room, {});
|
||||
const { container, rerender } = render(<WrappedEventTile roomContext={roomContext} />);
|
||||
|
||||
await act(flushPromises);
|
||||
await flushPromises();
|
||||
|
||||
const eventTiles = container.getElementsByClassName("mx_EventTile");
|
||||
expect(eventTiles).toHaveLength(1);
|
||||
|
@ -451,7 +451,7 @@ describe("EventTile", () => {
|
|||
|
||||
const roomContext = getRoomContext(room, {});
|
||||
const { container, rerender } = render(<WrappedEventTile roomContext={roomContext} />);
|
||||
await act(flushPromises);
|
||||
await flushPromises();
|
||||
|
||||
const eventTiles = container.getElementsByClassName("mx_EventTile");
|
||||
expect(eventTiles).toHaveLength(1);
|
||||
|
|
|
@ -8,7 +8,16 @@ Please see LICENSE files in the repository root for full details.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { act, fireEvent, render, RenderResult, screen, waitFor, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
import {
|
||||
act,
|
||||
fireEvent,
|
||||
render,
|
||||
RenderResult,
|
||||
screen,
|
||||
waitFor,
|
||||
waitForElementToBeRemoved,
|
||||
cleanup,
|
||||
} from "jest-matrix-react";
|
||||
import { Room, MatrixClient, RoomState, RoomMember, User, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { mocked, MockedObject } from "jest-mock";
|
||||
|
@ -361,6 +370,7 @@ describe("MemberList", () => {
|
|||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
cleanup();
|
||||
});
|
||||
|
||||
const renderComponent = () => {
|
||||
|
@ -397,21 +407,22 @@ describe("MemberList", () => {
|
|||
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
||||
jest.spyOn(room, "canInvite").mockReturnValue(false);
|
||||
|
||||
renderComponent();
|
||||
await flushPromises();
|
||||
const { findByLabelText } = renderComponent();
|
||||
|
||||
// button rendered but disabled
|
||||
expect(screen.getByText("Invite to this room")).toHaveAttribute("aria-disabled", "true");
|
||||
await expect(findByLabelText("You do not have permission to invite users")).resolves.toHaveAttribute(
|
||||
"aria-disabled",
|
||||
"true",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders enabled invite button when current user is a member and has rights to invite", async () => {
|
||||
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
||||
jest.spyOn(room, "canInvite").mockReturnValue(true);
|
||||
|
||||
renderComponent();
|
||||
await flushPromises();
|
||||
const { findByText } = renderComponent();
|
||||
|
||||
expect(screen.getByText("Invite to this room")).not.toBeDisabled();
|
||||
await expect(findByText("Invite to this room")).resolves.not.toBeDisabled();
|
||||
});
|
||||
|
||||
it("opens room inviter on button click", async () => {
|
||||
|
|
|
@ -42,17 +42,13 @@ import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/t
|
|||
import { SdkContextClass } from "../../../../../src/contexts/SDKContext";
|
||||
|
||||
const openStickerPicker = async (): Promise<void> => {
|
||||
await act(async () => {
|
||||
await userEvent.click(screen.getByLabelText("More options"));
|
||||
await userEvent.click(screen.getByLabelText("Sticker"));
|
||||
});
|
||||
await userEvent.click(screen.getByLabelText("More options"));
|
||||
await userEvent.click(screen.getByLabelText("Sticker"));
|
||||
};
|
||||
|
||||
const startVoiceMessage = async (): Promise<void> => {
|
||||
await act(async () => {
|
||||
await userEvent.click(screen.getByLabelText("More options"));
|
||||
await userEvent.click(screen.getByLabelText("Voice Message"));
|
||||
});
|
||||
await userEvent.click(screen.getByLabelText("More options"));
|
||||
await userEvent.click(screen.getByLabelText("Voice Message"));
|
||||
};
|
||||
|
||||
const setCurrentBroadcastRecording = (room: Room, state: VoiceBroadcastInfoState): void => {
|
||||
|
@ -61,7 +57,7 @@ const setCurrentBroadcastRecording = (room: Room, state: VoiceBroadcastInfoState
|
|||
MatrixClientPeg.safeGet(),
|
||||
state,
|
||||
);
|
||||
SdkContextClass.instance.voiceBroadcastRecordingsStore.setCurrent(recording);
|
||||
act(() => SdkContextClass.instance.voiceBroadcastRecordingsStore.setCurrent(recording));
|
||||
};
|
||||
|
||||
const expectVoiceMessageRecordingTriggered = (): void => {
|
||||
|
@ -97,6 +93,45 @@ describe("MessageComposer", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("wysiwyg correctly persists state to and from localStorage", async () => {
|
||||
const room = mkStubRoom("!roomId:server", "Room 1", cli);
|
||||
const messageText = "Test Text";
|
||||
await SettingsStore.setValue("feature_wysiwyg_composer", null, SettingLevel.DEVICE, true);
|
||||
const { renderResult, rawComponent } = wrapAndRender({ room });
|
||||
const { unmount } = renderResult;
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const key = `mx_wysiwyg_state_${room.roomId}`;
|
||||
|
||||
await userEvent.click(screen.getByRole("textbox"));
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
data: messageText,
|
||||
inputType: "insertText",
|
||||
});
|
||||
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveTextContent(messageText));
|
||||
|
||||
// Wait for event dispatch to happen
|
||||
await flushPromises();
|
||||
|
||||
// assert there is state persisted
|
||||
expect(localStorage.getItem(key)).toBeNull();
|
||||
|
||||
// ensure the right state was persisted to localStorage
|
||||
unmount();
|
||||
|
||||
// assert the persisted state
|
||||
expect(JSON.parse(localStorage.getItem(key)!)).toStrictEqual({
|
||||
content: messageText,
|
||||
isRichText: true,
|
||||
});
|
||||
|
||||
// ensure the correct state is re-loaded
|
||||
render(rawComponent);
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveTextContent(messageText));
|
||||
}, 10000);
|
||||
|
||||
describe("for a Room", () => {
|
||||
const room = mkStubRoom("!roomId:server", "Room 1", cli);
|
||||
|
||||
|
@ -185,14 +220,12 @@ describe("MessageComposer", () => {
|
|||
[true, false].forEach((value: boolean) => {
|
||||
describe(`when ${setting} = ${value}`, () => {
|
||||
beforeEach(async () => {
|
||||
SettingsStore.setValue(setting, null, SettingLevel.DEVICE, value);
|
||||
await act(() => SettingsStore.setValue(setting, null, SettingLevel.DEVICE, value));
|
||||
wrapAndRender({ room });
|
||||
await act(async () => {
|
||||
await userEvent.click(screen.getByLabelText("More options"));
|
||||
});
|
||||
await userEvent.click(screen.getByLabelText("More options"));
|
||||
});
|
||||
|
||||
it(`should${value || "not"} display the button`, () => {
|
||||
it(`should${value ? "" : " not"} display the button`, () => {
|
||||
if (value) {
|
||||
// eslint-disable-next-line jest/no-conditional-expect
|
||||
expect(screen.getByLabelText(buttonLabel)).toBeInTheDocument();
|
||||
|
@ -205,15 +238,17 @@ describe("MessageComposer", () => {
|
|||
describe(`and setting ${setting} to ${!value}`, () => {
|
||||
beforeEach(async () => {
|
||||
// simulate settings update
|
||||
await SettingsStore.setValue(setting, null, SettingLevel.DEVICE, !value);
|
||||
dis.dispatch(
|
||||
{
|
||||
action: Action.SettingUpdated,
|
||||
settingName: setting,
|
||||
newValue: !value,
|
||||
},
|
||||
true,
|
||||
);
|
||||
await act(async () => {
|
||||
await SettingsStore.setValue(setting, null, SettingLevel.DEVICE, !value);
|
||||
dis.dispatch(
|
||||
{
|
||||
action: Action.SettingUpdated,
|
||||
settingName: setting,
|
||||
newValue: !value,
|
||||
},
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should${!value || "not"} display the button`, () => {
|
||||
|
@ -273,7 +308,7 @@ describe("MessageComposer", () => {
|
|||
beforeEach(async () => {
|
||||
wrapAndRender({ room }, true, true);
|
||||
await openStickerPicker();
|
||||
resizeCallback(UI_EVENTS.Resize, {});
|
||||
act(() => resizeCallback(UI_EVENTS.Resize, {}));
|
||||
});
|
||||
|
||||
it("should close the menu", () => {
|
||||
|
@ -295,7 +330,7 @@ describe("MessageComposer", () => {
|
|||
beforeEach(async () => {
|
||||
wrapAndRender({ room }, true, false);
|
||||
await openStickerPicker();
|
||||
resizeCallback(UI_EVENTS.Resize, {});
|
||||
act(() => resizeCallback(UI_EVENTS.Resize, {}));
|
||||
});
|
||||
|
||||
it("should close the menu", () => {
|
||||
|
@ -443,51 +478,6 @@ describe("MessageComposer", () => {
|
|||
expect(screen.queryByLabelText("Sticker")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("wysiwyg correctly persists state to and from localStorage", async () => {
|
||||
const room = mkStubRoom("!roomId:server", "Room 1", cli);
|
||||
const messageText = "Test Text";
|
||||
await SettingsStore.setValue("feature_wysiwyg_composer", null, SettingLevel.DEVICE, true);
|
||||
const { renderResult, rawComponent } = wrapAndRender({ room });
|
||||
const { unmount, rerender } = renderResult;
|
||||
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
const key = `mx_wysiwyg_state_${room.roomId}`;
|
||||
|
||||
await act(async () => {
|
||||
await userEvent.click(screen.getByRole("textbox"));
|
||||
});
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
data: messageText,
|
||||
inputType: "insertText",
|
||||
});
|
||||
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveTextContent(messageText));
|
||||
|
||||
// Wait for event dispatch to happen
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
// assert there is state persisted
|
||||
expect(localStorage.getItem(key)).toBeNull();
|
||||
|
||||
// ensure the right state was persisted to localStorage
|
||||
unmount();
|
||||
|
||||
// assert the persisted state
|
||||
expect(JSON.parse(localStorage.getItem(key)!)).toStrictEqual({
|
||||
content: messageText,
|
||||
isRichText: true,
|
||||
});
|
||||
|
||||
// ensure the correct state is re-loaded
|
||||
rerender(rawComponent);
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveTextContent(messageText));
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
function wrapAndRender(
|
||||
|
@ -529,7 +519,7 @@ function wrapAndRender(
|
|||
);
|
||||
return {
|
||||
rawComponent: getRawComponent(props, roomContext, mockClient),
|
||||
renderResult: render(getRawComponent(props, roomContext, mockClient)),
|
||||
renderResult: render(getRawComponent(props, roomContext, mockClient), { legacyRoot: true }),
|
||||
roomContext,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -385,7 +385,7 @@ describe("<SendMessageComposer/>", () => {
|
|||
|
||||
it("correctly persists state to and from localStorage", () => {
|
||||
const props = { replyToEvent: mockEvent };
|
||||
const { container, unmount, rerender } = getComponent(props);
|
||||
let { container, unmount } = getComponent(props);
|
||||
|
||||
addTextToComposer(container, "Test Text");
|
||||
|
||||
|
@ -402,7 +402,7 @@ describe("<SendMessageComposer/>", () => {
|
|||
});
|
||||
|
||||
// ensure the correct model is re-loaded
|
||||
rerender(getRawComponent(props));
|
||||
({ container, unmount } = getComponent(props));
|
||||
expect(container.textContent).toBe("Test Text");
|
||||
expect(spyDispatcher).toHaveBeenCalledWith({
|
||||
action: "reply_to_event",
|
||||
|
@ -413,7 +413,7 @@ describe("<SendMessageComposer/>", () => {
|
|||
// now try with localStorage wiped out
|
||||
unmount();
|
||||
localStorage.removeItem(key);
|
||||
rerender(getRawComponent(props));
|
||||
({ container } = getComponent(props));
|
||||
expect(container.textContent).toBe("");
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||
|
||||
import "@testing-library/jest-dom";
|
||||
import React from "react";
|
||||
import { act, fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
||||
import { fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
||||
|
||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||
import RoomContext from "../../../../../../src/contexts/RoomContext";
|
||||
|
@ -253,9 +253,7 @@ describe("EditWysiwygComposer", () => {
|
|||
});
|
||||
|
||||
// Wait for event dispatch to happen
|
||||
await act(async () => {
|
||||
await flushPromises();
|
||||
});
|
||||
await flushPromises();
|
||||
|
||||
// Then we don't get it because we are disabled
|
||||
expect(screen.getByRole("textbox")).not.toHaveFocus();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue