@@ -8,17 +8,20 @@ Please see LICENSE files in the repository root for full details.
8
8
9
9
import React from "react" ;
10
10
import { render , screen , cleanup , fireEvent , waitFor } from "jest-matrix-react" ;
11
- import { mocked , type Mocked } from "jest-mock" ;
11
+ import { type Mock , mocked , type Mocked } from "jest-mock" ;
12
12
import {
13
13
Room ,
14
14
RoomStateEvent ,
15
15
type MatrixEvent ,
16
16
MatrixEventEvent ,
17
17
type MatrixClient ,
18
18
type RoomMember ,
19
+ EventType ,
20
+ RoomEvent ,
21
+ type IRoomTimelineData ,
19
22
} from "matrix-js-sdk/src/matrix" ;
20
23
import { type ClientWidgetApi , Widget } from "matrix-widget-api" ;
21
- import { type ICallNotifyContent } from "matrix-js-sdk/src/matrixrtc" ;
24
+ import { type IRTCNotificationContent } from "matrix-js-sdk/src/matrixrtc" ;
22
25
23
26
import {
24
27
useMockedCalls ,
@@ -27,6 +30,7 @@ import {
27
30
mkRoomMember ,
28
31
setupAsyncStoreWithClient ,
29
32
resetAsyncStoreWithClient ,
33
+ mkEvent ,
30
34
} from "../../test-utils" ;
31
35
import defaultDispatcher from "../../../src/dispatcher/dispatcher" ;
32
36
import { Action } from "../../../src/dispatcher/actions" ;
@@ -43,7 +47,8 @@ describe("IncomingCallToast", () => {
43
47
44
48
let client : Mocked < MatrixClient > ;
45
49
let room : Room ;
46
- let notifyContent : ICallNotifyContent ;
50
+ let notificationEvent : MatrixEvent ;
51
+
47
52
let alice : RoomMember ;
48
53
let bob : RoomMember ;
49
54
let call : MockedCall ;
@@ -64,10 +69,23 @@ describe("IncomingCallToast", () => {
64
69
document . body . appendChild ( audio ) ;
65
70
66
71
room = new Room ( "!1:example.org" , client , "@alice:example.org" ) ;
67
- notifyContent = {
68
- call_id : "" ,
69
- getRoomId : ( ) => room . roomId ,
70
- } as unknown as ICallNotifyContent ;
72
+ const ts = Date . now ( ) ;
73
+ const notificationContent = {
74
+ "notification_type" : "notification" ,
75
+ "m.relation" : { rel_type : "m.reference" , event_id : "$memberEventId" } ,
76
+ "m.mentions" : { user_ids : [ ] , room : true } ,
77
+ "lifetime" : 3000 ,
78
+ "sender_ts" : ts ,
79
+ } as unknown as IRTCNotificationContent ;
80
+ notificationEvent = mkEvent ( {
81
+ type : EventType . RTCNotification ,
82
+ user : "@userId:matrix.org" ,
83
+ content : notificationContent ,
84
+ room : room . roomId ,
85
+ ts,
86
+ id : "$notificationEventId" ,
87
+ event : true ,
88
+ } ) ;
71
89
alice = mkRoomMember ( room . roomId , "@alice:example.org" ) ;
72
90
bob = mkRoomMember ( room . roomId , "@bob:example.org" ) ;
73
91
@@ -104,8 +122,12 @@ describe("IncomingCallToast", () => {
104
122
} ) ;
105
123
106
124
const renderToast = ( ) => {
107
- call . event . getContent = ( ) => notifyContent as any ;
108
- render ( < IncomingCallToast notificationEvent = { call . event } /> ) ;
125
+ call . event . getContent = ( ) =>
126
+ ( {
127
+ call_id : "" ,
128
+ getRoomId : ( ) => room . roomId ,
129
+ } ) as any ;
130
+ render ( < IncomingCallToast notificationEvent = { notificationEvent } /> ) ;
109
131
} ;
110
132
111
133
it ( "correctly shows all the information" , ( ) => {
@@ -124,14 +146,13 @@ describe("IncomingCallToast", () => {
124
146
} ) ;
125
147
126
148
it ( "start ringing on ring notify event" , ( ) => {
127
- call . event . getContent = ( ) =>
128
- ( {
129
- ...notifyContent ,
130
- notify_type : "ring" ,
131
- } ) as any ;
149
+ const oldContent = notificationEvent . getContent ( ) as IRTCNotificationContent ;
150
+ ( notificationEvent as unknown as { getContent : ( ) => IRTCNotificationContent } ) . getContent = ( ) => {
151
+ return { ...oldContent , notification_type : "ring" } as IRTCNotificationContent ;
152
+ } ;
132
153
133
154
const playMock = jest . spyOn ( LegacyCallHandler . instance , "play" ) ;
134
- render ( < IncomingCallToast notificationEvent = { call . event } /> ) ;
155
+ render ( < IncomingCallToast notificationEvent = { notificationEvent } /> ) ;
135
156
expect ( playMock ) . toHaveBeenCalled ( ) ;
136
157
} ) ;
137
158
@@ -143,16 +164,18 @@ describe("IncomingCallToast", () => {
143
164
screen . getByText ( "Video" ) ;
144
165
145
166
screen . getByRole ( "button" , { name : "Join" } ) ;
167
+ screen . getByRole ( "button" , { name : "Decline" } ) ;
146
168
screen . getByRole ( "button" , { name : "Close" } ) ;
147
169
} ) ;
148
170
149
- it ( "joins the call and closes the toast" , async ( ) => {
171
+ it ( "opens the lobby and closes the toast when pressing on the toast" , async ( ) => {
150
172
renderToast ( ) ;
151
173
152
174
const dispatcherSpy = jest . fn ( ) ;
153
175
const dispatcherRef = defaultDispatcher . register ( dispatcherSpy ) ;
154
176
155
- fireEvent . click ( screen . getByRole ( "button" , { name : "Join" } ) ) ;
177
+ // click on the avatar (which is the example used for pressing on any area other than the buttons)
178
+ fireEvent . click ( screen . getByRole ( "presentation" , { name : "" } ) ) ;
156
179
await waitFor ( ( ) =>
157
180
expect ( dispatcherSpy ) . toHaveBeenCalledWith ( {
158
181
action : Action . ViewRoom ,
@@ -163,12 +186,38 @@ describe("IncomingCallToast", () => {
163
186
) ;
164
187
await waitFor ( ( ) =>
165
188
expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
166
- getIncomingCallToastKey ( notifyContent . call_id , room . roomId ) ,
189
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
190
+ ) ,
191
+ ) ;
192
+
193
+ defaultDispatcher . unregister ( dispatcherRef ) ;
194
+ } ) ;
195
+
196
+ it ( "opens the call directly and closes the toast when pressing on the join button" , async ( ) => {
197
+ renderToast ( ) ;
198
+
199
+ const dispatcherSpy = jest . fn ( ) ;
200
+ const dispatcherRef = defaultDispatcher . register ( dispatcherSpy ) ;
201
+
202
+ // click on the avatar (which is the example used for pressing on any area other than the buttons)
203
+ fireEvent . click ( screen . getByRole ( "button" , { name : "Join" } ) ) ;
204
+ await waitFor ( ( ) =>
205
+ expect ( dispatcherSpy ) . toHaveBeenCalledWith ( {
206
+ action : Action . ViewRoom ,
207
+ room_id : room . roomId ,
208
+ skipLobby : true ,
209
+ view_call : true ,
210
+ } ) ,
211
+ ) ;
212
+ await waitFor ( ( ) =>
213
+ expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
214
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
167
215
) ,
168
216
) ;
169
217
170
218
defaultDispatcher . unregister ( dispatcherRef ) ;
171
219
} ) ;
220
+
172
221
it ( "Dismiss toast if user starts call and skips lobby when using shift key click" , async ( ) => {
173
222
renderToast ( ) ;
174
223
@@ -186,7 +235,7 @@ describe("IncomingCallToast", () => {
186
235
) ;
187
236
await waitFor ( ( ) =>
188
237
expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
189
- getIncomingCallToastKey ( notifyContent . call_id , room . roomId ) ,
238
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
190
239
) ,
191
240
) ;
192
241
@@ -202,7 +251,7 @@ describe("IncomingCallToast", () => {
202
251
fireEvent . click ( screen . getByRole ( "button" , { name : "Close" } ) ) ;
203
252
await waitFor ( ( ) =>
204
253
expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
205
- getIncomingCallToastKey ( notifyContent . call_id , room . roomId ) ,
254
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
206
255
) ,
207
256
) ;
208
257
@@ -220,7 +269,7 @@ describe("IncomingCallToast", () => {
220
269
221
270
await waitFor ( ( ) =>
222
271
expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
223
- getIncomingCallToastKey ( notifyContent . call_id , room . roomId ) ,
272
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
224
273
) ,
225
274
) ;
226
275
} ) ;
@@ -233,7 +282,7 @@ describe("IncomingCallToast", () => {
233
282
234
283
await waitFor ( ( ) =>
235
284
expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
236
- getIncomingCallToastKey ( notifyContent . call_id , room . roomId ) ,
285
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
237
286
) ,
238
287
) ;
239
288
} ) ;
@@ -244,7 +293,82 @@ describe("IncomingCallToast", () => {
244
293
245
294
await waitFor ( ( ) =>
246
295
expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
247
- getIncomingCallToastKey ( notifyContent . call_id , room . roomId ) ,
296
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
297
+ ) ,
298
+ ) ;
299
+ } ) ;
300
+
301
+ it ( "closes toast when a decline event was received" , async ( ) => {
302
+ ( toastStore . dismissToast as Mock ) . mockReset ( ) ;
303
+ renderToast ( ) ;
304
+
305
+ room . emit (
306
+ RoomEvent . Timeline ,
307
+ mkEvent ( {
308
+ user : "@userId:matrix.org" ,
309
+ type : EventType . RTCDecline ,
310
+ content : { "m.relates_to" : { event_id : notificationEvent . getId ( ) ! , rel_type : "m.reference" } } ,
311
+ event : true ,
312
+ } ) ,
313
+ room ,
314
+ undefined ,
315
+ false ,
316
+ { } as unknown as IRoomTimelineData ,
317
+ ) ;
318
+
319
+ await waitFor ( ( ) =>
320
+ expect ( toastStore . dismissToast ) . toHaveBeenCalledWith (
321
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
322
+ ) ,
323
+ ) ;
324
+ } ) ;
325
+
326
+ it ( "does not close toast when a decline event for another user was received" , async ( ) => {
327
+ ( toastStore . dismissToast as Mock ) . mockReset ( ) ;
328
+ renderToast ( ) ;
329
+
330
+ room . emit (
331
+ RoomEvent . Timeline ,
332
+ mkEvent ( {
333
+ user : "@userIdNotMe:matrix.org" ,
334
+ type : EventType . RTCDecline ,
335
+ content : { "m.relates_to" : { event_id : notificationEvent . getId ( ) ! , rel_type : "m.reference" } } ,
336
+ event : true ,
337
+ } ) ,
338
+ room ,
339
+ undefined ,
340
+ false ,
341
+ { } as unknown as IRoomTimelineData ,
342
+ ) ;
343
+
344
+ await waitFor ( ( ) =>
345
+ expect ( toastStore . dismissToast ) . not . toHaveBeenCalledWith (
346
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
347
+ ) ,
348
+ ) ;
349
+ } ) ;
350
+
351
+ it ( "does not close toast when a decline event for another notification Event was received" , async ( ) => {
352
+ ( toastStore . dismissToast as Mock ) . mockReset ( ) ;
353
+ renderToast ( ) ;
354
+
355
+ room . emit (
356
+ RoomEvent . Timeline ,
357
+ mkEvent ( {
358
+ user : "@userId:matrix.org" ,
359
+ type : EventType . RTCDecline ,
360
+ content : { "m.relates_to" : { event_id : "$otherNotificationEventRelation" , rel_type : "m.reference" } } ,
361
+ event : true ,
362
+ } ) ,
363
+ room ,
364
+ undefined ,
365
+ false ,
366
+ { } as unknown as IRoomTimelineData ,
367
+ ) ;
368
+
369
+ await waitFor ( ( ) =>
370
+ expect ( toastStore . dismissToast ) . not . toHaveBeenCalledWith (
371
+ getIncomingCallToastKey ( notificationEvent . getId ( ) ! , room . roomId ) ,
248
372
) ,
249
373
) ;
250
374
} ) ;
0 commit comments