Skip to content

Commit 1cb200b

Browse files
committed
Add unit tests
1 parent 19001fb commit 1cb200b

File tree

2 files changed

+146
-2
lines changed

2 files changed

+146
-2
lines changed

apps/web/test/unit-tests/components/views/dialogs/InviteDialog-test.tsx

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ Please see LICENSE files in the repository root for full details.
77
*/
88

99
import React from "react";
10-
import { fireEvent, render, screen, findByText } from "jest-matrix-react";
10+
import { findByText, fireEvent, render, screen } from "jest-matrix-react";
1111
import userEvent from "@testing-library/user-event";
12-
import { RoomType, type MatrixClient, MatrixError, Room } from "matrix-js-sdk/src/matrix";
12+
import { type MatrixClient, MatrixError, Room, RoomType } from "matrix-js-sdk/src/matrix";
1313
import { KnownMembership } from "matrix-js-sdk/src/types";
1414
import { sleep } from "matrix-js-sdk/src/utils";
1515
import { mocked, type Mocked } from "jest-mock";
@@ -455,4 +455,44 @@ describe("InviteDialog", () => {
455455
await flushPromises();
456456
expect(screen.queryByText("@localpart:server.tld")).not.toBeInTheDocument();
457457
});
458+
459+
describe("when inviting a user whose cryptographic identity we do not know", () => {
460+
beforeEach(() => {
461+
mocked(mockClient.getCrypto()!.getUserVerificationStatus).mockImplementation(async (u) => {
462+
return new UserVerificationStatus(false, false, false, false);
463+
});
464+
});
465+
466+
describe.each([InviteKind.Invite, InviteKind.Dm])("with invitekind '%s'", (kind) => {
467+
const goButtonName = kind == InviteKind.Invite ? "Invite" : "Go";
468+
469+
beforeEach(() => {
470+
render(
471+
<InviteDialog
472+
kind={kind as InviteKind.Invite | InviteKind.Dm}
473+
roomId={roomId}
474+
onFinished={jest.fn()}
475+
/>,
476+
);
477+
});
478+
479+
it("should show a warning when inviting by user id", async () => {
480+
await enterIntoSearchField(aliceId);
481+
await userEvent.click(screen.getByRole("button", { name: goButtonName }));
482+
await screen.findByText("Confirm inviting them before continuing", { exact: false });
483+
484+
expect(mocked(mockClient.getCrypto()!.getUserVerificationStatus)).toHaveBeenCalledTimes(1);
485+
expect(mocked(mockClient.getCrypto()!.getUserVerificationStatus)).toHaveBeenCalledWith(aliceId);
486+
});
487+
488+
it("should show a warning when inviting by email address", async () => {
489+
await enterIntoSearchField("aaa@bbb");
490+
await userEvent.click(screen.getByRole("button", { name: goButtonName }));
491+
await screen.findByText("Confirm inviting them before continuing", { exact: false });
492+
493+
// We shouldn't call getUserVerificationStatus on an email address
494+
expect(mocked(mockClient.getCrypto()!.getUserVerificationStatus)).not.toHaveBeenCalled();
495+
});
496+
});
497+
});
458498
});
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
Copyright 2026 Element Creations Ltd.
3+
4+
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
5+
Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
import React, { type ComponentProps } from "react";
9+
import { render, type RenderResult } from "jest-matrix-react";
10+
import { getAllByRole, getAllByText, getByText } from "@testing-library/dom";
11+
12+
import UnknownIdentityUsersWarningDialog from "../../../../../../src/components/views/dialogs/invite/UnknownIdentityUsersWarningDialog.tsx";
13+
import { InviteKind } from "../../../../../../src/components/views/dialogs/InviteDialogTypes.ts";
14+
import { DirectoryMember, ThreepidMember } from "../../../../../../src/utils/direct-messages.ts";
15+
import { getMockClientWithEventEmitter, mockClientMethodsUser } from "../../../../../test-utils";
16+
17+
describe("UnknownIdentityUsersWarningDialog", () => {
18+
beforeEach(() => {
19+
getMockClientWithEventEmitter({
20+
...mockClientMethodsUser(),
21+
});
22+
});
23+
24+
afterEach(() => {
25+
jest.restoreAllMocks();
26+
});
27+
28+
it("should show entries for each user", () => {
29+
const result = renderComponent({
30+
users: [
31+
new DirectoryMember({ user_id: "@alice:example.com" }),
32+
new DirectoryMember({
33+
user_id: "@bob:example.net",
34+
display_name: "Bob",
35+
avatar_url: "mxc://example.com/abc",
36+
}),
37+
new ThreepidMember("charlie@example.com"),
38+
],
39+
});
40+
41+
const list = result.getByRole("listbox");
42+
const entries = getAllByRole(list, "option");
43+
expect(entries).toHaveLength(3);
44+
45+
// No displayname so mxid is displayed twice
46+
expect(getAllByText(entries[0], "@alice:example.com")).toHaveLength(2);
47+
48+
getByText(entries[1], "Bob");
49+
getByText(entries[2], "charlie@example.com");
50+
});
51+
52+
describe("in DM mode", () => {
53+
const kind = InviteKind.Dm;
54+
55+
it("shows a 'Continue' button", () => {
56+
const onContinue = jest.fn();
57+
const result = renderComponent({ kind, onContinue });
58+
const continueButton = result.getByRole("button", { name: "Continue" });
59+
continueButton.click();
60+
expect(onContinue).toHaveBeenCalled();
61+
});
62+
63+
it("shows a 'Cancel' button", () => {
64+
const onCancel = jest.fn();
65+
const result = renderComponent({ kind, onCancel });
66+
const cancelButton = result.getByRole("button", { name: "Cancel" });
67+
cancelButton.click();
68+
expect(onCancel).toHaveBeenCalled();
69+
});
70+
});
71+
72+
describe("in Invite mode", () => {
73+
const kind = InviteKind.Invite;
74+
75+
it("shows an 'Invite' button", () => {
76+
const onContinue = jest.fn();
77+
const result = renderComponent({ kind, onContinue });
78+
const continueButton = result.getByRole("button", { name: "Invite" });
79+
continueButton.click();
80+
expect(onContinue).toHaveBeenCalled();
81+
});
82+
83+
it("shows a 'Remove' button", () => {
84+
const onRemove = jest.fn();
85+
const result = renderComponent({ kind, onRemove });
86+
const removeButton = result.getByRole("button", { name: "Remove" });
87+
removeButton.click();
88+
expect(onRemove).toHaveBeenCalled();
89+
});
90+
});
91+
});
92+
93+
function renderComponent(props: Partial<ComponentProps<typeof UnknownIdentityUsersWarningDialog>>): RenderResult {
94+
const props1: ComponentProps<typeof UnknownIdentityUsersWarningDialog> = {
95+
onContinue: () => {},
96+
onCancel: () => {},
97+
onRemove: () => {},
98+
screenName: undefined,
99+
kind: InviteKind.Dm,
100+
users: [],
101+
...props,
102+
};
103+
return render(<UnknownIdentityUsersWarningDialog {...props1} />);
104+
}

0 commit comments

Comments
 (0)