@@ -60,15 +60,21 @@ class MockWidgetApi extends EventEmitter {
6060 public requestCapabilityToSendToDevice = jest . fn ( ) ;
6161 public requestCapabilityToReceiveToDevice = jest . fn ( ) ;
6262 public sendRoomEvent = jest . fn (
63- ( eventType : string , content : unknown , roomId ?: string , futureTimeout ?: number , futureGroupId ?: string ) =>
63+ (
64+ eventType : string ,
65+ content : unknown ,
66+ roomId ?: string ,
67+ futureTimeout ?: number ,
68+ futureGroupId ?: string
69+ ) =>
6470 futureTimeout === undefined && futureGroupId === undefined
6571 ? { event_id : `$${ Math . random ( ) } ` }
6672 : {
6773 future_group_id : futureGroupId ?? `fg-${ Math . random ( ) } ` ,
6874 send_token : `st-${ Math . random ( ) } ` ,
6975 cancel_token : `ct-${ Math . random ( ) } ` ,
7076 refresh_token : `rt-${ Math . random ( ) } ` ,
71- } ,
77+ }
7278 ) ;
7379 public sendStateEvent = jest . fn (
7480 (
@@ -86,7 +92,7 @@ class MockWidgetApi extends EventEmitter {
8692 send_token : `st-${ Math . random ( ) } ` ,
8793 cancel_token : `ct-${ Math . random ( ) } ` ,
8894 refresh_token : `rt-${ Math . random ( ) } ` ,
89- } ,
95+ }
9096 ) ;
9197 public sendToDevice = jest . fn ( ) ;
9298 public requestOpenIDConnectToken = jest . fn ( ( ) => {
@@ -188,102 +194,173 @@ describe("RoomWidgetClient", () => {
188194 } ) ;
189195
190196 describe ( "futures" , ( ) => {
191- const doesServerSupportUnstableFeatureMock = jest . fn ( ( feature ) =>
192- Promise . resolve ( feature === "org.matrix.msc4140" ) ,
193- ) ;
197+ describe ( "when supported" , ( ) => {
198+ const doesServerSupportUnstableFeatureMock = jest . fn ( ( feature ) =>
199+ Promise . resolve ( feature === "org.matrix.msc4140" )
200+ ) ;
194201
195- beforeAll ( ( ) => {
196- MatrixClient . prototype . doesServerSupportUnstableFeature = doesServerSupportUnstableFeatureMock ;
197- } ) ;
202+ beforeAll ( ( ) => {
203+ MatrixClient . prototype . doesServerSupportUnstableFeature = doesServerSupportUnstableFeatureMock ;
204+ } ) ;
198205
199- afterAll ( ( ) => {
200- doesServerSupportUnstableFeatureMock . mockClear ( ) ;
201- } ) ;
206+ afterAll ( ( ) => {
207+ doesServerSupportUnstableFeatureMock . mockReset ( ) ;
208+ } ) ;
202209
203- it ( "sends futures in a new group for message events" , async ( ) => {
204- await makeClient ( { sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
205- expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
206- expect ( widgetApi . requestCapabilityToSendEvent ) . toHaveBeenCalledWith ( "org.matrix.rageshake_request" ) ;
207- const futureOpts = {
208- future_timeout : 2000 ,
209- } ;
210- await client . _unstable_sendFuture ( "!1:example.org" , futureOpts , null , "org.matrix.rageshake_request" , {
211- request_id : 123 ,
210+ it ( "sends futures in a new group for message events" , async ( ) => {
211+ await makeClient ( { sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
212+ expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
213+ expect ( widgetApi . requestCapabilityToSendEvent ) . toHaveBeenCalledWith ( "org.matrix.rageshake_request" ) ;
214+ await client . _unstable_sendFuture (
215+ "!1:example.org" ,
216+ { future_timeout : 2000 } ,
217+ null ,
218+ "org.matrix.rageshake_request" ,
219+ { request_id : 123 } ,
220+ ) ;
221+ expect ( widgetApi . sendRoomEvent ) . toHaveBeenCalledWith (
222+ "org.matrix.rageshake_request" ,
223+ { request_id : 123 } ,
224+ "!1:example.org" ,
225+ 2000 ,
226+ undefined ,
227+ ) ;
212228 } ) ;
213- expect ( widgetApi . sendRoomEvent ) . toHaveBeenCalledWith (
214- "org.matrix.rageshake_request" ,
215- { request_id : 123 } ,
216- "!1:example.org" ,
217- futureOpts . future_timeout ,
218- undefined ,
219- ) ;
220- } ) ;
221229
222- it ( "sends action futures in an existing group for message events" , async ( ) => {
223- await makeClient ( { sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
224- expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
225- expect ( widgetApi . requestCapabilityToSendEvent ) . toHaveBeenCalledWith ( "org.matrix.rageshake_request" ) ;
226- const futureOpts = {
227- future_group_id : "fg" ,
228- } ;
229- await client . _unstable_sendFuture ( "!1:example.org" , futureOpts , null , "org.matrix.rageshake_request" , {
230- request_id : 123 ,
230+ it ( "sends action futures in an existing group for message events" , async ( ) => {
231+ await makeClient ( { sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
232+ expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
233+ expect ( widgetApi . requestCapabilityToSendEvent ) . toHaveBeenCalledWith ( "org.matrix.rageshake_request" ) ;
234+ const futureGroupId = `fg-${ Math . random ( ) } ` ;
235+ await client . _unstable_sendFuture (
236+ "!1:example.org" ,
237+ { future_group_id : futureGroupId } ,
238+ null ,
239+ "org.matrix.rageshake_request" ,
240+ { request_id : 123 } ,
241+ ) ;
242+ expect ( widgetApi . sendRoomEvent ) . toHaveBeenCalledWith (
243+ "org.matrix.rageshake_request" ,
244+ { request_id : 123 } ,
245+ "!1:example.org" ,
246+ undefined ,
247+ futureGroupId ,
248+ ) ;
231249 } ) ;
232- expect ( widgetApi . sendRoomEvent ) . toHaveBeenCalledWith (
233- "org.matrix.rageshake_request" ,
234- { request_id : 123 } ,
235- "!1:example.org" ,
236- undefined ,
237- futureOpts . future_group_id ,
238- ) ;
239- } ) ;
240250
241- it ( "sends futures in a new group for state events" , async ( ) => {
242- await makeClient ( { sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
243- expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
244- expect ( widgetApi . requestCapabilityToSendState ) . toHaveBeenCalledWith ( "org.example.foo" , "bar" ) ;
245- const futureOpts = {
246- future_timeout : 2000 ,
247- } ;
248- await client . _unstable_sendStateFuture (
249- "!1:example.org" ,
250- futureOpts ,
251- "org.example.foo" ,
252- { hello : "world" } ,
253- "bar" ,
254- ) ;
255- expect ( widgetApi . sendStateEvent ) . toHaveBeenCalledWith (
256- "org.example.foo" ,
257- "bar" ,
258- { hello : "world" } ,
259- "!1:example.org" ,
260- futureOpts . future_timeout ,
261- undefined ,
262- ) ;
251+ it ( "sends futures in a new group for state events" , async ( ) => {
252+ await makeClient ( { sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
253+ expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
254+ expect ( widgetApi . requestCapabilityToSendState ) . toHaveBeenCalledWith ( "org.example.foo" , "bar" ) ;
255+ await client . _unstable_sendStateFuture (
256+ "!1:example.org" ,
257+ { future_timeout : 2000 } ,
258+ "org.example.foo" ,
259+ { hello : "world" } ,
260+ "bar" ,
261+ ) ;
262+ expect ( widgetApi . sendStateEvent ) . toHaveBeenCalledWith (
263+ "org.example.foo" ,
264+ "bar" ,
265+ { hello : "world" } ,
266+ "!1:example.org" ,
267+ 2000 ,
268+ undefined ,
269+ ) ;
270+ } ) ;
271+
272+ it ( "sends action futures in an existing group for state events" , async ( ) => {
273+ await makeClient ( { sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
274+ expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
275+ expect ( widgetApi . requestCapabilityToSendState ) . toHaveBeenCalledWith ( "org.example.foo" , "bar" ) ;
276+ const futureGroupId = `fg-${ Math . random ( ) } ` ;
277+ await client . _unstable_sendStateFuture (
278+ "!1:example.org" ,
279+ { future_group_id : futureGroupId } ,
280+ "org.example.foo" ,
281+ { hello : "world" } ,
282+ "bar" ,
283+ ) ;
284+ expect ( widgetApi . sendStateEvent ) . toHaveBeenCalledWith (
285+ "org.example.foo" ,
286+ "bar" ,
287+ { hello : "world" } ,
288+ "!1:example.org" ,
289+ undefined ,
290+ futureGroupId ,
291+ ) ;
292+ } ) ;
293+
294+ describe ( "when improperly implemented" , ( ) => {
295+ const response = {
296+ future_group_id : `fg-${ Math . random ( ) } ` ,
297+ send_token : `st-${ Math . random ( ) } ` ,
298+ cancel_token : `ct-${ Math . random ( ) } ` ,
299+ refresh_token : `rt-${ Math . random ( ) } ` ,
300+ } ;
301+
302+ for ( const missingField of Object . keys ( response ) ) {
303+ const badResponse : Record < string , string > = { ...response } ;
304+ delete badResponse [ missingField ] ;
305+ const fullBadResponse = { ...badResponse , room_id : "!1:example.org" } ;
306+
307+ it ( `fails to send message futures without a ${ missingField } ` , async ( ) => {
308+ jest . spyOn ( widgetApi , "sendRoomEvent" ) . mockResolvedValue ( fullBadResponse ) ;
309+ await makeClient ( { sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
310+ await expect (
311+ client . _unstable_sendFuture (
312+ "!1:example.org" ,
313+ { future_timeout : 2000 } ,
314+ null ,
315+ "org.matrix.rageshake_request" ,
316+ { request_id : 123 } ,
317+ )
318+ ) . rejects . toThrow ( `'${ missingField } ' absent from response` ) ;
319+ } ) ;
320+
321+ it ( `fails to send state futures without a ${ missingField } ` , async ( ) => {
322+ jest . spyOn ( widgetApi , "sendStateEvent" ) . mockResolvedValue ( fullBadResponse ) ;
323+ await makeClient ( { sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
324+ await expect (
325+ client . _unstable_sendStateFuture (
326+ "!1:example.org" ,
327+ { future_timeout : 2000 , } ,
328+ "org.example.foo" ,
329+ { hello : "world" } ,
330+ "bar" ,
331+ )
332+ ) . rejects . toThrow ( `'${ missingField } ' absent from response` ) ;
333+ } ) ;
334+ }
335+ } ) ;
263336 } ) ;
264337
265- it ( "sends action futures in an existing group for state events" , async ( ) => {
266- await makeClient ( { sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
267- expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
268- expect ( widgetApi . requestCapabilityToSendState ) . toHaveBeenCalledWith ( "org.example.foo" , "bar" ) ;
269- const futureOpts = {
270- future_group_id : "fg" ,
271- } ;
272- await client . _unstable_sendStateFuture (
273- "!1:example.org" ,
274- futureOpts ,
275- "org.example.foo" ,
276- { hello : "world" } ,
277- "bar" ,
278- ) ;
279- expect ( widgetApi . sendStateEvent ) . toHaveBeenCalledWith (
280- "org.example.foo" ,
281- "bar" ,
282- { hello : "world" } ,
283- "!1:example.org" ,
284- undefined ,
285- futureOpts . future_group_id ,
286- ) ;
338+ describe ( "when unsupported" , ( ) => {
339+ it ( "fails to send message futures" , async ( ) => {
340+ await makeClient ( { sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
341+ await expect (
342+ client . _unstable_sendFuture (
343+ "!1:example.org" ,
344+ { future_timeout : 2000 } ,
345+ null ,
346+ "org.matrix.rageshake_request" ,
347+ { request_id : 123 } ,
348+ )
349+ ) . rejects . toThrow ( "Server does not support the Futures API" ) ;
350+ } ) ;
351+
352+ it ( "fails to send state futures" , async ( ) => {
353+ await makeClient ( { sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
354+ await expect (
355+ client . _unstable_sendStateFuture (
356+ "!1:example.org" ,
357+ { future_timeout : 2000 , } ,
358+ "org.example.foo" ,
359+ { hello : "world" } ,
360+ "bar" ,
361+ )
362+ ) . rejects . toThrow ( "Server does not support the Futures API" ) ;
363+ } ) ;
287364 } ) ;
288365 } ) ;
289366
0 commit comments