@@ -864,7 +864,64 @@ describe("MatrixRTCSession", () => {
864864 expect ( client . cancelPendingEvent ) . toHaveBeenCalledWith ( eventSentinel ) ;
865865 } ) ;
866866
867- it ( "Re-sends key if a new member joins" , async ( ) => {
867+ it ( "re-sends key if a new member joins even if a key rotation is in progress" , async ( ) => {
868+ jest . useFakeTimers ( ) ;
869+ try {
870+ // session with two members
871+ const member2 = Object . assign ( { } , membershipTemplate , {
872+ device_id : "BBBBBBB" ,
873+ } ) ;
874+ const mockRoom = makeMockRoom ( [ membershipTemplate , member2 ] ) ;
875+ sess = MatrixRTCSession . roomSessionForRoom ( client , mockRoom ) ;
876+
877+ // joining will trigger an initial key send
878+ const keysSentPromise1 = new Promise < EncryptionKeysEventContent > ( ( resolve ) => {
879+ sendEventMock . mockImplementation ( ( _roomId , _evType , payload ) => resolve ( payload ) ) ;
880+ } ) ;
881+ sess . joinRoomSession ( [ mockFocus ] , mockFocus , {
882+ manageMediaKeys : true ,
883+ updateEncryptionKeyThrottle : 1000 ,
884+ makeKeyDelay : 3000 ,
885+ } ) ;
886+ await keysSentPromise1 ;
887+ expect ( sess ! . statistics . counters . roomEventEncryptionKeysSent ) . toEqual ( 1 ) ;
888+
889+ // member2 leaves triggering key rotation
890+ mockRoom . getLiveTimeline ( ) . getState = jest
891+ . fn ( )
892+ . mockReturnValue ( makeMockRoomState ( [ membershipTemplate ] , mockRoom . roomId ) ) ;
893+ sess . onMembershipUpdate ( ) ;
894+
895+ // member2 re-joins which should trigger an immediate re-send
896+ const keysSentPromise2 = new Promise < EncryptionKeysEventContent > ( ( resolve ) => {
897+ sendEventMock . mockImplementation ( ( _roomId , _evType , payload ) => resolve ( payload ) ) ;
898+ } ) ;
899+ mockRoom . getLiveTimeline ( ) . getState = jest
900+ . fn ( )
901+ . mockReturnValue ( makeMockRoomState ( [ membershipTemplate , member2 ] , mockRoom . roomId ) ) ;
902+ sess . onMembershipUpdate ( ) ;
903+ // but, that immediate resend is throttled so we need to wait a bit
904+ jest . advanceTimersByTime ( 1000 ) ;
905+ const { keys } = await keysSentPromise2 ;
906+ expect ( sess ! . statistics . counters . roomEventEncryptionKeysSent ) . toEqual ( 2 ) ;
907+ // key index should still be the original: 0
908+ expect ( keys [ 0 ] . index ) . toEqual ( 0 ) ;
909+
910+ // check that the key rotation actually happens
911+ const keysSentPromise3 = new Promise < EncryptionKeysEventContent > ( ( resolve ) => {
912+ sendEventMock . mockImplementation ( ( _roomId , _evType , payload ) => resolve ( payload ) ) ;
913+ } ) ;
914+ jest . advanceTimersByTime ( 2000 ) ;
915+ const { keys : rotatedKeys } = await keysSentPromise3 ;
916+ expect ( sess ! . statistics . counters . roomEventEncryptionKeysSent ) . toEqual ( 3 ) ;
917+ // key index should now be the rotated one: 1
918+ expect ( rotatedKeys [ 0 ] . index ) . toEqual ( 1 ) ;
919+ } finally {
920+ jest . useRealTimers ( ) ;
921+ }
922+ } ) ;
923+
924+ it ( "re-sends key if a new member joins" , async ( ) => {
868925 jest . useFakeTimers ( ) ;
869926 try {
870927 const mockRoom = makeMockRoom ( [ membershipTemplate ] ) ;
0 commit comments