Update react monorepo to v19 (major) (#28914)

* Update react monorepo to v19

* Import JSX explicitly for React 19 compatibility

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update usages of refs for React 19 compatibility

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update react imports

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Avoid legacy contexts as much as possible

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Avoid deprecated React symbols

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Stash

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update usages of refs for React 19 compatibility

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>

* Switch pillify to use a html-react-parser approach rather than DOM muddling

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate react html parsing

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate react html parsing

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate html parsing

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Memoize the EventContentBody component

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate html parsing

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>

* Simplify

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Discard changes to src/Linkify.tsx

* Discard changes to src/components/views/messages/TextualBody.tsx

* Discard changes to src/settings/handlers/AbstractLocalStorageSettingsHandler.ts

* 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>

* Prepare for React 19 upgrade

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Remove stale comment

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
renovate[bot]
2025-04-09 19:03:09 +00:00
committed by GitHub
parent f54fbf7231
commit e1b2e3a101
44 changed files with 300 additions and 290 deletions

View File

@@ -7,8 +7,6 @@ exports[`TextForEvent textForJoinRulesEvent() returns correct JSX message when r
<AccessibleButton
kind="link_inline"
onClick={[Function]}
role="button"
tabIndex={0}
>
View settings
</AccessibleButton>

View File

@@ -33,6 +33,10 @@ const EMOJI_SHORTCODES = [
// to simply assert that the final completion with the colon is the exact emoji.
const TOO_SHORT_EMOJI_SHORTCODE = [{ emojiShortcode: ":o", expectedEmoji: "⭕️" }];
interface CompletionComponentProps {
title: string;
}
describe("EmojiProvider", function () {
const testRoom = mkStubRoom(undefined, undefined, undefined);
stubClient();
@@ -69,8 +73,8 @@ describe("EmojiProvider", function () {
const ep = new EmojiProvider(testRoom);
const completionsList = await ep.getCompletions(":heart", { beginning: true, start: 0, end: 6 });
expect(completionsList[0]?.component?.props.title).toEqual(":heartpulse:");
expect(completionsList[1]?.component?.props.title).toEqual(":heart_eyes:");
expect((completionsList[0]?.component?.props as CompletionComponentProps).title).toEqual(":heartpulse:");
expect((completionsList[1]?.component?.props as CompletionComponentProps).title).toEqual(":heart_eyes:");
});
it("Exact match in recently used takes the lead", async function () {
@@ -83,8 +87,8 @@ describe("EmojiProvider", function () {
const ep = new EmojiProvider(testRoom);
const completionsList = await ep.getCompletions(":heart", { beginning: true, start: 0, end: 6 });
expect(completionsList[0]?.component?.props.title).toEqual(":heart:");
expect(completionsList[1]?.component?.props.title).toEqual(":heartpulse:");
expect(completionsList[2]?.component?.props.title).toEqual(":heart_eyes:");
expect((completionsList[0]?.component?.props as CompletionComponentProps).title).toEqual(":heart:");
expect((completionsList[1]?.component?.props as CompletionComponentProps).title).toEqual(":heartpulse:");
expect((completionsList[2]?.component?.props as CompletionComponentProps).title).toEqual(":heart_eyes:");
});
});

View File

@@ -63,12 +63,12 @@ describe("AutocompleteInput", () => {
const input = getEditorInput();
act(() => {
await act(async () => {
fireEvent.focus(input);
fireEvent.change(input, { target: { value: "user" } });
await waitFor(() => expect(mockProvider.getCompletions).toHaveBeenCalledTimes(1));
});
await waitFor(() => expect(mockProvider.getCompletions).toHaveBeenCalledTimes(1));
expect(screen.getByTestId("autocomplete-matches").childNodes).toHaveLength(mockCompletion.length);
});
@@ -152,12 +152,12 @@ describe("AutocompleteInput", () => {
const input = getEditorInput();
act(() => {
await act(async () => {
fireEvent.focus(input);
fireEvent.change(input, { target: { value: "user" } });
await waitFor(() => expect(mockProvider.getCompletions).toHaveBeenCalledTimes(1));
});
await waitFor(() => expect(mockProvider.getCompletions).toHaveBeenCalledTimes(1));
expect(screen.getAllByTestId("custom-suggestion-element")).toHaveLength(mockCompletion.length);
});

View File

@@ -118,7 +118,7 @@ describe("<MatrixChat />", () => {
startup: jest.fn(),
},
login: jest.fn(),
loginFlows: jest.fn(),
loginFlows: jest.fn().mockResolvedValue({ flows: [] }),
isGuest: jest.fn().mockReturnValue(false),
clearStores: jest.fn(),
setGuest: jest.fn(),
@@ -165,12 +165,9 @@ describe("<MatrixChat />", () => {
isNameResolvable: true,
warning: "",
};
let initPromise: Promise<void> | undefined;
let defaultProps: ComponentProps<typeof MatrixChat>;
const getComponent = (props: Partial<ComponentProps<typeof MatrixChat>> = {}) => {
// MatrixChat does many questionable things which bomb tests in modern React mode,
// we'll want to refactor and break up MatrixChat before turning off legacyRoot mode
return render(<MatrixChat {...defaultProps} {...props} />, { legacyRoot: true });
return render(<MatrixChat {...defaultProps} {...props} />);
};
// make test results readable
@@ -220,6 +217,8 @@ describe("<MatrixChat />", () => {
};
beforeEach(async () => {
localStorage.clear();
jest.restoreAllMocks();
defaultProps = {
config: {
brand: "Test",
@@ -235,10 +234,8 @@ describe("<MatrixChat />", () => {
onNewScreen: jest.fn(),
onTokenLoginCompleted: jest.fn(),
realQueryParams: {},
initPromiseCallback: (p: Promise<void>) => (initPromise = p),
};
initPromise = undefined;
mockClient = getMockClientWithEventEmitter(getMockClientMethods());
jest.spyOn(MatrixJs, "createClient").mockReturnValue(mockClient);
@@ -257,18 +254,9 @@ describe("<MatrixChat />", () => {
});
afterEach(async () => {
// Wait for the promise that MatrixChat gives us to complete so that we know
// it's finished running its login code. We either need to do this or make the
// login code abort halfway through once the test finishes testing whatever it
// needs to test. If we do nothing, the login code will just continue running
// and interfere with the subsequent tests.
await initPromise;
// @ts-ignore
DMRoomMap.setShared(null);
jest.restoreAllMocks();
// emit a loggedOut event so that all of the Store singletons forget about their references to the mock client
// (must be sync otherwise the next test will start before it happens)
act(() => defaultDispatcher.dispatch({ action: Action.OnLoggedOut }, true));
@@ -313,7 +301,6 @@ describe("<MatrixChat />", () => {
state: state,
};
const userId = "@alice:server.org";
const deviceId = "test-device-id";
const accessToken = "test-access-token-from-oidc";
@@ -335,8 +322,6 @@ describe("<MatrixChat />", () => {
const dialog = await screen.findByRole("dialog");
expect(within(dialog).getByText(errorMessage)).toBeInTheDocument();
// just check we're back on welcome page
await expect(screen.findByTestId("mx_welcome_screen")).resolves.toBeInTheDocument();
};
beforeEach(() => {
@@ -518,6 +503,9 @@ describe("<MatrixChat />", () => {
it("should set logged in and start MatrixClient", async () => {
getComponent({ realQueryParams });
defaultDispatcher.dispatch({
action: "will_start_client",
});
// client successfully started
await waitFor(() =>
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: "client_started" }),
@@ -597,9 +585,7 @@ describe("<MatrixChat />", () => {
// wait for logged in view to load
await screen.findByLabelText("User menu");
expect(screen.queryByRole("progressbar")).not.toBeInTheDocument();
const h1Element = screen.getByRole("heading", { level: 1 });
expect(h1Element).toHaveTextContent(`Welcome Ernie`);
await screen.findByRole("heading", { level: 1, name: "Welcome Ernie" });
});
describe("clean up drafts", () => {
@@ -612,9 +598,6 @@ describe("<MatrixChat />", () => {
localStorage.setItem(`mx_cider_state_${roomId}`, "fake_content");
mockClient.getRoom.mockImplementation((id) => [room].find((room) => room.roomId === id) || null);
});
afterEach(() => {
jest.restoreAllMocks();
});
it("should clean up drafts", async () => {
Date.now = jest.fn(() => timestamp);
localStorage.setItem(`mx_cider_state_${roomId}`, "fake_content");
@@ -1113,8 +1096,6 @@ describe("<MatrixChat />", () => {
"org.matrix.e2e_cross_signing",
);
await flushPromises();
// logged in
await screen.findByLabelText("User menu");
});
@@ -1210,7 +1191,6 @@ describe("<MatrixChat />", () => {
};
let loginClient!: ReturnType<typeof getMockClientWithEventEmitter>;
const userId = "@alice:server.org";
const deviceId = "test-device-id";
const accessToken = "test-access-token";
const clientLoginResponse = {
@@ -1304,6 +1284,7 @@ describe("<MatrixChat />", () => {
},
);
});
it("should clear storage", async () => {
const localStorageClearSpy = jest.spyOn(localStorage.__proto__, "clear");
@@ -1349,6 +1330,9 @@ describe("<MatrixChat />", () => {
it("should continue to post login setup when no session is found in local storage", async () => {
getComponent({ realQueryParams });
defaultDispatcher.dispatch({
action: "will_start_client",
});
// logged in but waiting for sync screen
await screen.findByText("Logout");
@@ -1604,8 +1588,13 @@ describe("<MatrixChat />", () => {
});
await flushPromises();
mockClient.emit(CryptoEvent.KeyBackupFailed, "error code");
await waitFor(() => expect(spy).toHaveBeenCalledTimes(1));
expect((spy.mock.lastCall![0] as any)._payload._result).toEqual(expect.objectContaining({ __test: true }));
await waitFor(() =>
expect(spy).toHaveBeenCalledWith(
expect.objectContaining({
_payload: expect.objectContaining({ _result: expect.objectContaining({ __test: true }) }),
}),
),
);
});
it("should show the recovery method removed dialog", async () => {
@@ -1622,8 +1611,13 @@ describe("<MatrixChat />", () => {
});
await flushPromises();
mockClient.emit(CryptoEvent.KeyBackupFailed, "error code");
await waitFor(() => expect(spy).toHaveBeenCalledTimes(1));
expect((spy.mock.lastCall![0] as any)._payload._result).toEqual(expect.objectContaining({ __test: true }));
await waitFor(() =>
expect(spy).toHaveBeenCalledWith(
expect.objectContaining({
_payload: expect.objectContaining({ _result: expect.objectContaining({ __test: true }) }),
}),
),
);
});
});
});

View File

@@ -148,6 +148,8 @@ describe("PipContainer", () => {
WidgetStore.instance.addVirtualWidget(call.widget, room.roomId);
WidgetMessagingStore.instance.storeMessaging(widget, room.roomId, {
stop: () => {},
hasCapability: jest.fn(),
feedStateUpdate: jest.fn().mockResolvedValue(undefined),
} as unknown as ClientWidgetApi);
await call.start();
@@ -271,7 +273,10 @@ describe("PipContainer", () => {
Parameters<ClientWidgetApi["transport"]["send"]>
>()
.mockResolvedValue({});
const mockMessaging = { transport: { send: sendSpy }, stop: () => {} } as unknown as ClientWidgetApi;
const mockMessaging = {
transport: { send: sendSpy },
stop: () => {},
} as unknown as ClientWidgetApi;
WidgetMessagingStore.instance.storeMessaging(new Widget(widget), room.roomId, mockMessaging);
await user.click(screen.getByRole("button", { name: "Leave" }));
expect(sendSpy).toHaveBeenCalledWith(ElementWidgetActions.HangupCall, {});

View File

@@ -108,9 +108,7 @@ exports[`MessagePanel should handle lots of membership events quickly 1`] = `
<span
class="mx_TextualEvent mx_GenericEventListSummary_summary"
>
<span>
@user:id made no changes 100 times
</span>
@user:id made no changes 100 times
</span>
</div>
</div>

View File

@@ -197,7 +197,7 @@ describe("<TextualBody />", () => {
const { container } = getComponent({ mxEvent: ev });
const content = container.querySelector(".mx_EventTile_body");
expect(content.innerHTML).toMatchInlineSnapshot(
`"Chat with <bdi><a class="mx_Pill mx_UserPill mx_UserPill_me" href="https://matrix.to/#/@user:example.com"><span aria-label="Profile picture" aria-hidden="true" data-testid="avatar-img" data-type="round" data-color="2" class="_avatar_1qbcf_8 mx_BaseAvatar" style="--cpd-avatar-size: 16px;"><img loading="lazy" alt="" src="mxc://avatar.url/image.png" referrerpolicy="no-referrer" class="_image_1qbcf_41" data-type="round" width="16px" height="16px"></span><span class="mx_Pill_text">Member</span></a></bdi>"`,
`"Chat with <bdi><a class="mx_Pill mx_UserPill mx_UserPill_me" href="https://matrix.to/#/@user:example.com"><span aria-label="Profile picture" aria-hidden="true" data-testid="avatar-img" data-type="round" data-color="2" class="_avatar_1qbcf_8 mx_BaseAvatar" style="--cpd-avatar-size: 16px;"><img loading="lazy" alt="" referrerpolicy="no-referrer" class="_image_1qbcf_41" data-type="round" width="16px" height="16px" src="mxc://avatar.url/image.png"></span><span class="mx_Pill_text">Member</span></a></bdi>"`,
);
});

View File

@@ -510,9 +510,9 @@ exports[`<TextualBody /> renders plain-text m.text correctly linkification get a
</div>
`;
exports[`<TextualBody /> renders plain-text m.text correctly should pillify a permalink to a message in the same room with the label »Message from Member« 1`] = `"Visit <bdi><a class="mx_Pill mx_EventPill" href="https://matrix.to/#/!room1:example.com/%event_id%"><span aria-label="Profile picture" aria-hidden="true" data-testid="avatar-img" data-type="round" data-color="2" class="_avatar_1qbcf_8 mx_BaseAvatar" style="--cpd-avatar-size: 16px;"><img loading="lazy" alt="" src="mxc://avatar.url/image.png" referrerpolicy="no-referrer" class="_image_1qbcf_41" data-type="round" width="16px" height="16px"></span><span class="mx_Pill_text">Message from Member</span></a></bdi>"`;
exports[`<TextualBody /> renders plain-text m.text correctly should pillify a permalink to a message in the same room with the label »Message from Member« 1`] = `"Visit <bdi><a class="mx_Pill mx_EventPill" href="https://matrix.to/#/!room1:example.com/%event_id%"><span aria-label="Profile picture" aria-hidden="true" data-testid="avatar-img" data-type="round" data-color="2" class="_avatar_1qbcf_8 mx_BaseAvatar" style="--cpd-avatar-size: 16px;"><img loading="lazy" alt="" referrerpolicy="no-referrer" class="_image_1qbcf_41" data-type="round" width="16px" height="16px" src="mxc://avatar.url/image.png"></span><span class="mx_Pill_text">Message from Member</span></a></bdi>"`;
exports[`<TextualBody /> renders plain-text m.text correctly should pillify a permalink to an event in another room with the label »Message in Room 2« 1`] = `"Visit <bdi><a class="mx_Pill mx_EventPill" href="https://matrix.to/#/!room2:example.com/%event_id%"><span aria-label="Avatar" aria-hidden="true" data-testid="avatar-img" data-type="round" data-color="2" class="_avatar_1qbcf_8 mx_BaseAvatar" style="--cpd-avatar-size: 16px;"><img loading="lazy" alt="" src="mxc://avatar.url/room.png" referrerpolicy="no-referrer" class="_image_1qbcf_41" data-type="round" width="16px" height="16px"></span><span class="mx_Pill_text">Message in Room 2</span></a></bdi>"`;
exports[`<TextualBody /> renders plain-text m.text correctly should pillify a permalink to an event in another room with the label »Message in Room 2« 1`] = `"Visit <bdi><a class="mx_Pill mx_EventPill" href="https://matrix.to/#/!room2:example.com/%event_id%"><span aria-label="Avatar" aria-hidden="true" data-testid="avatar-img" data-type="round" data-color="2" class="_avatar_1qbcf_8 mx_BaseAvatar" style="--cpd-avatar-size: 16px;"><img loading="lazy" alt="" referrerpolicy="no-referrer" class="_image_1qbcf_41" data-type="round" width="16px" height="16px" src="mxc://avatar.url/room.png"></span><span class="mx_Pill_text">Message in Room 2</span></a></bdi>"`;
exports[`<TextualBody /> renders plain-text m.text correctly should pillify a permalink to an unknown message in the same room with the label »Message« 1`] = `
<div

View File

@@ -91,7 +91,7 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
tabindex="0"
>
<div
aria-labelledby=":rc:"
aria-labelledby=":ra:"
class="mx_PollListItem_content"
>
<span>
@@ -116,7 +116,7 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
tabindex="0"
>
<div
aria-labelledby=":rh:"
aria-labelledby=":rf:"
class="mx_PollListItem_content"
>
<span>

View File

@@ -467,7 +467,7 @@ describe("<UserInfo />", () => {
await expect(screen.findByRole("button", { name: "Deactivate user" })).resolves.toBeInTheDocument();
if (screen.queryAllByRole("progressbar").length) {
await waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar"));
await act(() => waitForElementToBeRemoved(() => screen.queryAllByRole("progressbar")));
}
expect(container).toMatchSnapshot();
});

View File

@@ -19,7 +19,7 @@ exports[`<UserInfo /> with crypto enabled renders <BasicUserInfo /> 1`] = `
</p>
</div>
<button
aria-labelledby=":r6m:"
aria-labelledby=":r6i:"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button"
role="button"
@@ -305,7 +305,7 @@ exports[`<UserInfo /> with crypto enabled should render a deactivate button for
</p>
</div>
<button
aria-labelledby=":r70:"
aria-labelledby=":r6s:"
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
data-testid="base-card-close-button"
role="button"
@@ -401,21 +401,13 @@ exports[`<UserInfo /> with crypto enabled should render a deactivate button for
class="mx_Flex mx_UserInfo_verification"
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: center; --mx-flex-gap: 0; --mx-flex-wrap: nowrap;"
>
<svg
class="_icon_11k6c_18"
fill="currentColor"
height="1em"
style="width: 24px; height: 24px;"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
<p
class="_typography_6v6n8_153 _font-body-sm-regular_6v6n8_31 mx_UserInfo_verification_unavailable"
>
<path
clip-rule="evenodd"
d="M12 4.031a8 8 0 1 0 8 8 1 1 0 0 1 2 0c0 5.523-4.477 10-10 10s-10-4.477-10-10 4.477-10 10-10a1 1 0 1 1 0 2"
fill-rule="evenodd"
/>
</svg>
(
User verification unavailable
)
</p>
</div>
</div>
<div

View File

@@ -55,7 +55,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
style="--cpd-icon-button-size: 100%; --cpd-color-icon-tertiary: var(--cpd-color-icon-disabled);"
>
<svg
aria-labelledby=":r166:"
aria-labelledby=":r15i:"
fill="currentColor"
height="1em"
viewBox="0 0 24 24"
@@ -71,7 +71,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
<button
aria-disabled="true"
aria-label="There's no one here to call"
aria-labelledby=":r16b:"
aria-labelledby=":r15n:"
class="_icon-button_m2erp_8"
role="button"
style="--cpd-icon-button-size: 32px;"
@@ -96,7 +96,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
</button>
<button
aria-label="Threads"
aria-labelledby=":r16g:"
aria-labelledby=":r15s:"
class="_icon-button_m2erp_8"
role="button"
style="--cpd-icon-button-size: 32px;"
@@ -122,7 +122,7 @@ exports[`RoomHeader dm does not show the face pile for DMs 1`] = `
</button>
<button
aria-label="Room info"
aria-labelledby=":r16l:"
aria-labelledby=":r161:"
class="_icon-button_m2erp_8"
role="button"
style="--cpd-icon-button-size: 32px;"

View File

@@ -84,12 +84,12 @@ describe("<AddPrivilegedUsers />", () => {
// Find some suggestions and select them.
const autocompleteInput = getByTestId("autocomplete-input");
act(() => {
await act(async () => {
fireEvent.focus(autocompleteInput);
fireEvent.change(autocompleteInput, { target: { value: "u" } });
await waitFor(() => expect(provider.mock.instances[0].getCompletions).toHaveBeenCalledTimes(1));
});
await waitFor(() => expect(provider.mock.instances[0].getCompletions).toHaveBeenCalledTimes(1));
const matchOne = getByTestId("autocomplete-suggestion-item-@user_1:host.local");
const matchTwo = getByTestId("autocomplete-suggestion-item-@user_2:host.local");

View File

@@ -41,6 +41,7 @@ import {
flushPromises,
getMockClientWithEventEmitter,
mkPusher,
mockClientMethodsCrypto,
mockClientMethodsServer,
mockClientMethodsUser,
mockPlatformPeg,
@@ -124,10 +125,11 @@ describe("<SessionManagerTab />", () => {
const mockCrypto = mocked({
getDeviceVerificationStatus: jest.fn(),
getUserDeviceInfo: jest.fn(),
getUserDeviceInfo: jest.fn().mockResolvedValue(new Map()),
requestDeviceVerification: jest.fn().mockResolvedValue(mockVerificationRequest),
supportsSecretsForQrLogin: jest.fn().mockReturnValue(false),
isCrossSigningReady: jest.fn().mockReturnValue(true),
getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]),
} as unknown as CryptoApi);
let mockClient!: MockedObject<MatrixClient>;
@@ -203,6 +205,7 @@ describe("<SessionManagerTab />", () => {
mockClient = getMockClientWithEventEmitter({
...mockClientMethodsUser(aliceId),
...mockClientMethodsServer(),
...mockClientMethodsCrypto(),
getCrypto: jest.fn().mockReturnValue(mockCrypto),
getDevices: jest.fn(),
getDeviceId: jest.fn().mockReturnValue(deviceId),

View File

@@ -224,7 +224,7 @@ exports[`ThreadsActivityCentre should close the release announcement when the TA
<div
data-radix-popper-content-wrapper=""
dir="ltr"
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;"
style="position: fixed; left: 0px; top: 0px; transform: translate(0px, -8px); min-width: max-content; --radix-popper-transform-origin: 0% 0px; --radix-popper-available-width: 0px; --radix-popper-available-height: -8px; --radix-popper-anchor-width: 0px; --radix-popper-anchor-height: 0px;"
>
<div
aria-labelledby="radix-:r1c:"

View File

@@ -1,48 +1,72 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FormattingUtils formatList should return expected sentence in ReactNode when given 2 React children 1`] = `
<span>
<span>
a
</span>
and
<span>
b
</span>
</span>
<React.Fragment>
<React.Fragment>
<span>
a
</span>
</React.Fragment>
<React.Fragment>
and
</React.Fragment>
<React.Fragment>
<span>
b
</span>
</React.Fragment>
</React.Fragment>
`;
exports[`FormattingUtils formatList should return expected sentence in ReactNode when given more React children 1`] = `
<span>
<span>
a
</span>
,
<span>
b
</span>
,
<span>
c
</span>
and
<span>
d
</span>
</span>
<React.Fragment>
<React.Fragment>
<span>
a
</span>
</React.Fragment>
<React.Fragment>
,
</React.Fragment>
<React.Fragment>
<span>
b
</span>
</React.Fragment>
<React.Fragment>
,
</React.Fragment>
<React.Fragment>
<span>
c
</span>
</React.Fragment>
<React.Fragment>
and
</React.Fragment>
<React.Fragment>
<span>
d
</span>
</React.Fragment>
</React.Fragment>
`;
exports[`FormattingUtils formatList should return expected sentence in ReactNode when using itemLimit 1`] = `
<span>
<span>
<span>
a
</span>
,
<span>
b
</span>
</span>
<React.Fragment>
<React.Fragment>
<span>
a
</span>
,
</React.Fragment>
<React.Fragment>
<span>
b
</span>
</React.Fragment>
</React.Fragment>
and 2 others
</span>
`;

View File

@@ -253,8 +253,9 @@ describe("export", function () {
},
setProgressText,
);
const imageRegex = /<img.+ src="mxc:\/\/test.org" alt="image\.png"\/?>/;
expect(imageRegex.test(renderToString(exporter.getEventTile(mkImageEvent(), true)))).toBeTruthy();
expect(renderToString(exporter.getEventTile(mkImageEvent(), true))).toMatch(
/<img.+ alt="image\.png" src="mxc:\/\/test.org"\/?>/,
);
});
const invalidExportOptions: [string, IExportOptions][] = [

File diff suppressed because one or more lines are too long

View File

@@ -116,7 +116,7 @@ describe("Permalinks", function () {
it("should gracefully handle invalid MXIDs", () => {
const roomId = "!fake:example.org";
const alice50 = makeMemberWithPL(roomId, "@alice:pl_50:org", 50);
const alice50 = makeMemberWithPL(roomId, "@alice:pl-50:org", 50);
const room = mockRoom(roomId, [alice50]);
const creator = new RoomPermalinkCreator(room);
creator.load();