@@ -32,7 +32,7 @@ import {
3232 IOpenIDCredentials ,
3333} from "matrix-widget-api" ;
3434
35- import { createRoomWidgetClient , MsgType } from "../../src/matrix" ;
35+ import { createRoomWidgetClient , MsgType , UpdateDelayedEventAction } from "../../src/matrix" ;
3636import { MatrixClient , ClientEvent , ITurnServer as IClientTurnServer } from "../../src/client" ;
3737import { SyncState } from "../../src/sync" ;
3838import { ICapabilities } from "../../src/embedded" ;
@@ -59,8 +59,26 @@ class MockWidgetApi extends EventEmitter {
5959 public requestCapabilityToReceiveState = jest . fn ( ) ;
6060 public requestCapabilityToSendToDevice = jest . fn ( ) ;
6161 public requestCapabilityToReceiveToDevice = jest . fn ( ) ;
62- public sendRoomEvent = jest . fn ( ( ) => ( { event_id : `$${ Math . random ( ) } ` } ) ) ;
63- public sendStateEvent = jest . fn ( ) ;
62+ public sendRoomEvent = jest . fn (
63+ ( eventType : string , content : unknown , roomId ?: string , delay ?: number , parentDelayId ?: string ) =>
64+ delay === undefined && parentDelayId === undefined
65+ ? { event_id : `$${ Math . random ( ) } ` }
66+ : { delay_id : `id-${ Math . random ( ) } ` } ,
67+ ) ;
68+ public sendStateEvent = jest . fn (
69+ (
70+ eventType : string ,
71+ stateKey : string ,
72+ content : unknown ,
73+ roomId ?: string ,
74+ delay ?: number ,
75+ parentDelayId ?: string ,
76+ ) =>
77+ delay === undefined && parentDelayId === undefined
78+ ? { event_id : `$${ Math . random ( ) } ` }
79+ : { delay_id : `id-${ Math . random ( ) } ` } ,
80+ ) ;
81+ public updateDelayedEvent = jest . fn ( ) ;
6482 public sendToDevice = jest . fn ( ) ;
6583 public requestOpenIDConnectToken = jest . fn ( ( ) => {
6684 return testOIDCToken ;
@@ -160,6 +178,162 @@ describe("RoomWidgetClient", () => {
160178 } ) ;
161179 } ) ;
162180
181+ describe ( "delayed events" , ( ) => {
182+ describe ( "when supported" , ( ) => {
183+ const doesServerSupportUnstableFeatureMock = jest . fn ( ( feature ) =>
184+ Promise . resolve ( feature === "org.matrix.msc4140" ) ,
185+ ) ;
186+
187+ beforeAll ( ( ) => {
188+ MatrixClient . prototype . doesServerSupportUnstableFeature = doesServerSupportUnstableFeatureMock ;
189+ } ) ;
190+
191+ afterAll ( ( ) => {
192+ doesServerSupportUnstableFeatureMock . mockReset ( ) ;
193+ } ) ;
194+
195+ it ( "sends delayed message events" , async ( ) => {
196+ await makeClient ( { sendDelayedEvents : true , sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
197+ expect ( widgetApi . requestCapability ) . toHaveBeenCalledWith ( MatrixCapabilities . MSC4157SendDelayedEvent ) ;
198+ await client . _unstable_sendDelayedEvent (
199+ "!1:example.org" ,
200+ { delay : 2000 } ,
201+ null ,
202+ "org.matrix.rageshake_request" ,
203+ { request_id : 123 } ,
204+ ) ;
205+ expect ( widgetApi . sendRoomEvent ) . toHaveBeenCalledWith (
206+ "org.matrix.rageshake_request" ,
207+ { request_id : 123 } ,
208+ "!1:example.org" ,
209+ 2000 ,
210+ undefined ,
211+ ) ;
212+ } ) ;
213+
214+ it ( "sends child action delayed message events" , async ( ) => {
215+ await makeClient ( { sendDelayedEvents : true , sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
216+ expect ( widgetApi . requestCapability ) . toHaveBeenCalledWith ( MatrixCapabilities . MSC4157SendDelayedEvent ) ;
217+ const parentDelayId = `id-${ Math . random ( ) } ` ;
218+ await client . _unstable_sendDelayedEvent (
219+ "!1:example.org" ,
220+ { parent_delay_id : parentDelayId } ,
221+ null ,
222+ "org.matrix.rageshake_request" ,
223+ { request_id : 123 } ,
224+ ) ;
225+ expect ( widgetApi . sendRoomEvent ) . toHaveBeenCalledWith (
226+ "org.matrix.rageshake_request" ,
227+ { request_id : 123 } ,
228+ "!1:example.org" ,
229+ undefined ,
230+ parentDelayId ,
231+ ) ;
232+ } ) ;
233+
234+ it ( "sends delayed state events" , async ( ) => {
235+ await makeClient ( {
236+ sendDelayedEvents : true ,
237+ sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] ,
238+ } ) ;
239+ expect ( widgetApi . requestCapability ) . toHaveBeenCalledWith ( MatrixCapabilities . MSC4157SendDelayedEvent ) ;
240+ await client . _unstable_sendDelayedStateEvent (
241+ "!1:example.org" ,
242+ { delay : 2000 } ,
243+ "org.example.foo" ,
244+ { hello : "world" } ,
245+ "bar" ,
246+ ) ;
247+ expect ( widgetApi . sendStateEvent ) . toHaveBeenCalledWith (
248+ "org.example.foo" ,
249+ "bar" ,
250+ { hello : "world" } ,
251+ "!1:example.org" ,
252+ 2000 ,
253+ undefined ,
254+ ) ;
255+ } ) ;
256+
257+ it ( "sends child action delayed state events" , async ( ) => {
258+ await makeClient ( {
259+ sendDelayedEvents : true ,
260+ sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] ,
261+ } ) ;
262+ expect ( widgetApi . requestCapability ) . toHaveBeenCalledWith ( MatrixCapabilities . MSC4157SendDelayedEvent ) ;
263+ const parentDelayId = `fg-${ Math . random ( ) } ` ;
264+ await client . _unstable_sendDelayedStateEvent (
265+ "!1:example.org" ,
266+ { parent_delay_id : parentDelayId } ,
267+ "org.example.foo" ,
268+ { hello : "world" } ,
269+ "bar" ,
270+ ) ;
271+ expect ( widgetApi . sendStateEvent ) . toHaveBeenCalledWith (
272+ "org.example.foo" ,
273+ "bar" ,
274+ { hello : "world" } ,
275+ "!1:example.org" ,
276+ undefined ,
277+ parentDelayId ,
278+ ) ;
279+ } ) ;
280+
281+ it ( "updates delayed events" , async ( ) => {
282+ await makeClient ( { updateDelayedEvents : true , sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
283+ expect ( widgetApi . requestCapability ) . toHaveBeenCalledWith ( MatrixCapabilities . MSC4157UpdateDelayedEvent ) ;
284+ for ( const action of [
285+ UpdateDelayedEventAction . Cancel ,
286+ UpdateDelayedEventAction . Restart ,
287+ UpdateDelayedEventAction . Send ,
288+ ] ) {
289+ await client . _unstable_updateDelayedEvent ( "id" , action ) ;
290+ expect ( widgetApi . updateDelayedEvent ) . toHaveBeenCalledWith ( "id" , action ) ;
291+ }
292+ } ) ;
293+ } ) ;
294+
295+ describe ( "when unsupported" , ( ) => {
296+ it ( "fails to send delayed message events" , async ( ) => {
297+ await makeClient ( { sendEvent : [ "org.matrix.rageshake_request" ] } ) ;
298+ await expect (
299+ client . _unstable_sendDelayedEvent (
300+ "!1:example.org" ,
301+ { delay : 2000 } ,
302+ null ,
303+ "org.matrix.rageshake_request" ,
304+ { request_id : 123 } ,
305+ ) ,
306+ ) . rejects . toThrow ( "Server does not support" ) ;
307+ } ) ;
308+
309+ it ( "fails to send delayed state events" , async ( ) => {
310+ await makeClient ( { sendState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
311+ await expect (
312+ client . _unstable_sendDelayedStateEvent (
313+ "!1:example.org" ,
314+ { delay : 2000 } ,
315+ "org.example.foo" ,
316+ { hello : "world" } ,
317+ "bar" ,
318+ ) ,
319+ ) . rejects . toThrow ( "Server does not support" ) ;
320+ } ) ;
321+
322+ it ( "fails to update delayed state events" , async ( ) => {
323+ await makeClient ( { } ) ;
324+ for ( const action of [
325+ UpdateDelayedEventAction . Cancel ,
326+ UpdateDelayedEventAction . Restart ,
327+ UpdateDelayedEventAction . Send ,
328+ ] ) {
329+ await expect ( client . _unstable_updateDelayedEvent ( "id" , action ) ) . rejects . toThrow (
330+ "Server does not support" ,
331+ ) ;
332+ }
333+ } ) ;
334+ } ) ;
335+ } ) ;
336+
163337 describe ( "initialization" , ( ) => {
164338 it ( "requests permissions for specific message types" , async ( ) => {
165339 await makeClient ( { sendMessage : [ MsgType . Text ] , receiveMessage : [ MsgType . Text ] } ) ;
0 commit comments