Implement third-party invite waiting room (#10229)
This commit is contained in:
parent
94950c6987
commit
db6ee53535
12 changed files with 388 additions and 40 deletions
|
@ -23,7 +23,7 @@ import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
|
|||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { EventType, RoomStateEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib";
|
||||
import { fireEvent, render } from "@testing-library/react";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
|
||||
import {
|
||||
stubClient,
|
||||
|
@ -34,6 +34,8 @@ import {
|
|||
mkEvent,
|
||||
setupAsyncStoreWithClient,
|
||||
filterConsole,
|
||||
mkRoomMemberJoinEvent,
|
||||
mkThirdPartyInviteEvent,
|
||||
} from "../../test-utils";
|
||||
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
||||
import { Action } from "../../../src/dispatcher/actions";
|
||||
|
@ -68,7 +70,7 @@ describe("RoomView", () => {
|
|||
// mute some noise
|
||||
filterConsole("RVS update", "does not have an m.room.create event", "Current version: 1", "Version capability");
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
mockPlatformPeg({ reload: () => {} });
|
||||
stubClient();
|
||||
cli = mocked(MatrixClientPeg.get());
|
||||
|
@ -91,7 +93,7 @@ describe("RoomView", () => {
|
|||
jest.spyOn(VoipUserMapper.sharedInstance(), "getVirtualRoomForRoom").mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
afterEach(() => {
|
||||
unmockPlatformPeg();
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
@ -369,6 +371,32 @@ describe("RoomView", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("when rendering a DM room with a single third-party invite", () => {
|
||||
beforeEach(async () => {
|
||||
room.currentState.setStateEvents([
|
||||
mkRoomMemberJoinEvent(cli.getSafeUserId(), room.roomId),
|
||||
mkThirdPartyInviteEvent(cli.getSafeUserId(), "user@example.com", room.roomId),
|
||||
]);
|
||||
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(cli.getSafeUserId());
|
||||
jest.spyOn(DMRoomMap.shared(), "getRoomIds").mockReturnValue(new Set([room.roomId]));
|
||||
mocked(cli).isRoomEncrypted.mockReturnValue(true);
|
||||
await renderRoomView();
|
||||
});
|
||||
|
||||
it("should render the »waiting for third-party« view", () => {
|
||||
expect(screen.getByText("Waiting for users to join Element")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"Once invited users have joined Element, you will be able to chat and the room will be end-to-end encrypted",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
|
||||
// no message composer
|
||||
expect(screen.queryByText("Send an encrypted message…")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Send a message…")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there is a RoomView", () => {
|
||||
const widget1Id = "widget1";
|
||||
const widget2Id = "widget2";
|
||||
|
|
|
@ -20,13 +20,12 @@ import { render, screen } from "@testing-library/react";
|
|||
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { LocalRoom } from "../../../../src/models/LocalRoom";
|
||||
import { createTestClient } from "../../../test-utils";
|
||||
import { filterConsole, mkRoomMemberJoinEvent, mkThirdPartyInviteEvent, stubClient } from "../../../test-utils";
|
||||
import RoomContext from "../../../../src/contexts/RoomContext";
|
||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||
import NewRoomIntro from "../../../../src/components/views/rooms/NewRoomIntro";
|
||||
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
||||
import DMRoomMap from "../../../../src/utils/DMRoomMap";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import { DirectoryMember } from "../../../../src/utils/direct-messages";
|
||||
|
||||
const renderNewRoomIntro = (client: MatrixClient, room: Room | LocalRoom) => {
|
||||
|
@ -44,9 +43,10 @@ describe("NewRoomIntro", () => {
|
|||
const roomId = "!room:example.com";
|
||||
const userId = "@user:example.com";
|
||||
|
||||
beforeEach(() => {
|
||||
client = createTestClient();
|
||||
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(client);
|
||||
filterConsole("Room !room:example.com does not have an m.room.create event");
|
||||
|
||||
beforeAll(() => {
|
||||
client = stubClient();
|
||||
DMRoomMap.makeShared();
|
||||
});
|
||||
|
||||
|
@ -64,6 +64,24 @@ describe("NewRoomIntro", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should render as expected for a DM room with a single third-party invite", () => {
|
||||
const room = new Room(roomId, client, client.getSafeUserId());
|
||||
room.currentState.setStateEvents([
|
||||
mkRoomMemberJoinEvent(client.getSafeUserId(), room.roomId),
|
||||
mkThirdPartyInviteEvent(client.getSafeUserId(), "user@example.com", room.roomId),
|
||||
]);
|
||||
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(userId);
|
||||
jest.spyOn(DMRoomMap.shared(), "getRoomIds").mockReturnValue(new Set([room.roomId]));
|
||||
renderNewRoomIntro(client, room);
|
||||
|
||||
expect(screen.getByText("Once everyone has joined, you’ll be able to chat")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText(
|
||||
"Only the two of you are in this conversation, unless either of you invites anyone to join.",
|
||||
),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("for a DM LocalRoom", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(userId);
|
||||
|
|
|
@ -116,11 +116,11 @@ describe("direct-messages", () => {
|
|||
it("should create a local room and dispatch a view room event", async () => {
|
||||
mocked(createDmLocalRoom).mockResolvedValue(localRoom);
|
||||
const members = [member1];
|
||||
const room = await dmModule.startDmOnFirstMessage(mockClient, members);
|
||||
expect(room).toBe(localRoom);
|
||||
const roomId = await dmModule.startDmOnFirstMessage(mockClient, members);
|
||||
expect(roomId).toBe(localRoom.roomId);
|
||||
expect(dis.dispatch).toHaveBeenCalledWith({
|
||||
action: Action.ViewRoom,
|
||||
room_id: room.roomId,
|
||||
room_id: roomId,
|
||||
joining: false,
|
||||
targets: [member1],
|
||||
});
|
||||
|
@ -135,8 +135,8 @@ describe("direct-messages", () => {
|
|||
|
||||
mocked(createDmLocalRoom).mockResolvedValue(localRoom);
|
||||
const members = [member1];
|
||||
const room = await dmModule.startDmOnFirstMessage(mockClient, members);
|
||||
expect(room).toBe(localRoom);
|
||||
const roomId = await dmModule.startDmOnFirstMessage(mockClient, members);
|
||||
expect(roomId).toBe(localRoom.roomId);
|
||||
|
||||
// ensure that startDmOnFirstMessage tries to resolve 3rd-party IDs
|
||||
expect(resolveThreePids).toHaveBeenCalledWith(members, mockClient);
|
||||
|
@ -152,8 +152,8 @@ describe("direct-messages", () => {
|
|||
});
|
||||
|
||||
it("should return the room and dispatch a view room event", async () => {
|
||||
const room = await dmModule.startDmOnFirstMessage(mockClient, [member1]);
|
||||
expect(room).toBe(room1);
|
||||
const roomId = await dmModule.startDmOnFirstMessage(mockClient, [member1]);
|
||||
expect(roomId).toBe(room1.roomId);
|
||||
expect(dis.dispatch).toHaveBeenCalledWith({
|
||||
action: Action.ViewRoom,
|
||||
room_id: room1.roomId,
|
||||
|
|
|
@ -70,10 +70,10 @@ describe("createDmLocalRoom", () => {
|
|||
mocked(privateShouldBeEncrypted).mockReturnValue(true);
|
||||
});
|
||||
|
||||
it("should create an unencrypted room for 3PID targets", async () => {
|
||||
it("should create an encrytped room for 3PID targets", async () => {
|
||||
const room = await createDmLocalRoom(mockClient, [member2]);
|
||||
expect(mockClient.store.storeRoom).toHaveBeenCalledWith(room);
|
||||
assertLocalRoom(room, [member2], false);
|
||||
assertLocalRoom(room, [member2], true);
|
||||
});
|
||||
|
||||
describe("for MXID targets with encryption available", () => {
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import DMRoomMap from "../../../src/utils/DMRoomMap";
|
||||
import { shouldEncryptRoomWithSingle3rdPartyInvite } from "../../../src/utils/room/shouldEncryptRoomWithSingle3rdPartyInvite";
|
||||
import { privateShouldBeEncrypted } from "../../../src/utils/rooms";
|
||||
import { mkRoomMemberJoinEvent, mkThirdPartyInviteEvent, stubClient } from "../../test-utils";
|
||||
|
||||
jest.mock("../../../src/utils/rooms", () => ({
|
||||
privateShouldBeEncrypted: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("shouldEncryptRoomWithSingle3rdPartyInvite", () => {
|
||||
let client: MatrixClient;
|
||||
let thirdPartyInviteEvent: MatrixEvent;
|
||||
let roomWithOneThirdPartyInvite: Room;
|
||||
|
||||
beforeAll(() => {
|
||||
client = stubClient();
|
||||
DMRoomMap.makeShared();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
roomWithOneThirdPartyInvite = new Room("!room1:example.com", client, client.getSafeUserId());
|
||||
thirdPartyInviteEvent = mkThirdPartyInviteEvent(
|
||||
client.getSafeUserId(),
|
||||
"user@example.com",
|
||||
roomWithOneThirdPartyInvite.roomId,
|
||||
);
|
||||
|
||||
roomWithOneThirdPartyInvite.currentState.setStateEvents([
|
||||
mkRoomMemberJoinEvent(client.getSafeUserId(), roomWithOneThirdPartyInvite.roomId),
|
||||
thirdPartyInviteEvent,
|
||||
]);
|
||||
jest.spyOn(DMRoomMap.shared(), "getRoomIds").mockReturnValue(new Set([roomWithOneThirdPartyInvite.roomId]));
|
||||
});
|
||||
|
||||
describe("when well-known promotes encryption", () => {
|
||||
beforeEach(() => {
|
||||
mocked(privateShouldBeEncrypted).mockReturnValue(true);
|
||||
});
|
||||
|
||||
it("should return true + invite event for a DM room with one third-party invite", () => {
|
||||
expect(shouldEncryptRoomWithSingle3rdPartyInvite(roomWithOneThirdPartyInvite)).toEqual({
|
||||
shouldEncrypt: true,
|
||||
inviteEvent: thirdPartyInviteEvent,
|
||||
});
|
||||
});
|
||||
|
||||
it("should return false for a non-DM room with one third-party invite", () => {
|
||||
mocked(DMRoomMap.shared().getRoomIds).mockReturnValue(new Set());
|
||||
|
||||
expect(shouldEncryptRoomWithSingle3rdPartyInvite(roomWithOneThirdPartyInvite)).toEqual({
|
||||
shouldEncrypt: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("should return false for a DM room with two members", () => {
|
||||
roomWithOneThirdPartyInvite.currentState.setStateEvents([
|
||||
mkRoomMemberJoinEvent("@user2:example.com", roomWithOneThirdPartyInvite.roomId),
|
||||
]);
|
||||
|
||||
expect(shouldEncryptRoomWithSingle3rdPartyInvite(roomWithOneThirdPartyInvite)).toEqual({
|
||||
shouldEncrypt: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("should return false for a DM room with two third-party invites", () => {
|
||||
roomWithOneThirdPartyInvite.currentState.setStateEvents([
|
||||
mkThirdPartyInviteEvent(
|
||||
client.getSafeUserId(),
|
||||
"user2@example.com",
|
||||
roomWithOneThirdPartyInvite.roomId,
|
||||
),
|
||||
]);
|
||||
|
||||
expect(shouldEncryptRoomWithSingle3rdPartyInvite(roomWithOneThirdPartyInvite)).toEqual({
|
||||
shouldEncrypt: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("when well-known does not promote encryption", () => {
|
||||
beforeEach(() => {
|
||||
mocked(privateShouldBeEncrypted).mockReturnValue(false);
|
||||
});
|
||||
|
||||
it("should return false for a DM room with one third-party invite", () => {
|
||||
expect(shouldEncryptRoomWithSingle3rdPartyInvite(roomWithOneThirdPartyInvite)).toEqual({
|
||||
shouldEncrypt: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue