Properly type Modal props to ensure useful typescript checking (#10238
* Properly type Modal props to ensure useful typescript checking * delint * Iterate * Iterate * Fix modal.close loop * Iterate * Fix tests * Add comment * Fix test
This commit is contained in:
parent
ae5725b24c
commit
629e5cb01f
124 changed files with 600 additions and 560 deletions
|
@ -21,7 +21,7 @@ import { RoomType } from "matrix-js-sdk/src/@types/event";
|
|||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import InviteDialog from "../../../../src/components/views/dialogs/InviteDialog";
|
||||
import { KIND_DM, KIND_INVITE } from "../../../../src/components/views/dialogs/InviteDialogTypes";
|
||||
import { InviteKind } from "../../../../src/components/views/dialogs/InviteDialogTypes";
|
||||
import { getMockClientWithEventEmitter, mkMembership, mkMessage, mkRoomCreateEvent } from "../../../test-utils";
|
||||
import DMRoomMap from "../../../../src/utils/DMRoomMap";
|
||||
import SdkConfig from "../../../../src/SdkConfig";
|
||||
|
@ -109,20 +109,20 @@ describe("InviteDialog", () => {
|
|||
room.isSpaceRoom = jest.fn().mockReturnValue(true);
|
||||
room.getType = jest.fn().mockReturnValue(RoomType.Space);
|
||||
room.name = "Space";
|
||||
render(<InviteDialog kind={KIND_INVITE} roomId={roomId} onFinished={jest.fn()} />);
|
||||
render(<InviteDialog kind={InviteKind.Invite} roomId={roomId} onFinished={jest.fn()} />);
|
||||
|
||||
expect(screen.queryByText("Invite to Space")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should label with room name", () => {
|
||||
render(<InviteDialog kind={KIND_INVITE} roomId={roomId} onFinished={jest.fn()} />);
|
||||
render(<InviteDialog kind={InviteKind.Invite} roomId={roomId} onFinished={jest.fn()} />);
|
||||
expect(screen.getByText(`Invite to ${roomId}`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should suggest valid MXIDs even if unknown", async () => {
|
||||
render(
|
||||
<InviteDialog
|
||||
kind={KIND_INVITE}
|
||||
kind={InviteKind.Invite}
|
||||
roomId={roomId}
|
||||
onFinished={jest.fn()}
|
||||
initialText="@localpart:server.tld"
|
||||
|
@ -135,7 +135,7 @@ describe("InviteDialog", () => {
|
|||
it("should not suggest invalid MXIDs", () => {
|
||||
render(
|
||||
<InviteDialog
|
||||
kind={KIND_INVITE}
|
||||
kind={InviteKind.Invite}
|
||||
roomId={roomId}
|
||||
onFinished={jest.fn()}
|
||||
initialText="@localpart:server:tld"
|
||||
|
@ -145,9 +145,9 @@ describe("InviteDialog", () => {
|
|||
expect(screen.queryByText("@localpart:server:tld")).toBeFalsy();
|
||||
});
|
||||
|
||||
it.each([[KIND_DM], [KIND_INVITE]] as [typeof KIND_DM | typeof KIND_INVITE][])(
|
||||
it.each([[InviteKind.Dm], [InviteKind.Invite]] as [typeof InviteKind.Dm | typeof InviteKind.Invite][])(
|
||||
"should lookup inputs which look like email addresses (%s)",
|
||||
async (kind: typeof KIND_DM | typeof KIND_INVITE) => {
|
||||
async (kind: typeof InviteKind.Dm | typeof InviteKind.Invite) => {
|
||||
mockClient.getIdentityServerUrl.mockReturnValue("https://identity-server");
|
||||
mockClient.lookupThreePid.mockResolvedValue({
|
||||
address: aliceEmail,
|
||||
|
@ -162,7 +162,7 @@ describe("InviteDialog", () => {
|
|||
render(
|
||||
<InviteDialog
|
||||
kind={kind}
|
||||
roomId={kind === KIND_INVITE ? roomId : ""}
|
||||
roomId={kind === InviteKind.Invite ? roomId : ""}
|
||||
onFinished={jest.fn()}
|
||||
initialText={aliceEmail}
|
||||
/>,
|
||||
|
@ -182,7 +182,12 @@ describe("InviteDialog", () => {
|
|||
mockClient.lookupThreePid.mockResolvedValue({});
|
||||
|
||||
render(
|
||||
<InviteDialog kind={KIND_INVITE} roomId={roomId} onFinished={jest.fn()} initialText="foobar@email.com" />,
|
||||
<InviteDialog
|
||||
kind={InviteKind.Invite}
|
||||
roomId={roomId}
|
||||
onFinished={jest.fn()}
|
||||
initialText="foobar@email.com"
|
||||
/>,
|
||||
);
|
||||
|
||||
await screen.findByText("foobar@email.com");
|
||||
|
@ -193,7 +198,7 @@ describe("InviteDialog", () => {
|
|||
mockClient.getIdentityServerUrl.mockReturnValue("https://identity-server");
|
||||
mockClient.lookupThreePid.mockResolvedValue({});
|
||||
|
||||
render(<InviteDialog kind={KIND_INVITE} roomId={roomId} onFinished={jest.fn()} />);
|
||||
render(<InviteDialog kind={InviteKind.Invite} roomId={roomId} onFinished={jest.fn()} />);
|
||||
|
||||
const input = screen.getByTestId("invite-dialog-input");
|
||||
input.focus();
|
||||
|
|
|
@ -22,7 +22,6 @@ import SettingsStore, { CallbackFn } from "../../../../src/settings/SettingsStor
|
|||
import SdkConfig from "../../../../src/SdkConfig";
|
||||
import { UserTab } from "../../../../src/components/views/dialogs/UserTab";
|
||||
import UserSettingsDialog from "../../../../src/components/views/dialogs/UserSettingsDialog";
|
||||
import { IDialogProps } from "../../../../src/components/views/dialogs/IDialogProps";
|
||||
import {
|
||||
getMockClientWithEventEmitter,
|
||||
mockClientMethodsUser,
|
||||
|
@ -62,7 +61,7 @@ describe("<UserSettingsDialog />", () => {
|
|||
});
|
||||
|
||||
const defaultProps = { onFinished: jest.fn() };
|
||||
const getComponent = (props: Partial<IDialogProps & { initialTabId?: UserTab }> = {}): ReactElement => (
|
||||
const getComponent = (props: Partial<typeof defaultProps & { initialTabId?: UserTab }> = {}): ReactElement => (
|
||||
<UserSettingsDialog {...defaultProps} {...props} />
|
||||
);
|
||||
|
||||
|
|
|
@ -21,13 +21,13 @@ import { mocked } from "jest-mock";
|
|||
import { Room, User, MatrixClient, RoomMember, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import { Phase, VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
||||
import { DeviceTrustLevel, UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
|
||||
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
|
||||
|
||||
import UserInfo, {
|
||||
BanToggleButton,
|
||||
DeviceItem,
|
||||
disambiguateDevices,
|
||||
getPowerLevels,
|
||||
IDevice,
|
||||
isMuted,
|
||||
PowerLevelEditor,
|
||||
RoomAdminToolsContainer,
|
||||
|
@ -80,6 +80,22 @@ const mockRoom = mocked({
|
|||
getEventReadUpTo: jest.fn(),
|
||||
} as unknown as Room);
|
||||
|
||||
const mockSpace = mocked({
|
||||
roomId: "!fkfk",
|
||||
getType: jest.fn().mockReturnValue("m.space"),
|
||||
isSpaceRoom: jest.fn().mockReturnValue(true),
|
||||
getMember: jest.fn().mockReturnValue(undefined),
|
||||
getMxcAvatarUrl: jest.fn().mockReturnValue("mock-avatar-url"),
|
||||
name: "test room",
|
||||
on: jest.fn(),
|
||||
off: jest.fn(),
|
||||
currentState: {
|
||||
getStateEvents: jest.fn(),
|
||||
on: jest.fn(),
|
||||
},
|
||||
getEventReadUpTo: jest.fn(),
|
||||
} as unknown as Room);
|
||||
|
||||
const mockClient = mocked({
|
||||
getUser: jest.fn(),
|
||||
isGuest: jest.fn().mockReturnValue(false),
|
||||
|
@ -258,7 +274,7 @@ describe("<UserInfoHeader />", () => {
|
|||
});
|
||||
|
||||
describe("<DeviceItem />", () => {
|
||||
const device: IDevice = { deviceId: "deviceId", getDisplayName: () => "deviceName" };
|
||||
const device = { deviceId: "deviceId", getDisplayName: () => "deviceName" } as DeviceInfo;
|
||||
const defaultProps = {
|
||||
userId: defaultUserId,
|
||||
device,
|
||||
|
@ -722,14 +738,14 @@ describe("<RoomKickButton />", () => {
|
|||
it("clicking the kick button calls Modal.createDialog with the correct arguments", async () => {
|
||||
createDialogSpy.mockReturnValueOnce({ finished: Promise.resolve([]), close: jest.fn() });
|
||||
|
||||
renderComponent({ member: memberWithInviteMembership });
|
||||
renderComponent({ room: mockSpace, member: memberWithInviteMembership });
|
||||
await userEvent.click(screen.getByText(/disinvite from/i));
|
||||
|
||||
// check the last call arguments and the presence of the spaceChildFilter callback
|
||||
expect(createDialogSpy).toHaveBeenLastCalledWith(
|
||||
expect.any(Function),
|
||||
expect.objectContaining({ spaceChildFilter: expect.any(Function) }),
|
||||
undefined,
|
||||
"mx_ConfirmSpaceUserActionDialog_wrapper",
|
||||
);
|
||||
|
||||
// test the spaceChildFilter callback
|
||||
|
@ -806,14 +822,14 @@ describe("<BanToggleButton />", () => {
|
|||
it("clicking the ban or unban button calls Modal.createDialog with the correct arguments if user is not banned", async () => {
|
||||
createDialogSpy.mockReturnValueOnce({ finished: Promise.resolve([]), close: jest.fn() });
|
||||
|
||||
renderComponent();
|
||||
renderComponent({ room: mockSpace });
|
||||
await userEvent.click(screen.getByText(/ban from/i));
|
||||
|
||||
// check the last call arguments and the presence of the spaceChildFilter callback
|
||||
expect(createDialogSpy).toHaveBeenLastCalledWith(
|
||||
expect.any(Function),
|
||||
expect.objectContaining({ spaceChildFilter: expect.any(Function) }),
|
||||
undefined,
|
||||
"mx_ConfirmSpaceUserActionDialog_wrapper",
|
||||
);
|
||||
|
||||
// test the spaceChildFilter callback
|
||||
|
@ -844,14 +860,14 @@ describe("<BanToggleButton />", () => {
|
|||
it("clicking the ban or unban button calls Modal.createDialog with the correct arguments if user _is_ banned", async () => {
|
||||
createDialogSpy.mockReturnValueOnce({ finished: Promise.resolve([]), close: jest.fn() });
|
||||
|
||||
renderComponent({ member: memberWithBanMembership });
|
||||
renderComponent({ room: mockSpace, member: memberWithBanMembership });
|
||||
await userEvent.click(screen.getByText(/ban from/i));
|
||||
|
||||
// check the last call arguments and the presence of the spaceChildFilter callback
|
||||
expect(createDialogSpy).toHaveBeenLastCalledWith(
|
||||
expect.any(Function),
|
||||
expect.objectContaining({ spaceChildFilter: expect.any(Function) }),
|
||||
undefined,
|
||||
"mx_ConfirmSpaceUserActionDialog_wrapper",
|
||||
);
|
||||
|
||||
// test the spaceChildFilter callback
|
||||
|
@ -955,9 +971,9 @@ describe("<RoomAdminToolsContainer />", () => {
|
|||
describe("disambiguateDevices", () => {
|
||||
it("does not add ambiguous key to unique names", () => {
|
||||
const initialDevices = [
|
||||
{ deviceId: "id1", getDisplayName: () => "name1" },
|
||||
{ deviceId: "id2", getDisplayName: () => "name2" },
|
||||
{ deviceId: "id3", getDisplayName: () => "name3" },
|
||||
{ deviceId: "id1", getDisplayName: () => "name1" } as DeviceInfo,
|
||||
{ deviceId: "id2", getDisplayName: () => "name2" } as DeviceInfo,
|
||||
{ deviceId: "id3", getDisplayName: () => "name3" } as DeviceInfo,
|
||||
];
|
||||
disambiguateDevices(initialDevices);
|
||||
|
||||
|
@ -969,14 +985,14 @@ describe("disambiguateDevices", () => {
|
|||
|
||||
it("adds ambiguous key to all ids with non-unique names", () => {
|
||||
const uniqueNameDevices = [
|
||||
{ deviceId: "id3", getDisplayName: () => "name3" },
|
||||
{ deviceId: "id4", getDisplayName: () => "name4" },
|
||||
{ deviceId: "id6", getDisplayName: () => "name6" },
|
||||
{ deviceId: "id3", getDisplayName: () => "name3" } as DeviceInfo,
|
||||
{ deviceId: "id4", getDisplayName: () => "name4" } as DeviceInfo,
|
||||
{ deviceId: "id6", getDisplayName: () => "name6" } as DeviceInfo,
|
||||
];
|
||||
const nonUniqueNameDevices = [
|
||||
{ deviceId: "id1", getDisplayName: () => "nonUnique" },
|
||||
{ deviceId: "id2", getDisplayName: () => "nonUnique" },
|
||||
{ deviceId: "id5", getDisplayName: () => "nonUnique" },
|
||||
{ deviceId: "id1", getDisplayName: () => "nonUnique" } as DeviceInfo,
|
||||
{ deviceId: "id2", getDisplayName: () => "nonUnique" } as DeviceInfo,
|
||||
{ deviceId: "id5", getDisplayName: () => "nonUnique" } as DeviceInfo,
|
||||
];
|
||||
const initialDevices = [...uniqueNameDevices, ...nonUniqueNameDevices];
|
||||
disambiguateDevices(initialDevices);
|
||||
|
|
|
@ -38,12 +38,12 @@ describe("LinkModal", () => {
|
|||
isForward: true,
|
||||
};
|
||||
|
||||
const customRender = (isTextEnabled: boolean, onClose: () => void, isEditing = false) => {
|
||||
const customRender = (isTextEnabled: boolean, onFinished: () => void, isEditing = false) => {
|
||||
return render(
|
||||
<LinkModal
|
||||
composer={formattingFunctions}
|
||||
isTextEnabled={isTextEnabled}
|
||||
onClose={onClose}
|
||||
onFinished={onFinished}
|
||||
composerContext={{ selection: defaultValue }}
|
||||
isEditing={isEditing}
|
||||
/>,
|
||||
|
@ -60,8 +60,8 @@ describe("LinkModal", () => {
|
|||
|
||||
it("Should create a link", async () => {
|
||||
// When
|
||||
const onClose = jest.fn();
|
||||
customRender(false, onClose);
|
||||
const onFinished = jest.fn();
|
||||
customRender(false, onFinished);
|
||||
|
||||
// Then
|
||||
expect(screen.getByLabelText("Link")).toBeTruthy();
|
||||
|
@ -84,7 +84,7 @@ describe("LinkModal", () => {
|
|||
// Then
|
||||
await waitFor(() => {
|
||||
expect(selectionSpy).toHaveBeenCalledWith(defaultValue);
|
||||
expect(onClose).toBeCalledTimes(1);
|
||||
expect(onFinished).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
// Then
|
||||
|
@ -93,8 +93,8 @@ describe("LinkModal", () => {
|
|||
|
||||
it("Should create a link with text", async () => {
|
||||
// When
|
||||
const onClose = jest.fn();
|
||||
customRender(true, onClose);
|
||||
const onFinished = jest.fn();
|
||||
customRender(true, onFinished);
|
||||
|
||||
// Then
|
||||
expect(screen.getByLabelText("Text")).toBeTruthy();
|
||||
|
@ -127,7 +127,7 @@ describe("LinkModal", () => {
|
|||
// Then
|
||||
await waitFor(() => {
|
||||
expect(selectionSpy).toHaveBeenCalledWith(defaultValue);
|
||||
expect(onClose).toBeCalledTimes(1);
|
||||
expect(onFinished).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
// Then
|
||||
|
@ -136,13 +136,13 @@ describe("LinkModal", () => {
|
|||
|
||||
it("Should remove the link", async () => {
|
||||
// When
|
||||
const onClose = jest.fn();
|
||||
customRender(true, onClose, true);
|
||||
const onFinished = jest.fn();
|
||||
customRender(true, onFinished, true);
|
||||
await userEvent.click(screen.getByText("Remove"));
|
||||
|
||||
// Then
|
||||
expect(formattingFunctions.removeLinks).toHaveBeenCalledTimes(1);
|
||||
expect(onClose).toBeCalledTimes(1);
|
||||
expect(onFinished).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it("Should display the link in editing", async () => {
|
||||
|
|
|
@ -28,7 +28,7 @@ describe("deleteDevices()", () => {
|
|||
deleteMultipleDevices: jest.fn(),
|
||||
});
|
||||
|
||||
const modalSpy = jest.spyOn(Modal, "createDialog");
|
||||
const modalSpy = jest.spyOn(Modal, "createDialog") as jest.SpyInstance;
|
||||
|
||||
const interactiveAuthError = { httpStatus: 401, data: { flows: [] as UIAFlow[] } };
|
||||
|
||||
|
|
|
@ -922,7 +922,7 @@ describe("ElementCall", () => {
|
|||
const sourceId = "source_id";
|
||||
jest.spyOn(Modal, "createDialog").mockReturnValue({
|
||||
finished: new Promise((r) => r([sourceId])),
|
||||
} as IHandle<any[]>);
|
||||
} as IHandle<any>);
|
||||
jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(true);
|
||||
|
||||
await call.connect();
|
||||
|
@ -950,7 +950,7 @@ describe("ElementCall", () => {
|
|||
it("sends ScreenshareStop if we couldn't get a source id", async () => {
|
||||
jest.spyOn(Modal, "createDialog").mockReturnValue({
|
||||
finished: new Promise((r) => r([null])),
|
||||
} as IHandle<any[]>);
|
||||
} as IHandle<any>);
|
||||
jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(true);
|
||||
|
||||
await call.connect();
|
||||
|
|
|
@ -18,10 +18,11 @@ import { mocked } from "jest-mock";
|
|||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
import Modal, { ModalManager } from "../../src/Modal";
|
||||
import Modal, { ComponentType, ComponentProps } from "../../src/Modal";
|
||||
import SettingsStore from "../../src/settings/SettingsStore";
|
||||
import MultiInviter, { CompletionStates } from "../../src/utils/MultiInviter";
|
||||
import * as TestUtilsMatrix from "../test-utils";
|
||||
import AskInviteAnywayDialog from "../../src/components/views/dialogs/AskInviteAnywayDialog";
|
||||
|
||||
const ROOMID = "!room:server";
|
||||
|
||||
|
@ -56,9 +57,11 @@ const mockPromptBeforeInviteUnknownUsers = (value: boolean) => {
|
|||
};
|
||||
|
||||
const mockCreateTrackedDialog = (callbackName: "onInviteAnyways" | "onGiveUp") => {
|
||||
mocked(Modal.createDialog).mockImplementation((...rest: Parameters<ModalManager["createDialog"]>): any => {
|
||||
rest[1]![callbackName]();
|
||||
});
|
||||
mocked(Modal.createDialog).mockImplementation(
|
||||
(Element: ComponentType, props?: ComponentProps<ComponentType>): any => {
|
||||
(props as ComponentProps<typeof AskInviteAnywayDialog>)[callbackName]();
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const expectAllInvitedResult = (result: CompletionStates) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue