From ef0ba77f1446d4743b1297827483f664edadd7f9 Mon Sep 17 00:00:00 2001 From: maheichyk Date: Fri, 19 Aug 2022 17:09:26 +0300 Subject: [PATCH] End jitsi call when member is banned (#8879) * Jitsi call is ended when member is banned * cypress tests for widget PIP close on leave/kick/ban * copyright updated * import changes * import changes, lint fixed * import changes * smaller spec changes to fix problems * stale import removed, win.matrixcs.RoomStateEvent.Events is used * fixed problem with kick, smaller test optimisations * comment removed Co-authored-by: mikhail.aheichyk Co-authored-by: Oliver Sand --- cypress/e2e/widgets/widget-pip-close.spec.ts | 201 +++++++++++++++++++ src/components/views/elements/AppTile.tsx | 2 +- 2 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 cypress/e2e/widgets/widget-pip-close.spec.ts diff --git a/cypress/e2e/widgets/widget-pip-close.spec.ts b/cypress/e2e/widgets/widget-pip-close.spec.ts new file mode 100644 index 0000000000..7689e38ed0 --- /dev/null +++ b/cypress/e2e/widgets/widget-pip-close.spec.ts @@ -0,0 +1,201 @@ +/* +Copyright 2022 Mikhail Aheichyk +Copyright 2022 Nordeck IT + Consulting GmbH. + +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 { IWidget } from "matrix-widget-api/src/interfaces/IWidget"; + +import type { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { SynapseInstance } from "../../plugins/synapsedocker"; +import { UserCredentials } from "../../support/login"; + +const DEMO_WIDGET_ID = "demo-widget-id"; +const DEMO_WIDGET_NAME = "Demo Widget"; +const DEMO_WIDGET_TYPE = "demo"; +const ROOM_NAME = "Demo"; + +const DEMO_WIDGET_HTML = ` + + + Demo Widget + + + + + + +`; + +// mostly copied from src/utils/WidgetUtils.waitForRoomWidget with small modifications +function waitForRoomWidget(win: Cypress.AUTWindow, widgetId: string, roomId: string, add: boolean): Promise { + const matrixClient = win.mxMatrixClientPeg.get(); + + return new Promise((resolve, reject) => { + function eventsInIntendedState(evList) { + const widgetPresent = evList.some((ev) => { + return ev.getContent() && ev.getContent()['id'] === widgetId; + }); + if (add) { + return widgetPresent; + } else { + return !widgetPresent; + } + } + + const room = matrixClient.getRoom(roomId); + + const startingWidgetEvents = room.currentState.getStateEvents('im.vector.modular.widgets'); + if (eventsInIntendedState(startingWidgetEvents)) { + resolve(); + return; + } + + function onRoomStateEvents(ev: MatrixEvent) { + if (ev.getRoomId() !== roomId || ev.getType() !== "im.vector.modular.widgets") return; + + const currentWidgetEvents = room.currentState.getStateEvents('im.vector.modular.widgets'); + + if (eventsInIntendedState(currentWidgetEvents)) { + matrixClient.removeListener(win.matrixcs.RoomStateEvent.Events, onRoomStateEvents); + resolve(); + } + } + + matrixClient.on(win.matrixcs.RoomStateEvent.Events, onRoomStateEvents); + }); +} + +describe("Widget PIP", () => { + let synapse: SynapseInstance; + let user: UserCredentials; + let bot: MatrixClient; + let demoWidgetUrl: string; + + function roomCreateAddWidgetPip(userRemove: 'leave' | 'kick' | 'ban') { + cy.createRoom({ + name: ROOM_NAME, + invite: [bot.getUserId()], + }).then(roomId => { + // sets bot to Admin and user to Moderator + cy.getClient().then(matrixClient => { + return matrixClient.sendStateEvent(roomId, 'm.room.power_levels', { + users: { + [user.userId]: 50, + [bot.getUserId()]: 100, + }, + }); + }).as('powerLevelsChanged'); + + // bot joins the room + cy.botJoinRoom(bot, roomId).as('botJoined'); + + // setup widget via state event + cy.getClient().then(async matrixClient => { + const content: IWidget = { + id: DEMO_WIDGET_ID, + creatorUserId: 'somebody', + type: DEMO_WIDGET_TYPE, + name: DEMO_WIDGET_NAME, + url: demoWidgetUrl, + }; + await matrixClient.sendStateEvent(roomId, 'im.vector.modular.widgets', content, DEMO_WIDGET_ID); + }).as('widgetEventSent'); + + // open the room + cy.viewRoomByName(ROOM_NAME); + + cy.all([ + cy.get("@powerLevelsChanged"), + cy.get("@botJoined"), + cy.get("@widgetEventSent"), + ]).then(() => { + cy.window().then(async win => { + // wait for widget state event + await waitForRoomWidget(win, DEMO_WIDGET_ID, roomId, true); + + // activate widget in pip mode + win.mxActiveWidgetStore.setWidgetPersistence(DEMO_WIDGET_ID, roomId, true); + + // checks that pip window is opened + cy.get(".mx_CallView_pip").should("exist"); + + // checks that widget is opened in pip + cy.accessIframe(`iframe[title="${DEMO_WIDGET_NAME}"]`).within({}, () => { + cy.get("#demo").should('exist').then(async () => { + const userId = user.userId; + if (userRemove == 'leave') { + cy.getClient().then(async matrixClient => { + await matrixClient.leave(roomId); + }); + } else if (userRemove == 'kick') { + await bot.kick(roomId, userId); + } else if (userRemove == 'ban') { + await bot.ban(roomId, userId); + } + + // checks that pip window is closed + cy.get(".mx_CallView_pip").should("not.exist"); + }); + }); + }); + }); + }); + } + + beforeEach(() => { + cy.startSynapse("default").then(data => { + synapse = data; + + cy.initTestUser(synapse, "Mike").then(_user => { + user = _user; + }); + cy.getBot(synapse, { displayName: "Bot", autoAcceptInvites: false }).then(_bot => { + bot = _bot; + }); + }); + cy.serveHtmlFile(DEMO_WIDGET_HTML).then(url => { + demoWidgetUrl = url; + }); + }); + + afterEach(() => { + cy.stopSynapse(synapse); + cy.stopWebServers(); + }); + + it('should be closed on leave', () => { + roomCreateAddWidgetPip('leave'); + }); + + it('should be closed on kick', () => { + roomCreateAddWidgetPip('kick'); + }); + + it('should be closed on ban', () => { + roomCreateAddWidgetPip('ban'); + }); +}); diff --git a/src/components/views/elements/AppTile.tsx b/src/components/views/elements/AppTile.tsx index 05c67ab941..211966bde6 100644 --- a/src/components/views/elements/AppTile.tsx +++ b/src/components/views/elements/AppTile.tsx @@ -192,7 +192,7 @@ export default class AppTile extends React.Component { } private onMyMembership = (room: Room, membership: string): void => { - if (membership === "leave" && room.roomId === this.props.room?.roomId) { + if ((membership === "leave" || membership === "ban") && room.roomId === this.props.room?.roomId) { this.onUserLeftRoom(); } };