@@ -16,7 +16,11 @@ limitations under the License.
16
16
17
17
import { EventTimeline , EventType , MatrixClient , MatrixError , MatrixEvent , Room } from "../../../src" ;
18
18
import { KnownMembership } from "../../../src/@types/membership" ;
19
- import { CallMembershipData } from "../../../src/matrixrtc/CallMembership" ;
19
+ import {
20
+ CallMembershipData ,
21
+ CallMembershipDataLegacy ,
22
+ SessionMembershipData ,
23
+ } from "../../../src/matrixrtc/CallMembership" ;
20
24
import { MatrixRTCSession , MatrixRTCSessionEvent } from "../../../src/matrixrtc/MatrixRTCSession" ;
21
25
import { EncryptionKeysEventContent } from "../../../src/matrixrtc/types" ;
22
26
import { randomString } from "../../../src/randomstring" ;
@@ -99,22 +103,33 @@ describe("MatrixRTCSession", () => {
99
103
} ) ;
100
104
101
105
it ( "safely ignores events with no memberships section" , ( ) => {
106
+ const roomId = randomString ( 8 ) ;
107
+ const event = {
108
+ getType : jest . fn ( ) . mockReturnValue ( EventType . GroupCallMemberPrefix ) ,
109
+ getContent : jest . fn ( ) . mockReturnValue ( { } ) ,
110
+ getSender : jest . fn ( ) . mockReturnValue ( "@mock:user.example" ) ,
111
+ getTs : jest . fn ( ) . mockReturnValue ( 1000 ) ,
112
+ getLocalAge : jest . fn ( ) . mockReturnValue ( 0 ) ,
113
+ } ;
102
114
const mockRoom = {
103
115
...makeMockRoom ( [ ] ) ,
104
- roomId : randomString ( 8 ) ,
116
+ roomId,
105
117
getLiveTimeline : jest . fn ( ) . mockReturnValue ( {
106
118
getState : jest . fn ( ) . mockReturnValue ( {
107
119
on : jest . fn ( ) ,
108
120
off : jest . fn ( ) ,
109
- getStateEvents : ( _type : string , _stateKey : string ) => [
110
- {
111
- getType : jest . fn ( ) . mockReturnValue ( EventType . GroupCallMemberPrefix ) ,
112
- getContent : jest . fn ( ) . mockReturnValue ( { } ) ,
113
- getSender : jest . fn ( ) . mockReturnValue ( "@mock:user.example" ) ,
114
- getTs : jest . fn ( ) . mockReturnValue ( 1000 ) ,
115
- getLocalAge : jest . fn ( ) . mockReturnValue ( 0 ) ,
116
- } ,
117
- ] ,
121
+ getStateEvents : ( _type : string , _stateKey : string ) => [ event ] ,
122
+ events : new Map ( [
123
+ [
124
+ EventType . GroupCallMemberPrefix ,
125
+ {
126
+ size : ( ) => true ,
127
+ has : ( _stateKey : string ) => true ,
128
+ get : ( _stateKey : string ) => event ,
129
+ values : ( ) => [ event ] ,
130
+ } ,
131
+ ] ,
132
+ ] ) ,
118
133
} ) ,
119
134
} ) ,
120
135
} ;
@@ -123,22 +138,33 @@ describe("MatrixRTCSession", () => {
123
138
} ) ;
124
139
125
140
it ( "safely ignores events with junk memberships section" , ( ) => {
141
+ const roomId = randomString ( 8 ) ;
142
+ const event = {
143
+ getType : jest . fn ( ) . mockReturnValue ( EventType . GroupCallMemberPrefix ) ,
144
+ getContent : jest . fn ( ) . mockReturnValue ( { memberships : [ "i am a fish" ] } ) ,
145
+ getSender : jest . fn ( ) . mockReturnValue ( "@mock:user.example" ) ,
146
+ getTs : jest . fn ( ) . mockReturnValue ( 1000 ) ,
147
+ getLocalAge : jest . fn ( ) . mockReturnValue ( 0 ) ,
148
+ } ;
126
149
const mockRoom = {
127
150
...makeMockRoom ( [ ] ) ,
128
- roomId : randomString ( 8 ) ,
151
+ roomId,
129
152
getLiveTimeline : jest . fn ( ) . mockReturnValue ( {
130
153
getState : jest . fn ( ) . mockReturnValue ( {
131
154
on : jest . fn ( ) ,
132
155
off : jest . fn ( ) ,
133
- getStateEvents : ( _type : string , _stateKey : string ) => [
134
- {
135
- getType : jest . fn ( ) . mockReturnValue ( EventType . GroupCallMemberPrefix ) ,
136
- getContent : jest . fn ( ) . mockReturnValue ( { memberships : "i am a fish" } ) ,
137
- getSender : jest . fn ( ) . mockReturnValue ( "@mock:user.example" ) ,
138
- getTs : jest . fn ( ) . mockReturnValue ( 1000 ) ,
139
- getLocalAge : jest . fn ( ) . mockReturnValue ( 0 ) ,
140
- } ,
141
- ] ,
156
+ getStateEvents : ( _type : string , _stateKey : string ) => [ event ] ,
157
+ events : new Map ( [
158
+ [
159
+ EventType . GroupCallMemberPrefix ,
160
+ {
161
+ size : ( ) => true ,
162
+ has : ( _stateKey : string ) => true ,
163
+ get : ( _stateKey : string ) => event ,
164
+ values : ( ) => [ event ] ,
165
+ } ,
166
+ ] ,
167
+ ] ) ,
142
168
} ) ,
143
169
} ) ,
144
170
} ;
@@ -186,6 +212,67 @@ describe("MatrixRTCSession", () => {
186
212
expect ( sess . memberships ) . toHaveLength ( 0 ) ;
187
213
} ) ;
188
214
215
+ describe ( "updateCallMembershipEvent" , ( ) => {
216
+ const mockFocus = { type : "livekit" , livekit_service_url : "https://test.org" } ;
217
+ const joinSessionConfig = { useLegacyMemberEvents : false } ;
218
+
219
+ const legacyMembershipData : CallMembershipDataLegacy = {
220
+ call_id : "" ,
221
+ scope : "m.room" ,
222
+ application : "m.call" ,
223
+ device_id : "AAAAAAA_legacy" ,
224
+ expires : 60 * 60 * 1000 ,
225
+ membershipID : "bloop" ,
226
+ foci_active : [ mockFocus ] ,
227
+ } ;
228
+
229
+ const expiredLegacyMembershipData : CallMembershipDataLegacy = {
230
+ ...legacyMembershipData ,
231
+ device_id : "AAAAAAA_legacy_expired" ,
232
+ expires : 0 ,
233
+ } ;
234
+
235
+ const sessionMembershipData : SessionMembershipData = {
236
+ call_id : "" ,
237
+ scope : "m.room" ,
238
+ application : "m.call" ,
239
+ device_id : "AAAAAAA_session" ,
240
+ focus_active : mockFocus ,
241
+ foci_preferred : [ mockFocus ] ,
242
+ } ;
243
+
244
+ function testSession (
245
+ membershipData : CallMembershipData [ ] | SessionMembershipData ,
246
+ shouldUseLegacy : boolean ,
247
+ ) : void {
248
+ sess = MatrixRTCSession . roomSessionForRoom ( client , makeMockRoom ( membershipData ) ) ;
249
+
250
+ const makeNewLegacyMembershipsMock = jest . spyOn ( sess as any , "makeNewLegacyMemberships" ) ;
251
+ const makeNewMembershipMock = jest . spyOn ( sess as any , "makeNewMembership" ) ;
252
+
253
+ sess . joinRoomSession ( [ mockFocus ] , mockFocus , joinSessionConfig ) ;
254
+
255
+ expect ( makeNewLegacyMembershipsMock ) . toHaveBeenCalledTimes ( shouldUseLegacy ? 1 : 0 ) ;
256
+ expect ( makeNewMembershipMock ) . toHaveBeenCalledTimes ( shouldUseLegacy ? 0 : 1 ) ;
257
+ }
258
+
259
+ it ( "uses legacy events if there are any active legacy calls" , ( ) => {
260
+ testSession ( [ expiredLegacyMembershipData , legacyMembershipData , sessionMembershipData ] , true ) ;
261
+ } ) ;
262
+
263
+ it ( 'uses legacy events if a non-legacy call is in a "memberships" array' , ( ) => {
264
+ testSession ( [ sessionMembershipData ] , true ) ;
265
+ } ) ;
266
+
267
+ it ( "uses non-legacy events if all legacy calls are expired" , ( ) => {
268
+ testSession ( [ expiredLegacyMembershipData ] , false ) ;
269
+ } ) ;
270
+
271
+ it ( "uses non-legacy events if there are only non-legacy calls" , ( ) => {
272
+ testSession ( sessionMembershipData , false ) ;
273
+ } ) ;
274
+ } ) ;
275
+
189
276
describe ( "getOldestMembership" , ( ) => {
190
277
it ( "returns the oldest membership event" , ( ) => {
191
278
const mockRoom = makeMockRoom ( [
@@ -340,9 +427,20 @@ describe("MatrixRTCSession", () => {
340
427
341
428
// definitely should have renewed by 1 second before the expiry!
342
429
const timeElapsed = 60 * 60 * 1000 - 1000 ;
343
- mockRoom . getLiveTimeline ( ) . getState ( EventTimeline . FORWARDS ) ! . getStateEvents = jest
344
- . fn ( )
345
- . mockReturnValue ( mockRTCEvent ( eventContent . memberships , mockRoom . roomId , timeElapsed ) ) ;
430
+ const event = mockRTCEvent ( eventContent . memberships , mockRoom . roomId , timeElapsed ) ;
431
+ const getState = mockRoom . getLiveTimeline ( ) . getState ( EventTimeline . FORWARDS ) ! ;
432
+ getState . getStateEvents = jest . fn ( ) . mockReturnValue ( event ) ;
433
+ getState . events = new Map ( [
434
+ [
435
+ event . getType ( ) ,
436
+ {
437
+ size : ( ) => true ,
438
+ has : ( _stateKey : string ) => true ,
439
+ get : ( _stateKey : string ) => event ,
440
+ values : ( ) => [ event ] ,
441
+ } as unknown as Map < string , MatrixEvent > ,
442
+ ] ,
443
+ ] ) ;
346
444
347
445
const eventReSentPromise = new Promise < Record < string , any > > ( ( r ) => {
348
446
resolveFn = ( _roomId : string , _type : string , val : Record < string , any > ) => {
0 commit comments