202 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
| /*
 | |
| 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.
 | |
| */
 | |
| 
 | |
| /// <reference types="cypress" />
 | |
| 
 | |
| 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 = `
 | |
|     <html lang="en">
 | |
|         <head>
 | |
|             <title>Demo Widget</title>
 | |
|             <script>
 | |
|                 window.onmessage = ev => {
 | |
|                     if (ev.data.action === 'capabilities') {
 | |
|                         window.parent.postMessage(Object.assign({
 | |
|                             response: {
 | |
|                                 capabilities: []
 | |
|                             },
 | |
|                         }, ev.data), '*');
 | |
|                     }
 | |
|                 };
 | |
|             </script>
 | |
|         </head>
 | |
|         <body>
 | |
|             <button id="demo">Demo</button>
 | |
|         </body>
 | |
|     </html>
 | |
| `;
 | |
| 
 | |
| // mostly copied from src/utils/WidgetUtils.waitForRoomWidget with small modifications
 | |
| function waitForRoomWidget(win: Cypress.AUTWindow, widgetId: string, roomId: string, add: boolean): Promise<void> {
 | |
|     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<string>("@powerLevelsChanged"),
 | |
|                 cy.get<string>("@botJoined"),
 | |
|                 cy.get<string>("@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_LegacyCallView_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_LegacyCallView_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');
 | |
|     });
 | |
| });
 |