From 74ea0d134e56b5087a36d4553bfdc3b51ba64453 Mon Sep 17 00:00:00 2001 From: maheichyk Date: Mon, 4 Dec 2023 13:20:24 +0300 Subject: [PATCH] Fix rejoin of knock rooms (#11980) Signed-off-by: Mikhail Aheichyk Co-authored-by: Mikhail Aheichyk --- cypress/e2e/knock/knock-into-room.spec.ts | 120 +++++++++++++++++- src/components/structures/RoomView.tsx | 4 +- src/components/views/rooms/RoomPreviewBar.tsx | 5 +- .../views/rooms/RoomPreviewBar-test.tsx | 10 +- .../RoomPreviewBar-test.tsx.snap | 25 ++++ 5 files changed, 160 insertions(+), 4 deletions(-) diff --git a/cypress/e2e/knock/knock-into-room.spec.ts b/cypress/e2e/knock/knock-into-room.spec.ts index c58d93db7e..4d6a0eebe7 100644 --- a/cypress/e2e/knock/knock-into-room.spec.ts +++ b/cypress/e2e/knock/knock-into-room.spec.ts @@ -63,7 +63,7 @@ describe("Knock Into Room", () => { cy.stopHomeserver(homeserver); }); - it("should knock into the room then knock is approved and user joins the room", () => { + it("should knock into the room then knock is approved and user joins the room then user is kicked and joins again", () => { cy.viewRoomById(roomId); cy.get(".mx_RoomPreviewBar").within(() => { @@ -104,6 +104,124 @@ describe("Knock Into Room", () => { cy.findByRole("group", { name: "Rooms" }).findByRole("treeitem", { name: "Cybersecurity" }); cy.findByText("Alice joined the room").should("exist"); + + cy.window().then(async (win) => { + // bot kicks Alice + await bot.kick(roomId, user.userId); + }); + + cy.get(".mx_RoomPreviewBar").within(() => { + cy.findByRole("button", { name: "Re-join" }).click(); + + cy.findByRole("heading", { name: "Ask to join Cybersecurity?" }); + cy.findByRole("button", { name: "Request access" }).click(); + }); + + cy.window().then(async (win) => { + // bot waits for knock request from Alice + await waitForRoom(win, bot, roomId, (room) => { + const events = room.getLiveTimeline().getEvents(); + return events.some( + (e) => + e.getType() === "m.room.member" && + e.getContent()?.membership === "knock" && + e.getContent()?.displayname === "Alice", + ); + }); + + // bot invites Alice + await bot.invite(roomId, user.userId); + }); + + // Alice have to accept invitation in order to join the room. + // It will be not needed when homeserver implements auto accept knock requests. + cy.get(".mx_RoomView").findByRole("button", { name: "Accept" }).click(); + + cy.findByText("Alice was invited, joined, was removed, was invited, and joined").should("exist"); + }); + + it("should knock into the room then knock is approved and user joins the room then user is banned/unbanned and joins again", () => { + cy.viewRoomById(roomId); + + cy.get(".mx_RoomPreviewBar").within(() => { + cy.findByRole("button", { name: "Join the discussion" }).click(); + + cy.findByRole("heading", { name: "Ask to join?" }); + cy.findByRole("textbox"); + cy.findByRole("button", { name: "Request access" }).click(); + + cy.findByRole("heading", { name: "Request to join sent" }); + }); + + // Knocked room should appear in Rooms + cy.findByRole("group", { name: "Rooms" }).findByRole("treeitem", { name: "Cybersecurity" }); + + cy.window().then(async (win) => { + // bot waits for knock request from Alice + await waitForRoom(win, bot, roomId, (room) => { + const events = room.getLiveTimeline().getEvents(); + return events.some( + (e) => + e.getType() === "m.room.member" && + e.getContent()?.membership === "knock" && + e.getContent()?.displayname === "Alice", + ); + }); + + // bot invites Alice + await bot.invite(roomId, user.userId); + }); + + cy.findByRole("group", { name: "Invites" }).findByRole("treeitem", { name: "Cybersecurity" }); + + // Alice have to accept invitation in order to join the room. + // It will be not needed when homeserver implements auto accept knock requests. + cy.get(".mx_RoomView").findByRole("button", { name: "Accept" }).click(); + + cy.findByRole("group", { name: "Rooms" }).findByRole("treeitem", { name: "Cybersecurity" }); + + cy.findByText("Alice joined the room").should("exist"); + + cy.window().then(async (win) => { + // bot bans Alice + await bot.ban(roomId, user.userId); + }); + + cy.get(".mx_RoomPreviewBar").findByText("You were banned from Cybersecurity by Bob").should("exist"); + + cy.window().then(async (win) => { + // bot unbans Alice + await bot.unban(roomId, user.userId); + }); + + cy.get(".mx_RoomPreviewBar").within(() => { + cy.findByRole("button", { name: "Re-join" }).click(); + + cy.findByRole("heading", { name: "Ask to join Cybersecurity?" }); + cy.findByRole("button", { name: "Request access" }).click(); + }); + + cy.window().then(async (win) => { + // bot waits for knock request from Alice + await waitForRoom(win, bot, roomId, (room) => { + const events = room.getLiveTimeline().getEvents(); + return events.some( + (e) => + e.getType() === "m.room.member" && + e.getContent()?.membership === "knock" && + e.getContent()?.displayname === "Alice", + ); + }); + + // bot invites Alice + await bot.invite(roomId, user.userId); + }); + + // Alice have to accept invitation in order to join the room. + // It will be not needed when homeserver implements auto accept knock requests. + cy.get(".mx_RoomView").findByRole("button", { name: "Accept" }).click(); + + cy.findByText("Alice was invited, joined, was banned, was unbanned, was invited, and joined").should("exist"); }); it("should knock into the room and knock is cancelled by user himself", () => { diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 2689fab9d4..364ec3a32f 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -2229,8 +2229,10 @@ export class RoomView extends React.Component {
{ if (myMember.isKicked()) { if (previousMembership === "knock") { return MessageCase.RequestDenied; + } else if (this.props.promptAskToJoin) { + return MessageCase.PromptAskToJoin; } return MessageCase.Kicked; } else if (myMember.membership === "ban") { @@ -208,7 +211,7 @@ export default class RoomPreviewBar extends React.Component { return MessageCase.Loading; } else if (this.props.knocked) { return MessageCase.Knocked; - } else if (this.props.promptAskToJoin) { + } else if (this.props.canAskToJoinAndMembershipIsLeave || this.props.promptAskToJoin) { return MessageCase.PromptAskToJoin; } diff --git a/test/components/views/rooms/RoomPreviewBar-test.tsx b/test/components/views/rooms/RoomPreviewBar-test.tsx index 6f2805d164..80359a8dee 100644 --- a/test/components/views/rooms/RoomPreviewBar-test.tsx +++ b/test/components/views/rooms/RoomPreviewBar-test.tsx @@ -172,7 +172,7 @@ describe("", () => { it("renders kicked message", () => { const room = createRoom(roomId, otherUserId); jest.spyOn(room, "getMember").mockReturnValue(makeMockRoomMember({ isKicked: true })); - const component = getComponent({ room, promptAskToJoin: true }); + const component = getComponent({ room, canAskToJoinAndMembershipIsLeave: true, promptAskToJoin: false }); expect(getMessage(component)).toMatchSnapshot(); }); @@ -458,6 +458,14 @@ describe("", () => { expect(getMessage(component)).toMatchSnapshot(); }); + it("renders the corresponding message when kicked", () => { + const room = createRoom(roomId, otherUserId); + jest.spyOn(room, "getMember").mockReturnValue(makeMockRoomMember({ isKicked: true })); + const component = getComponent({ room, promptAskToJoin: true }); + + expect(getMessage(component)).toMatchSnapshot(); + }); + it("renders the corresponding message with a generic title", () => { const component = render(); expect(getMessage(component)).toMatchSnapshot(); diff --git a/test/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap b/test/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap index 7ab3f365ce..62843249d1 100644 --- a/test/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap +++ b/test/components/views/rooms/__snapshots__/RoomPreviewBar-test.tsx.snap @@ -39,6 +39,31 @@ exports[` message case AskToJoin renders the corresponding mes
`; +exports[` message case AskToJoin renders the corresponding message when kicked 1`] = ` +
+

+ Ask to join RoomPreviewBar-test-room? +

+

+ + R + +

+

+ You need to be granted access to this room in order to view or participate in the conversation. You can send a request to join below. +

+
+`; + exports[` message case AskToJoin renders the corresponding message with a generic title 1`] = `