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

Commit ef0ba77

Browse files
maheichykFox32
andauthored
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 <[email protected]> Co-authored-by: Oliver Sand <[email protected]>
1 parent 3bf52fc commit ef0ba77

File tree

2 files changed

+202
-1
lines changed

2 files changed

+202
-1
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
Copyright 2022 Mikhail Aheichyk
3+
Copyright 2022 Nordeck IT + Consulting GmbH.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
/// <reference types="cypress" />
19+
20+
import { IWidget } from "matrix-widget-api/src/interfaces/IWidget";
21+
22+
import type { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
23+
import { SynapseInstance } from "../../plugins/synapsedocker";
24+
import { UserCredentials } from "../../support/login";
25+
26+
const DEMO_WIDGET_ID = "demo-widget-id";
27+
const DEMO_WIDGET_NAME = "Demo Widget";
28+
const DEMO_WIDGET_TYPE = "demo";
29+
const ROOM_NAME = "Demo";
30+
31+
const DEMO_WIDGET_HTML = `
32+
<html lang="en">
33+
<head>
34+
<title>Demo Widget</title>
35+
<script>
36+
window.onmessage = ev => {
37+
if (ev.data.action === 'capabilities') {
38+
window.parent.postMessage(Object.assign({
39+
response: {
40+
capabilities: []
41+
},
42+
}, ev.data), '*');
43+
}
44+
};
45+
</script>
46+
</head>
47+
<body>
48+
<button id="demo">Demo</button>
49+
</body>
50+
</html>
51+
`;
52+
53+
// mostly copied from src/utils/WidgetUtils.waitForRoomWidget with small modifications
54+
function waitForRoomWidget(win: Cypress.AUTWindow, widgetId: string, roomId: string, add: boolean): Promise<void> {
55+
const matrixClient = win.mxMatrixClientPeg.get();
56+
57+
return new Promise((resolve, reject) => {
58+
function eventsInIntendedState(evList) {
59+
const widgetPresent = evList.some((ev) => {
60+
return ev.getContent() && ev.getContent()['id'] === widgetId;
61+
});
62+
if (add) {
63+
return widgetPresent;
64+
} else {
65+
return !widgetPresent;
66+
}
67+
}
68+
69+
const room = matrixClient.getRoom(roomId);
70+
71+
const startingWidgetEvents = room.currentState.getStateEvents('im.vector.modular.widgets');
72+
if (eventsInIntendedState(startingWidgetEvents)) {
73+
resolve();
74+
return;
75+
}
76+
77+
function onRoomStateEvents(ev: MatrixEvent) {
78+
if (ev.getRoomId() !== roomId || ev.getType() !== "im.vector.modular.widgets") return;
79+
80+
const currentWidgetEvents = room.currentState.getStateEvents('im.vector.modular.widgets');
81+
82+
if (eventsInIntendedState(currentWidgetEvents)) {
83+
matrixClient.removeListener(win.matrixcs.RoomStateEvent.Events, onRoomStateEvents);
84+
resolve();
85+
}
86+
}
87+
88+
matrixClient.on(win.matrixcs.RoomStateEvent.Events, onRoomStateEvents);
89+
});
90+
}
91+
92+
describe("Widget PIP", () => {
93+
let synapse: SynapseInstance;
94+
let user: UserCredentials;
95+
let bot: MatrixClient;
96+
let demoWidgetUrl: string;
97+
98+
function roomCreateAddWidgetPip(userRemove: 'leave' | 'kick' | 'ban') {
99+
cy.createRoom({
100+
name: ROOM_NAME,
101+
invite: [bot.getUserId()],
102+
}).then(roomId => {
103+
// sets bot to Admin and user to Moderator
104+
cy.getClient().then(matrixClient => {
105+
return matrixClient.sendStateEvent(roomId, 'm.room.power_levels', {
106+
users: {
107+
[user.userId]: 50,
108+
[bot.getUserId()]: 100,
109+
},
110+
});
111+
}).as('powerLevelsChanged');
112+
113+
// bot joins the room
114+
cy.botJoinRoom(bot, roomId).as('botJoined');
115+
116+
// setup widget via state event
117+
cy.getClient().then(async matrixClient => {
118+
const content: IWidget = {
119+
id: DEMO_WIDGET_ID,
120+
creatorUserId: 'somebody',
121+
type: DEMO_WIDGET_TYPE,
122+
name: DEMO_WIDGET_NAME,
123+
url: demoWidgetUrl,
124+
};
125+
await matrixClient.sendStateEvent(roomId, 'im.vector.modular.widgets', content, DEMO_WIDGET_ID);
126+
}).as('widgetEventSent');
127+
128+
// open the room
129+
cy.viewRoomByName(ROOM_NAME);
130+
131+
cy.all([
132+
cy.get<string>("@powerLevelsChanged"),
133+
cy.get<string>("@botJoined"),
134+
cy.get<string>("@widgetEventSent"),
135+
]).then(() => {
136+
cy.window().then(async win => {
137+
// wait for widget state event
138+
await waitForRoomWidget(win, DEMO_WIDGET_ID, roomId, true);
139+
140+
// activate widget in pip mode
141+
win.mxActiveWidgetStore.setWidgetPersistence(DEMO_WIDGET_ID, roomId, true);
142+
143+
// checks that pip window is opened
144+
cy.get(".mx_CallView_pip").should("exist");
145+
146+
// checks that widget is opened in pip
147+
cy.accessIframe(`iframe[title="${DEMO_WIDGET_NAME}"]`).within({}, () => {
148+
cy.get("#demo").should('exist').then(async () => {
149+
const userId = user.userId;
150+
if (userRemove == 'leave') {
151+
cy.getClient().then(async matrixClient => {
152+
await matrixClient.leave(roomId);
153+
});
154+
} else if (userRemove == 'kick') {
155+
await bot.kick(roomId, userId);
156+
} else if (userRemove == 'ban') {
157+
await bot.ban(roomId, userId);
158+
}
159+
160+
// checks that pip window is closed
161+
cy.get(".mx_CallView_pip").should("not.exist");
162+
});
163+
});
164+
});
165+
});
166+
});
167+
}
168+
169+
beforeEach(() => {
170+
cy.startSynapse("default").then(data => {
171+
synapse = data;
172+
173+
cy.initTestUser(synapse, "Mike").then(_user => {
174+
user = _user;
175+
});
176+
cy.getBot(synapse, { displayName: "Bot", autoAcceptInvites: false }).then(_bot => {
177+
bot = _bot;
178+
});
179+
});
180+
cy.serveHtmlFile(DEMO_WIDGET_HTML).then(url => {
181+
demoWidgetUrl = url;
182+
});
183+
});
184+
185+
afterEach(() => {
186+
cy.stopSynapse(synapse);
187+
cy.stopWebServers();
188+
});
189+
190+
it('should be closed on leave', () => {
191+
roomCreateAddWidgetPip('leave');
192+
});
193+
194+
it('should be closed on kick', () => {
195+
roomCreateAddWidgetPip('kick');
196+
});
197+
198+
it('should be closed on ban', () => {
199+
roomCreateAddWidgetPip('ban');
200+
});
201+
});

src/components/views/elements/AppTile.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ export default class AppTile extends React.Component<IProps, IState> {
192192
}
193193

194194
private onMyMembership = (room: Room, membership: string): void => {
195-
if (membership === "leave" && room.roomId === this.props.room?.roomId) {
195+
if ((membership === "leave" || membership === "ban") && room.roomId === this.props.room?.roomId) {
196196
this.onUserLeftRoom();
197197
}
198198
};

0 commit comments

Comments
 (0)