Show a "progress" dialog while invites are being sent (#30561)
* InviteDialog: show some words and a spinner while invites are being sent * MultiInviter-test: avoid building unhandled rejected promises If we don't handle rejected promises, jest gets confused by them. Instead, let's create them on-demand. * Open a "progress" dialog while invites are being sent * Inhibit invite progress dialog when RoomUpgradeWarning dialog is kept open ... otherwise the `RoomUpgradeWarning` dialog disappears during the invites, and the tests that assert that it is showing the correct thing fail. enter the commit message for your changes. Lines starting * Switch to compound CSS variables instead of old pcss vars * update playwright screenshots * Revert "update playwright screenshots" This reverts commit b0a15d97f35a088fe5b67009085eab46be1316fd. * Another go at updating screenshots * Address review comments * remove redundant Props
This commit is contained in:
committed by
GitHub
parent
c842b615db
commit
e8c88918cb
@@ -137,6 +137,7 @@ describe("InviteDialog", () => {
|
||||
supportsThreads: jest.fn().mockReturnValue(false),
|
||||
isInitialSyncComplete: jest.fn().mockReturnValue(true),
|
||||
getClientWellKnown: jest.fn().mockResolvedValue({}),
|
||||
invite: jest.fn(),
|
||||
});
|
||||
SdkConfig.put({ validated_server_config: {} as ValidatedServerConfig } as IConfigOptions);
|
||||
DMRoomMap.makeShared(mockClient);
|
||||
@@ -406,6 +407,18 @@ describe("InviteDialog", () => {
|
||||
expect(tile).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("while the invite is in progress", () => {
|
||||
it("should show a spinner", async () => {
|
||||
mockClient.invite.mockReturnValue(new Promise(() => {}));
|
||||
|
||||
render(<InviteDialog kind={InviteKind.Invite} roomId={roomId} onFinished={jest.fn()} />);
|
||||
await enterIntoSearchField(bobId);
|
||||
await userEvent.click(screen.getByRole("button", { name: "Invite" }));
|
||||
|
||||
await screen.findByText("Preparing invitations...");
|
||||
});
|
||||
});
|
||||
|
||||
describe("when inviting a user with an unknown profile", () => {
|
||||
beforeEach(async () => {
|
||||
render(<InviteDialog kind={InviteKind.Dm} onFinished={jest.fn()} />);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import InviteProgressBody from "../../../../../src/components/views/dialogs/InviteProgressBody.tsx";
|
||||
|
||||
describe("InviteProgressBody", () => {
|
||||
it("should match snapshot", () => {
|
||||
const { asFragment } = render(<InviteProgressBody />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`InviteProgressBody should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_InviteProgressBody"
|
||||
>
|
||||
<div
|
||||
class="mx_InlineSpinner"
|
||||
>
|
||||
<div
|
||||
aria-label="Loading…"
|
||||
class="mx_InlineSpinner_icon mx_Spinner_icon"
|
||||
style="width: 32px; height: 32px;"
|
||||
/>
|
||||
</div>
|
||||
<h1>
|
||||
Preparing invitations...
|
||||
</h1>
|
||||
Do not close the app until finished.
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
@@ -15,7 +15,7 @@ import Modal, { type ComponentType, type ComponentProps } from "../../../src/Mod
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import MultiInviter, { type CompletionStates } from "../../../src/utils/MultiInviter";
|
||||
import * as TestUtilsMatrix from "../../test-utils";
|
||||
import type AskInviteAnywayDialog from "../../../src/components/views/dialogs/AskInviteAnywayDialog";
|
||||
import AskInviteAnywayDialog from "../../../src/components/views/dialogs/AskInviteAnywayDialog";
|
||||
import ConfirmUserActionDialog from "../../../src/components/views/dialogs/ConfirmUserActionDialog";
|
||||
|
||||
const ROOMID = "!room:server";
|
||||
@@ -24,10 +24,14 @@ const MXID1 = "@user1:server";
|
||||
const MXID2 = "@user2:server";
|
||||
const MXID3 = "@user3:server";
|
||||
|
||||
const MXID_PROFILE_STATES: Record<string, Promise<any>> = {
|
||||
[MXID1]: Promise.resolve({}),
|
||||
[MXID2]: Promise.reject(new MatrixError({ errcode: "M_FORBIDDEN" })),
|
||||
[MXID3]: Promise.reject(new MatrixError({ errcode: "M_NOT_FOUND" })),
|
||||
const MXID_PROFILE_STATES: Record<string, () => {}> = {
|
||||
[MXID1]: () => ({}),
|
||||
[MXID2]: () => {
|
||||
throw new MatrixError({ errcode: "M_FORBIDDEN" });
|
||||
},
|
||||
[MXID3]: () => {
|
||||
throw new MatrixError({ errcode: "M_NOT_FOUND" });
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock("../../../src/Modal", () => ({
|
||||
@@ -51,11 +55,12 @@ const mockPromptBeforeInviteUnknownUsers = (value: boolean) => {
|
||||
};
|
||||
|
||||
const mockCreateTrackedDialog = (callbackName: "onInviteAnyways" | "onGiveUp") => {
|
||||
mocked(Modal.createDialog).mockImplementation(
|
||||
(Element: ComponentType, props?: ComponentProps<ComponentType>): any => {
|
||||
mocked(Modal.createDialog).mockImplementation((Element: ComponentType, props?: ComponentProps<ComponentType>) => {
|
||||
if (Element === AskInviteAnywayDialog) {
|
||||
(props as ComponentProps<typeof AskInviteAnywayDialog>)[callbackName]();
|
||||
},
|
||||
);
|
||||
}
|
||||
return { close: jest.fn(), finished: new Promise(() => {}) };
|
||||
});
|
||||
};
|
||||
|
||||
const expectAllInvitedResult = (result: CompletionStates) => {
|
||||
@@ -72,6 +77,7 @@ describe("MultiInviter", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
mocked(Modal.createDialog).mockReturnValue({ close: jest.fn(), finished: new Promise(() => {}) });
|
||||
|
||||
TestUtilsMatrix.stubClient();
|
||||
client = MatrixClientPeg.safeGet() as jest.Mocked<MatrixClient>;
|
||||
@@ -80,8 +86,10 @@ describe("MultiInviter", () => {
|
||||
client.invite.mockResolvedValue({});
|
||||
|
||||
client.getProfileInfo = jest.fn();
|
||||
client.getProfileInfo.mockImplementation((userId: string) => {
|
||||
return MXID_PROFILE_STATES[userId] || Promise.reject();
|
||||
client.getProfileInfo.mockImplementation(async (userId: string) => {
|
||||
const m = MXID_PROFILE_STATES[userId];
|
||||
if (m) return m();
|
||||
throw new Error();
|
||||
});
|
||||
client.unban = jest.fn();
|
||||
|
||||
@@ -89,6 +97,22 @@ describe("MultiInviter", () => {
|
||||
});
|
||||
|
||||
describe("invite", () => {
|
||||
it("should show a progress dialog while the invite happens", async () => {
|
||||
const mockModalHandle = { close: jest.fn(), finished: new Promise<[]>(() => {}) };
|
||||
mocked(Modal.createDialog).mockReturnValue(mockModalHandle);
|
||||
|
||||
const invitePromise = Promise.withResolvers<{}>();
|
||||
client.invite.mockReturnValue(invitePromise.promise);
|
||||
|
||||
const resultPromise = inviter.invite([MXID1]);
|
||||
expect(Modal.createDialog).toHaveBeenCalledTimes(1);
|
||||
expect(mockModalHandle.close).not.toHaveBeenCalled();
|
||||
|
||||
invitePromise.resolve({});
|
||||
await resultPromise;
|
||||
expect(mockModalHandle.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("with promptBeforeInviteUnknownUsers = false", () => {
|
||||
beforeEach(() => mockPromptBeforeInviteUnknownUsers(false));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user