@@ -20,6 +20,7 @@ import {
2020 RoomEvent ,
2121 type IRoomTimelineData ,
2222 type ISendEventResponse ,
23+ type IContent ,
2324} from "matrix-js-sdk/src/matrix" ;
2425import { Widget } from "matrix-widget-api" ;
2526import { type IRTCNotificationContent } from "matrix-js-sdk/src/matrixrtc" ;
@@ -50,12 +51,32 @@ import LegacyCallHandler, { AudioID } from "../../../src/LegacyCallHandler";
5051import { CallEvent } from "../../../src/models/Call" ;
5152import { type WidgetMessaging } from "../../../src/stores/widgets/WidgetMessaging" ;
5253
54+ function makeNotificationEvent ( room : Room , content : IContent = { } ) : MatrixEvent {
55+ const ts = Date . now ( ) ;
56+ const notificationContent = {
57+ "notification_type" : "notification" ,
58+ "m.relation" : { rel_type : "m.reference" , event_id : "$memberEventId" } ,
59+ "m.mentions" : { user_ids : [ ] , room : true } ,
60+ "lifetime" : 3000 ,
61+ "sender_ts" : ts ,
62+ ...content ,
63+ } as unknown as IRTCNotificationContent ;
64+ return mkEvent ( {
65+ type : EventType . RTCNotification ,
66+ user : "@userId:matrix.org" ,
67+ content : notificationContent ,
68+ room : room . roomId ,
69+ ts,
70+ id : "$notificationEventId" ,
71+ event : true ,
72+ } ) ;
73+ }
74+
5375describe ( "IncomingCallToast" , ( ) => {
5476 useMockedCalls ( ) ;
5577
5678 let client : Mocked < MatrixClient > ;
5779 let room : Room ;
58- let notificationEvent : MatrixEvent ;
5980
6081 let alice : RoomMember ;
6182 let bob : RoomMember ;
@@ -77,23 +98,6 @@ describe("IncomingCallToast", () => {
7798 document . body . appendChild ( audio ) ;
7899
79100 room = new Room ( "!1:example.org" , client , "@alice:example.org" ) ;
80- const ts = Date . now ( ) ;
81- const notificationContent = {
82- "notification_type" : "notification" ,
83- "m.relation" : { rel_type : "m.reference" , event_id : "$memberEventId" } ,
84- "m.mentions" : { user_ids : [ ] , room : true } ,
85- "lifetime" : 3000 ,
86- "sender_ts" : ts ,
87- } as unknown as IRTCNotificationContent ;
88- notificationEvent = mkEvent ( {
89- type : EventType . RTCNotification ,
90- user : "@userId:matrix.org" ,
91- content : notificationContent ,
92- room : room . roomId ,
93- ts,
94- id : "$notificationEventId" ,
95- event : true ,
96- } ) ;
97101 alice = mkRoomMember ( room . roomId , "@alice:example.org" ) ;
98102 bob = mkRoomMember ( room . roomId , "@bob:example.org" ) ;
99103
@@ -130,7 +134,7 @@ describe("IncomingCallToast", () => {
130134 jest . restoreAllMocks ( ) ;
131135 } ) ;
132136
133- const renderToast = ( ) : string => {
137+ const renderToast = ( notificationEvent : MatrixEvent = makeNotificationEvent ( room ) ) : string => {
134138 const callId = randomUUID ( ) ;
135139 call . event . getContent = ( ) =>
136140 ( {
@@ -146,29 +150,52 @@ describe("IncomingCallToast", () => {
146150 return callId ;
147151 } ;
148152
149- it ( "correctly shows all the information ", ( ) => {
153+ it . each ( [ "video" , "voice" ] ) ( " shows information for a group %s call ", ( callType : string ) => {
150154 call . participants = new Map ( [
151155 [ alice , new Set ( "a" ) ] ,
152156 [ bob , new Set ( [ "b1" , "b2" ] ) ] ,
153157 ] ) ;
154- renderToast ( ) ;
158+ const notificationEvent = makeNotificationEvent ( room , {
159+ "m.call.intent" : callType === "voice" ? "audio" : "video" ,
160+ } ) ;
161+ renderToast ( notificationEvent ) ;
155162
156163 screen . getByText ( "Group call started" ) ;
157- screen . getByLabelText ( "Video call" ) ;
164+ screen . getByLabelText ( callType === "voice" ? "Voice call" : "Video call" ) ;
158165 screen . getByLabelText ( "@alice:example.org" ) ;
159166 screen . getByLabelText ( "@bob:example.org" ) ;
167+ screen . getByText ( "on the call" ) ;
160168
161169 screen . getByRole ( "button" , { name : "Join" } ) ;
162170 screen . getByRole ( "button" , { name : "Ignore" } ) ;
163171 screen . getByRole ( "button" , { name : "Expand" } ) ;
164172 } ) ;
165173
166- it ( "start ringing on ring notify event" , ( ) => {
167- const oldContent = notificationEvent . getContent ( ) as IRTCNotificationContent ;
168- ( notificationEvent as unknown as { getContent : ( ) => IRTCNotificationContent } ) . getContent = ( ) => {
169- return { ...oldContent , notification_type : "ring" } as IRTCNotificationContent ;
170- } ;
174+ it . each ( [ "video" , "voice" ] ) ( "shows information for a DM %s call" , ( callType : string ) => {
175+ mocked ( dmRoomMap . getUserIdForRoomId ) . mockImplementation ( ( roomId ) =>
176+ roomId === room . roomId ? alice . userId : undefined ,
177+ ) ;
178+ try {
179+ call . participants = new Map ( [ [ alice , new Set ( "a" ) ] ] ) ;
180+ const notificationEvent = makeNotificationEvent ( room , {
181+ "m.call.intent" : callType === "voice" ? "audio" : "video" ,
182+ } ) ;
183+ renderToast ( notificationEvent ) ;
184+
185+ screen . getByText ( callType === "voice" ? "Incoming voice call" : "Incoming video call" ) ;
186+ screen . getByLabelText ( callType === "voice" ? "Voice call" : "Video call" ) ;
187+ screen . getByLabelText ( "@alice:example.org" ) ;
188+
189+ screen . getByRole ( "button" , { name : "Join" } ) ;
190+ screen . getByRole ( "button" , { name : "Ignore" } ) ;
191+ screen . getByRole ( "button" , { name : "Expand" } ) ;
192+ } finally {
193+ mocked ( dmRoomMap . getUserIdForRoomId ) . mockReset ( ) ;
194+ }
195+ } ) ;
171196
197+ it ( "start ringing on ring notify event" , ( ) => {
198+ const notificationEvent = makeNotificationEvent ( room , { notification_type : "ring" } ) ;
172199 const playMock = jest . spyOn ( LegacyCallHandler . instance , "play" ) ;
173200 render ( < IncomingCallToast notificationEvent = { notificationEvent } toastKey = "" /> ) ;
174201 expect ( playMock ) . toHaveBeenCalled ( ) ;
@@ -180,6 +207,7 @@ describe("IncomingCallToast", () => {
180207
181208 screen . getByText ( "Group call started" ) ;
182209 screen . getByLabelText ( "Video call" ) ;
210+ expect ( screen . queryByText ( "on the call" ) ) . toBe ( null ) ;
183211
184212 screen . getByRole ( "button" , { name : "Join" } ) ;
185213 screen . getByRole ( "button" , { name : "Ignore" } ) ;
@@ -328,7 +356,8 @@ describe("IncomingCallToast", () => {
328356 } ) ;
329357
330358 it ( "closes toast when the notification event is redacted" , async ( ) => {
331- const callId = renderToast ( ) ;
359+ const notificationEvent = makeNotificationEvent ( room ) ;
360+ const callId = renderToast ( notificationEvent ) ;
332361
333362 room . emit ( MatrixEventEvent . BeforeRedaction , notificationEvent , { } as unknown as MatrixEvent ) ;
334363
@@ -347,7 +376,8 @@ describe("IncomingCallToast", () => {
347376 } ) ;
348377
349378 it ( "closes toast when a decline event was received" , async ( ) => {
350- const callId = renderToast ( ) ;
379+ const notificationEvent = makeNotificationEvent ( room ) ;
380+ const callId = renderToast ( notificationEvent ) ;
351381
352382 room . emit (
353383 RoomEvent . Timeline ,
@@ -369,7 +399,8 @@ describe("IncomingCallToast", () => {
369399 } ) ;
370400
371401 it ( "does not close toast when a decline event for another user was received" , async ( ) => {
372- const callId = renderToast ( ) ;
402+ const notificationEvent = makeNotificationEvent ( room ) ;
403+ const callId = renderToast ( notificationEvent ) ;
373404
374405 room . emit (
375406 RoomEvent . Timeline ,
@@ -434,6 +465,7 @@ describe("IncomingCallToast", () => {
434465 } ) ;
435466
436467 it ( "getNotificationEventSendTs returns the correct ts" , ( ) => {
468+ const notificationEvent = makeNotificationEvent ( room ) ;
437469 const eventOriginServerTs = mkEvent ( {
438470 user : "@userId:matrix.org" ,
439471 type : EventType . RTCNotification ,
0 commit comments