@@ -9,7 +9,7 @@ import type { EventType, Preset } from "matrix-js-sdk/src/matrix";
99import { SettingLevel } from "../../../src/settings/SettingLevel" ;
1010import { test , expect } from "../../element-web-test" ;
1111import type { Credentials } from "../../plugins/homeserver" ;
12- import type { Bot } from "../../pages/bot" ;
12+ import { Bot } from "../../pages/bot" ;
1313
1414function assertCommonCallParameters (
1515 url : URLSearchParams ,
@@ -27,27 +27,28 @@ function assertCommonCallParameters(
2727 expect ( hash . get ( "preload" ) ) . toEqual ( "false" ) ;
2828}
2929
30- async function sendRTCState ( bot : Bot , roomId : string , notification ?: "ring" | "notification" ) {
30+ async function sendRTCState ( bot : Bot , roomId : string , notification ?: "ring" | "notification" , intent ?: string ) {
3131 const resp = await bot . sendStateEvent (
3232 roomId ,
3333 "org.matrix.msc3401.call.member" ,
3434 {
35- application : "m.call" ,
36- call_id : "" ,
37- device_id : "OiDFxsZrjz" ,
38- expires : 180000000 ,
39- foci_preferred : [
35+ "application" : "m.call" ,
36+ "call_id" : "" ,
37+ "m.call.intent" : intent ,
38+ "device_id" : "OiDFxsZrjz" ,
39+ "expires" : 180000000 ,
40+ "foci_preferred" : [
4041 {
4142 livekit_alias : roomId ,
4243 livekit_service_url : "https://example.org" ,
4344 type : "livekit" ,
4445 } ,
4546 ] ,
46- focus_active : {
47+ " focus_active" : {
4748 focus_selection : "oldest_membership" ,
4849 type : "livekit" ,
4950 } ,
50- scope : "m.room" ,
51+ " scope" : "m.room" ,
5152 } ,
5253 `_@${ bot . credentials . userId } _OiDFxsZrjz_m.call` ,
5354 ) ;
@@ -64,6 +65,7 @@ async function sendRTCState(bot: Bot, roomId: string, notification?: "ring" | "n
6465 event_id : resp . event_id ,
6566 rel_type : "org.matrix.msc4075.rtc.notification.parent" ,
6667 } ,
68+ "m.call.intent" : intent ,
6769 "notification_type" : notification ,
6870 "sender_ts" : 1758611895996 ,
6971 } ) ;
@@ -103,15 +105,21 @@ test.describe("Element Call", () => {
103105 } ) ;
104106
105107 test . describe ( "Group Chat" , ( ) => {
108+ let charlie : Bot ;
106109 test . use ( {
107- room : async ( { page, app, user, bot } , use ) => {
108- const roomId = await app . client . createRoom ( { name : "TestRoom" , invite : [ bot . credentials . userId ] } ) ;
110+ room : async ( { page, app, user, homeserver, bot } , use ) => {
111+ charlie = new Bot ( page , homeserver , { displayName : "Charlie" } ) ;
112+ await charlie . prepareClient ( ) ;
113+ const roomId = await app . client . createRoom ( {
114+ name : "TestRoom" ,
115+ invite : [ bot . credentials . userId , charlie . credentials . userId ] ,
116+ } ) ;
109117 await use ( { roomId } ) ;
110118 } ,
111119 } ) ;
112120 test ( "should be able to start a video call" , async ( { page, user, room, app } ) => {
113121 await app . viewRoomById ( room . roomId ) ;
114- await expect ( page . getByText ( "Bob joined the room " ) ) . toBeVisible ( ) ;
122+ await expect ( page . getByText ( "Bob and one other were invited and joined " ) ) . toBeVisible ( ) ;
115123
116124 await page . getByRole ( "button" , { name : "Video call" } ) . click ( ) ;
117125 await page . getByRole ( "menuitem" , { name : "Element Call" } ) . click ( ) ;
@@ -126,9 +134,16 @@ test.describe("Element Call", () => {
126134 expect ( hash . get ( "skipLobby" ) ) . toEqual ( null ) ;
127135 } ) ;
128136
137+ test ( "should NOT be able to start a voice call" , async ( { page, user, room, app } ) => {
138+ // Voice calls do not exist in group rooms
139+ await app . viewRoomById ( room . roomId ) ;
140+ await expect ( page . getByText ( "Bob and one other were invited and joined" ) ) . toBeVisible ( ) ;
141+ await expect ( page . getByRole ( "button" , { name : "Voice call" } ) ) . not . toBeVisible ( ) ;
142+ } ) ;
143+
129144 test ( "should be able to skip lobby by holding down shift" , async ( { page, user, bot, room, app } ) => {
130145 await app . viewRoomById ( room . roomId ) ;
131- await expect ( page . getByText ( "Bob joined the room " ) ) . toBeVisible ( ) ;
146+ await expect ( page . getByText ( "Bob and one other were invited and joined " ) ) . toBeVisible ( ) ;
132147
133148 await page . getByRole ( "button" , { name : "Video call" } ) . click ( ) ;
134149 await page . keyboard . down ( "Shift" ) ;
@@ -147,16 +162,15 @@ test.describe("Element Call", () => {
147162 test ( "should be able to join a call in progress" , async ( { page, user, bot, room, app } ) => {
148163 await app . viewRoomById ( room . roomId ) ;
149164 // Allow bob to create a call
165+ await expect ( page . getByText ( "Bob and one other were invited and joined" ) ) . toBeVisible ( ) ;
150166 await app . client . setPowerLevel ( room . roomId , bot . credentials . userId , 50 ) ;
151- await expect ( page . getByText ( "Bob joined the room" ) ) . toBeVisible ( ) ;
152167 // Fake a start of a call
153168 await sendRTCState ( bot , room . roomId ) ;
154169 const button = page . getByTestId ( "join-call-button" ) ;
155170 await expect ( button ) . toBeInViewport ( { timeout : 5000 } ) ;
156171 // And test joining
157172 await button . click ( ) ;
158173 const frameUrlStr = await page . locator ( "iframe" ) . getAttribute ( "src" ) ;
159- console . log ( frameUrlStr ) ;
160174 await expect ( frameUrlStr ) . toBeDefined ( ) ;
161175 const url = new URL ( frameUrlStr ) ;
162176 const hash = new URLSearchParams ( url . hash . slice ( 1 ) ) ;
@@ -168,29 +182,29 @@ test.describe("Element Call", () => {
168182
169183 [ true , false ] . forEach ( ( skipLobbyToggle ) => {
170184 test (
171- `should be able to join a call via incoming call toast (skipLobby=${ skipLobbyToggle } )` ,
185+ `should be able to join a call via incoming video call toast (skipLobby=${ skipLobbyToggle } )` ,
172186 { tag : [ "@screenshot" ] } ,
173187 async ( { page, user, bot, room, app } ) => {
174188 await app . viewRoomById ( room . roomId ) ;
175189 // Allow bob to create a call
190+ await expect ( page . getByText ( "Bob and one other were invited and joined" ) ) . toBeVisible ( ) ;
176191 await app . client . setPowerLevel ( room . roomId , bot . credentials . userId , 50 ) ;
177- await expect ( page . getByText ( "Bob joined the room" ) ) . toBeVisible ( ) ;
178192 // Fake a start of a call
179- await sendRTCState ( bot , room . roomId , "notification" ) ;
193+ await sendRTCState ( bot , room . roomId , "notification" , "video" ) ;
180194 const toast = page . locator ( ".mx_Toast_toast" ) ;
181195 const button = toast . getByRole ( "button" , { name : "Join" } ) ;
196+
182197 if ( skipLobbyToggle ) {
183198 await toast . getByRole ( "switch" ) . check ( ) ;
184- await expect ( toast ) . toMatchScreenshot ( " incoming-call-group-video-toast-checked.png" ) ;
199+ await expect ( toast ) . toMatchScreenshot ( ` incoming-call-group-video-toast-checked.png` ) ;
185200 } else {
186201 await toast . getByRole ( "switch" ) . uncheck ( ) ;
187- await expect ( toast ) . toMatchScreenshot ( " incoming-call-group-video-toast-unchecked.png" ) ;
202+ await expect ( toast ) . toMatchScreenshot ( ` incoming-call-group-video-toast-unchecked.png` ) ;
188203 }
189204
190205 // And test joining
191206 await button . click ( ) ;
192207 const frameUrlStr = await page . locator ( "iframe" ) . getAttribute ( "src" ) ;
193- console . log ( frameUrlStr ) ;
194208 await expect ( frameUrlStr ) . toBeDefined ( ) ;
195209 const url = new URL ( frameUrlStr ) ;
196210 const hash = new URLSearchParams ( url . hash . slice ( 1 ) ) ;
@@ -201,6 +215,34 @@ test.describe("Element Call", () => {
201215 } ,
202216 ) ;
203217 } ) ;
218+
219+ test (
220+ `should be able to join a call via incoming voice call toast` ,
221+ { tag : [ "@screenshot" ] } ,
222+ async ( { page, user, bot, room, app } ) => {
223+ await app . viewRoomById ( room . roomId ) ;
224+ // Allow bob to create a call
225+ await expect ( page . getByText ( "Bob and one other were invited and joined" ) ) . toBeVisible ( ) ;
226+ await app . client . setPowerLevel ( room . roomId , bot . credentials . userId , 50 ) ;
227+ // Fake a start of a call
228+ await sendRTCState ( bot , room . roomId , "notification" , "audio" ) ;
229+ const toast = page . locator ( ".mx_Toast_toast" ) ;
230+ const button = toast . getByRole ( "button" , { name : "Join" } ) ;
231+
232+ await expect ( toast ) . toMatchScreenshot ( `incoming-call-group-voice-toast.png` ) ;
233+
234+ // And test joining
235+ await button . click ( ) ;
236+ const frameUrlStr = await page . locator ( "iframe" ) . getAttribute ( "src" ) ;
237+ await expect ( frameUrlStr ) . toBeDefined ( ) ;
238+ const url = new URL ( frameUrlStr ) ;
239+ const hash = new URLSearchParams ( url . hash . slice ( 1 ) ) ;
240+ assertCommonCallParameters ( url . searchParams , hash , user , room ) ;
241+
242+ expect ( hash . get ( "intent" ) ) . toEqual ( "join_existing" ) ;
243+ expect ( hash . get ( "skipLobby" ) ) . toEqual ( "true" ) ;
244+ } ,
245+ ) ;
204246 } ) ;
205247
206248 test . describe ( "DMs" , ( ) => {
@@ -253,7 +295,6 @@ test.describe("Element Call", () => {
253295
254296 test ( "should be able to join a call in progress" , async ( { page, user, bot, room, app } ) => {
255297 await app . viewRoomById ( room . roomId ) ;
256- // Allow bob to create a call
257298 await expect ( page . getByText ( "Bob joined the room" ) ) . toBeVisible ( ) ;
258299 // Fake a start of a call
259300 await sendRTCState ( bot , room . roomId ) ;
@@ -262,7 +303,6 @@ test.describe("Element Call", () => {
262303 // And test joining
263304 await button . click ( ) ;
264305 const frameUrlStr = await page . locator ( "iframe" ) . getAttribute ( "src" ) ;
265- console . log ( frameUrlStr ) ;
266306 await expect ( frameUrlStr ) . toBeDefined ( ) ;
267307 const url = new URL ( frameUrlStr ) ;
268308 const hash = new URLSearchParams ( url . hash . slice ( 1 ) ) ;
@@ -278,24 +318,31 @@ test.describe("Element Call", () => {
278318 { tag : [ "@screenshot" ] } ,
279319 async ( { page, user, bot, room, app } ) => {
280320 await app . viewRoomById ( room . roomId ) ;
281- // Allow bob to create a call
282321 await expect ( page . getByText ( "Bob joined the room" ) ) . toBeVisible ( ) ;
283322 // Fake a start of a call
284- await sendRTCState ( bot , room . roomId , "ring" ) ;
323+ await sendRTCState ( bot , room . roomId , "ring" , "video" ) ;
285324 const toast = page . locator ( ".mx_Toast_toast" ) ;
286- const button = toast . getByRole ( "button" , { name : "Join " } ) ;
325+ const button = toast . getByRole ( "button" , { name : "Accept " } ) ;
287326 if ( skipLobbyToggle ) {
288327 await toast . getByRole ( "switch" ) . check ( ) ;
289- await expect ( toast ) . toMatchScreenshot ( "incoming-call-dm-video-toast-checked.png" ) ;
290328 } else {
291329 await toast . getByRole ( "switch" ) . uncheck ( ) ;
292- await expect ( toast ) . toMatchScreenshot ( "incoming-call-dm-video-toast-unchecked.png" ) ;
293330 }
331+ await expect ( toast ) . toMatchScreenshot (
332+ `incoming-call-dm-video-toast-${ skipLobbyToggle ? "checked" : "unchecked" } .png` ,
333+ {
334+ // Hide UserId
335+ css : `
336+ .mx_IncomingCallToast_AvatarWithDetails span:nth-child(2) {
337+ opacity: 0;
338+ }
339+ ` ,
340+ } ,
341+ ) ;
294342
295343 // And test joining
296344 await button . click ( ) ;
297345 const frameUrlStr = await page . locator ( "iframe" ) . getAttribute ( "src" ) ;
298- console . log ( frameUrlStr ) ;
299346 await expect ( frameUrlStr ) . toBeDefined ( ) ;
300347 const url = new URL ( frameUrlStr ) ;
301348 const hash = new URLSearchParams ( url . hash . slice ( 1 ) ) ;
@@ -306,6 +353,39 @@ test.describe("Element Call", () => {
306353 } ,
307354 ) ;
308355 } ) ;
356+
357+ test (
358+ `should be able to join a call via incoming voice call toast` ,
359+ { tag : [ "@screenshot" ] } ,
360+ async ( { page, user, bot, room, app } ) => {
361+ await app . viewRoomById ( room . roomId ) ;
362+ await expect ( page . getByText ( "Bob joined the room" ) ) . toBeVisible ( ) ;
363+ // Fake a start of a call
364+ await sendRTCState ( bot , room . roomId , "ring" , "audio" ) ;
365+ const toast = page . locator ( ".mx_Toast_toast" ) ;
366+ const button = toast . getByRole ( "button" , { name : "Accept" } ) ;
367+
368+ await expect ( toast ) . toMatchScreenshot ( `incoming-call-dm-voice-toast.png` , {
369+ // Hide UserId
370+ css : `
371+ .mx_IncomingCallToast_AvatarWithDetails span:nth-child(2) {
372+ opacity: 0;
373+ }
374+ ` ,
375+ } ) ;
376+
377+ // And test joining
378+ await button . click ( ) ;
379+ const frameUrlStr = await page . locator ( "iframe" ) . getAttribute ( "src" ) ;
380+ await expect ( frameUrlStr ) . toBeDefined ( ) ;
381+ const url = new URL ( frameUrlStr ) ;
382+ const hash = new URLSearchParams ( url . hash . slice ( 1 ) ) ;
383+ assertCommonCallParameters ( url . searchParams , hash , user , room ) ;
384+
385+ expect ( hash . get ( "intent" ) ) . toEqual ( "join_existing_dm_voice" ) ;
386+ expect ( hash . get ( "skipLobby" ) ) . toEqual ( "true" ) ;
387+ } ,
388+ ) ;
309389 } ) ;
310390
311391 test . describe ( "Video Rooms" , ( ) => {
0 commit comments