Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix email lookup in invite dialog (#10150)
Browse files Browse the repository at this point in the history
  • Loading branch information
weeman1337 authored Feb 14, 2023
1 parent 18c9b2b commit 6ab44fd
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 36 deletions.
5 changes: 3 additions & 2 deletions src/components/views/dialogs/InviteDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,8 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
display_name: profile.displayname,
avatar_url: profile.avatar_url,
}),
userId: lookup.mxid,
// Use the search term as identifier, so that it shows up in suggestions.
userId: term,
},
],
});
Expand Down Expand Up @@ -934,7 +935,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
<DMRoomTile
member={r.user}
lastActiveTs={lastActive(r)}
key={r.userId}
key={r.user.userId}
onToggle={this.toggleMember}
highlightWord={this.state.filterText}
isSelected={this.state.targets.some((t) => t.userId === r.userId)}
Expand Down
106 changes: 72 additions & 34 deletions test/components/views/dialogs/InviteDialog-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ limitations under the License.
import React from "react";
import { render, screen } from "@testing-library/react";
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_INVITE } from "../../../../src/components/views/dialogs/InviteDialogTypes";
import { getMockClientWithEventEmitter, mkStubRoom } from "../../../test-utils";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { KIND_DM, KIND_INVITE } 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";
import { ValidatedServerConfig } from "../../../../src/utils/ValidatedServerConfig";
Expand All @@ -37,8 +37,11 @@ jest.mock("../../../../src/IdentityAuthClient", () =>
describe("InviteDialog", () => {
const roomId = "!111111111111111111:example.org";
const aliceId = "@alice:example.org";
const aliceEmail = "foobar@email.com";
const bobId = "@bob:example.org";
const mockClient = getMockClientWithEventEmitter({
getUserId: jest.fn().mockReturnValue(aliceId),
getUserId: jest.fn().mockReturnValue(bobId),
getSafeUserId: jest.fn().mockReturnValue(bobId),
isGuest: jest.fn().mockReturnValue(false),
getVisibleRooms: jest.fn().mockReturnValue([]),
getRoom: jest.fn(),
Expand All @@ -58,36 +61,61 @@ describe("InviteDialog", () => {
getOpenIdToken: jest.fn().mockResolvedValue({}),
getIdentityAccount: jest.fn().mockResolvedValue({}),
getTerms: jest.fn().mockResolvedValue({ policies: [] }),
supportsThreads: jest.fn().mockReturnValue(false),
isInitialSyncComplete: jest.fn().mockReturnValue(true),
});
let room: Room;

beforeEach(() => {
SdkConfig.put({ validated_server_config: {} as ValidatedServerConfig } as IConfigOptions);
DMRoomMap.makeShared();
jest.clearAllMocks();
mockClient.getUserId.mockReturnValue("@bob:example.org");

const room = mkStubRoom(roomId, "Room", mockClient);
mockClient.getUserId.mockReturnValue(bobId);

room = new Room(roomId, mockClient, mockClient.getSafeUserId());
room.addLiveEvents([
mkMessage({
msg: "Hello",
relatesTo: undefined,
event: true,
room: roomId,
user: mockClient.getSafeUserId(),
ts: Date.now(),
}),
]);
room.currentState.setStateEvents([
mkRoomCreateEvent(bobId, roomId),
mkMembership({
event: true,
room: roomId,
mship: "join",
user: aliceId,
skey: aliceId,
}),
]);
jest.spyOn(DMRoomMap.shared(), "getUniqueRoomsWithIndividuals").mockReturnValue({
[aliceId]: room,
});
mockClient.getRooms.mockReturnValue([room]);
mockClient.getRoom.mockReturnValue(room);
});

afterAll(() => {
jest.spyOn(MatrixClientPeg, "get").mockRestore();
jest.restoreAllMocks();
});

it("should label with space name", () => {
mockClient.getRoom(roomId)!.isSpaceRoom = jest.fn().mockReturnValue(true);
mockClient.getRoom(roomId)!.getType = jest.fn().mockReturnValue(RoomType.Space);
mockClient.getRoom(roomId)!.name = "Space";
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()} />);

expect(screen.queryByText("Invite to Space")).toBeTruthy();
});

it("should label with room name", () => {
render(<InviteDialog kind={KIND_INVITE} roomId={roomId} onFinished={jest.fn()} />);

expect(screen.queryByText("Invite to Room")).toBeTruthy();
expect(screen.getByText(`Invite to ${roomId}`)).toBeInTheDocument();
});

it("should suggest valid MXIDs even if unknown", async () => {
Expand Down Expand Up @@ -116,27 +144,37 @@ describe("InviteDialog", () => {
expect(screen.queryByText("@localpart:server:tld")).toBeFalsy();
});

it("should lookup inputs which look like email addresses", async () => {
mockClient.getIdentityServerUrl.mockReturnValue("https://identity-server");
mockClient.lookupThreePid.mockResolvedValue({
address: "foobar@email.com",
medium: "email",
mxid: "@foobar:server",
});
mockClient.getProfileInfo.mockResolvedValue({
displayname: "Mr. Foo",
avatar_url: "mxc://foo/bar",
});

render(
<InviteDialog kind={KIND_INVITE} roomId={roomId} onFinished={jest.fn()} initialText="foobar@email.com" />,
);

await screen.findByText("Mr. Foo");
await screen.findByText("@foobar:server");
expect(mockClient.lookupThreePid).toHaveBeenCalledWith("email", "foobar@email.com", expect.anything());
expect(mockClient.getProfileInfo).toHaveBeenCalledWith("@foobar:server");
});
it.each([[KIND_DM], [KIND_INVITE]] as [typeof KIND_DM | typeof KIND_INVITE][])(
"should lookup inputs which look like email addresses (%s)",
async (kind: typeof KIND_DM | typeof KIND_INVITE) => {
mockClient.getIdentityServerUrl.mockReturnValue("https://identity-server");
mockClient.lookupThreePid.mockResolvedValue({
address: aliceEmail,
medium: "email",
mxid: aliceId,
});
mockClient.getProfileInfo.mockResolvedValue({
displayname: "Mrs Alice",
avatar_url: "mxc://foo/bar",
});

render(
<InviteDialog
kind={kind}
roomId={kind === KIND_INVITE ? roomId : ""}
onFinished={jest.fn()}
initialText={aliceEmail}
/>,
);

await screen.findByText("Mrs Alice");
// expect the email and MXID to be visible
await screen.findByText(aliceId);
await screen.findByText(aliceEmail);
expect(mockClient.lookupThreePid).toHaveBeenCalledWith("email", aliceEmail, expect.anything());
expect(mockClient.getProfileInfo).toHaveBeenCalledWith(aliceId);
},
);

it("should suggest e-mail even if lookup fails", async () => {
mockClient.getIdentityServerUrl.mockReturnValue("https://identity-server");
Expand Down

0 comments on commit 6ab44fd

Please sign in to comment.