@@ -222,6 +222,27 @@ describe("MatrixRTCSession", () => {
222222 } ) ;
223223 } ) ;
224224
225+ describe ( "getConsensusCallIntent" , ( ) => {
226+ it . each ( [
227+ [ undefined , undefined , undefined ] ,
228+ [ "audio" , undefined , "audio" ] ,
229+ [ undefined , "audio" , "audio" ] ,
230+ [ "audio" , "audio" , "audio" ] ,
231+ [ "audio" , "video" , undefined ] ,
232+ ] ) ( "gets correct consensus for %s + %s = %s" , ( intentA , intentB , result ) => {
233+ jest . useFakeTimers ( ) ;
234+ jest . setSystemTime ( 4000 ) ;
235+ const mockRoom = makeMockRoom ( [
236+ Object . assign ( { } , membershipTemplate , { "m.call.intent" : intentA } ) ,
237+ Object . assign ( { } , membershipTemplate , { "m.call.intent" : intentB } ) ,
238+ ] ) ;
239+
240+ sess = MatrixRTCSession . sessionForRoom ( client , mockRoom , callSession ) ;
241+ expect ( sess . getConsensusCallIntent ( ) ) . toEqual ( result ) ;
242+ jest . useRealTimers ( ) ;
243+ } ) ;
244+ } ) ;
245+
225246 describe ( "getsActiveFocus" , ( ) => {
226247 const firstPreferredFocus = {
227248 type : "livekit" ,
@@ -370,6 +391,79 @@ describe("MatrixRTCSession", () => {
370391 ) ;
371392 } ) ;
372393
394+ it ( "sends a notification with a intent when starting a call and emits DidSendCallNotification" , async ( ) => {
395+ // Simulate a join, including the update to the room state
396+ // Ensure sendEvent returns event IDs so the DidSendCallNotification payload includes them
397+ sendEventMock
398+ . mockResolvedValueOnce ( { event_id : "legacy-evt" } )
399+ . mockResolvedValueOnce ( { event_id : "new-evt" } ) ;
400+ const didSendEventFn = jest . fn ( ) ;
401+ sess ! . once ( MatrixRTCSessionEvent . DidSendCallNotification , didSendEventFn ) ;
402+ // Create an additional listener to create a promise that resolves after the emission.
403+ const didSendNotification = new Promise ( ( resolve ) => {
404+ sess ! . once ( MatrixRTCSessionEvent . DidSendCallNotification , resolve ) ;
405+ } ) ;
406+
407+ sess ! . joinRoomSession ( [ mockFocus ] , mockFocus , { notificationType : "ring" , callIntent : "audio" } ) ;
408+ await Promise . race ( [ sentStateEvent , new Promise ( ( resolve ) => setTimeout ( resolve , 5000 ) ) ] ) ;
409+
410+ mockRoomState ( mockRoom , [
411+ {
412+ ...membershipTemplate ,
413+ "user_id" : client . getUserId ( ) ! ,
414+ // This is what triggers the intent type on the notification event.
415+ "m.call.intent" : "audio" ,
416+ } ,
417+ ] ) ;
418+
419+ sess ! . onRTCSessionMemberUpdate ( ) ;
420+ const ownMembershipId = sess ?. memberships [ 0 ] . eventId ;
421+ expect ( sess ! . getConsensusCallIntent ( ) ) . toEqual ( "audio" ) ;
422+
423+ expect ( client . sendEvent ) . toHaveBeenCalledWith ( mockRoom ! . roomId , EventType . RTCNotification , {
424+ "m.mentions" : { user_ids : [ ] , room : true } ,
425+ "notification_type" : "ring" ,
426+ "m.call.intent" : "audio" ,
427+ "m.relates_to" : {
428+ event_id : ownMembershipId ,
429+ rel_type : "m.reference" ,
430+ } ,
431+ "lifetime" : 30000 ,
432+ "sender_ts" : expect . any ( Number ) ,
433+ } ) ;
434+
435+ // Check if deprecated notify event is also sent.
436+ expect ( client . sendEvent ) . toHaveBeenCalledWith ( mockRoom ! . roomId , EventType . CallNotify , {
437+ "application" : "m.call" ,
438+ "m.mentions" : { user_ids : [ ] , room : true } ,
439+ "notify_type" : "ring" ,
440+ "call_id" : "" ,
441+ } ) ;
442+ await didSendNotification ;
443+ // And ensure we emitted the DidSendCallNotification event with both payloads
444+ expect ( didSendEventFn ) . toHaveBeenCalledWith (
445+ {
446+ "event_id" : "new-evt" ,
447+ "lifetime" : 30000 ,
448+ "m.mentions" : { room : true , user_ids : [ ] } ,
449+ "m.relates_to" : {
450+ event_id : expect . any ( String ) ,
451+ rel_type : "m.reference" ,
452+ } ,
453+ "notification_type" : "ring" ,
454+ "m.call.intent" : "audio" ,
455+ "sender_ts" : expect . any ( Number ) ,
456+ } ,
457+ {
458+ "application" : "m.call" ,
459+ "call_id" : "" ,
460+ "event_id" : "legacy-evt" ,
461+ "m.mentions" : { room : true , user_ids : [ ] } ,
462+ "notify_type" : "ring" ,
463+ } ,
464+ ) ;
465+ } ) ;
466+
373467 it ( "doesn't send a notification when joining an existing call" , async ( ) => {
374468 // Add another member to the call so that it is considered an existing call
375469 mockRoomState ( mockRoom , [ membershipTemplate ] ) ;
0 commit comments