@@ -102,6 +102,7 @@ describe("MatrixRTCSessionManager", () => {
102
102
getContent : jest . fn ( ) . mockReturnValue ( { } ) ,
103
103
getSender : jest . fn ( ) . mockReturnValue ( "@mock:user.example" ) ,
104
104
getRoomId : jest . fn ( ) . mockReturnValue ( "!room:id" ) ,
105
+ isDecryptionFailure : jest . fn ( ) . mockReturnValue ( false ) ,
105
106
sender : {
106
107
userId : "@mock:user.example" ,
107
108
} ,
@@ -110,4 +111,93 @@ describe("MatrixRTCSessionManager", () => {
110
111
await new Promise ( process . nextTick ) ;
111
112
expect ( onCallEncryptionMock ) . toHaveBeenCalled ( ) ;
112
113
} ) ;
114
+
115
+ describe ( "event decryption" , ( ) => {
116
+ it ( "Retries decryption and processes success" , async ( ) => {
117
+ try {
118
+ jest . useFakeTimers ( ) ;
119
+ const room1 = makeMockRoom ( [ membershipTemplate ] ) ;
120
+ jest . spyOn ( client , "getRooms" ) . mockReturnValue ( [ room1 ] ) ;
121
+ jest . spyOn ( client , "getRoom" ) . mockReturnValue ( room1 ) ;
122
+
123
+ client . emit ( ClientEvent . Room , room1 ) ;
124
+ const onCallEncryptionMock = jest . fn ( ) ;
125
+ client . matrixRTC . getRoomSession ( room1 ) . onCallEncryption = onCallEncryptionMock ;
126
+ let isDecryptionFailure = true ;
127
+ client . decryptEventIfNeeded = jest
128
+ . fn ( )
129
+ . mockReturnValueOnce ( Promise . resolve ( ) )
130
+ . mockImplementation ( ( ) => {
131
+ isDecryptionFailure = false ;
132
+ return Promise . resolve ( ) ;
133
+ } ) ;
134
+ const timelineEvent = {
135
+ getType : jest . fn ( ) . mockReturnValue ( EventType . CallEncryptionKeysPrefix ) ,
136
+ getContent : jest . fn ( ) . mockReturnValue ( { } ) ,
137
+ getSender : jest . fn ( ) . mockReturnValue ( "@mock:user.example" ) ,
138
+ getRoomId : jest . fn ( ) . mockReturnValue ( "!room:id" ) ,
139
+ isDecryptionFailure : jest . fn ( ) . mockImplementation ( ( ) => isDecryptionFailure ) ,
140
+ getId : jest . fn ( ) . mockReturnValue ( "event_id" ) ,
141
+ sender : {
142
+ userId : "@mock:user.example" ,
143
+ } ,
144
+ } as unknown as MatrixEvent ;
145
+ client . emit ( RoomEvent . Timeline , timelineEvent , undefined , undefined , false , { } as IRoomTimelineData ) ;
146
+
147
+ expect ( client . decryptEventIfNeeded ) . toHaveBeenCalledTimes ( 1 ) ;
148
+ expect ( onCallEncryptionMock ) . toHaveBeenCalledTimes ( 0 ) ;
149
+
150
+ // should retry after one second:
151
+ await jest . advanceTimersByTimeAsync ( 1500 ) ;
152
+
153
+ expect ( client . decryptEventIfNeeded ) . toHaveBeenCalledTimes ( 2 ) ;
154
+ expect ( onCallEncryptionMock ) . toHaveBeenCalledTimes ( 1 ) ;
155
+ } finally {
156
+ jest . useRealTimers ( ) ;
157
+ }
158
+ } ) ;
159
+
160
+ it ( "Retries decryption and processes failure" , async ( ) => {
161
+ try {
162
+ jest . useFakeTimers ( ) ;
163
+ const room1 = makeMockRoom ( [ membershipTemplate ] ) ;
164
+ jest . spyOn ( client , "getRooms" ) . mockReturnValue ( [ room1 ] ) ;
165
+ jest . spyOn ( client , "getRoom" ) . mockReturnValue ( room1 ) ;
166
+
167
+ client . emit ( ClientEvent . Room , room1 ) ;
168
+ const onCallEncryptionMock = jest . fn ( ) ;
169
+ client . matrixRTC . getRoomSession ( room1 ) . onCallEncryption = onCallEncryptionMock ;
170
+ client . decryptEventIfNeeded = jest . fn ( ) . mockReturnValue ( Promise . resolve ( ) ) ;
171
+ const timelineEvent = {
172
+ getType : jest . fn ( ) . mockReturnValue ( EventType . CallEncryptionKeysPrefix ) ,
173
+ getContent : jest . fn ( ) . mockReturnValue ( { } ) ,
174
+ getSender : jest . fn ( ) . mockReturnValue ( "@mock:user.example" ) ,
175
+ getRoomId : jest . fn ( ) . mockReturnValue ( "!room:id" ) ,
176
+ isDecryptionFailure : jest . fn ( ) . mockReturnValue ( true ) , // always fail
177
+ getId : jest . fn ( ) . mockReturnValue ( "event_id" ) ,
178
+ sender : {
179
+ userId : "@mock:user.example" ,
180
+ } ,
181
+ } as unknown as MatrixEvent ;
182
+ client . emit ( RoomEvent . Timeline , timelineEvent , undefined , undefined , false , { } as IRoomTimelineData ) ;
183
+
184
+ expect ( client . decryptEventIfNeeded ) . toHaveBeenCalledTimes ( 1 ) ;
185
+ expect ( onCallEncryptionMock ) . toHaveBeenCalledTimes ( 0 ) ;
186
+
187
+ // should retry after one second:
188
+ await jest . advanceTimersByTimeAsync ( 1500 ) ;
189
+
190
+ expect ( client . decryptEventIfNeeded ) . toHaveBeenCalledTimes ( 2 ) ;
191
+ expect ( onCallEncryptionMock ) . toHaveBeenCalledTimes ( 0 ) ;
192
+
193
+ // doesn't retry again:
194
+ await jest . advanceTimersByTimeAsync ( 1500 ) ;
195
+
196
+ expect ( client . decryptEventIfNeeded ) . toHaveBeenCalledTimes ( 2 ) ;
197
+ expect ( onCallEncryptionMock ) . toHaveBeenCalledTimes ( 0 ) ;
198
+ } finally {
199
+ jest . useRealTimers ( ) ;
200
+ }
201
+ } ) ;
202
+ } ) ;
113
203
} ) ;
0 commit comments