@@ -31,6 +31,9 @@ import {
3131 type IOpenIDCredentials ,
3232 type ISendEventFromWidgetResponseData ,
3333 WidgetApiResponseError ,
34+ UnstableApiVersion ,
35+ type ApiVersion ,
36+ type IRoomEvent ,
3437} from "matrix-widget-api" ;
3538
3639import { createRoomWidgetClient , MatrixError , MsgType , UpdateDelayedEventAction } from "../../src/matrix" ;
@@ -49,6 +52,7 @@ const testOIDCToken = {
4952} ;
5053class MockWidgetApi extends EventEmitter {
5154 public start = jest . fn ( ) . mockResolvedValue ( undefined ) ;
55+ public getClientVersions = jest . fn ( ) ;
5256 public requestCapability = jest . fn ( ) . mockResolvedValue ( undefined ) ;
5357 public requestCapabilities = jest . fn ( ) . mockResolvedValue ( undefined ) ;
5458 public requestCapabilityForRoomTimeline = jest . fn ( ) . mockResolvedValue ( undefined ) ;
@@ -96,6 +100,11 @@ class MockWidgetApi extends EventEmitter {
96100 send : jest . fn ( ) ,
97101 sendComplete : jest . fn ( ) ,
98102 } ;
103+
104+ public constructor ( clientVersions : ApiVersion [ ] ) {
105+ super ( ) ;
106+ this . getClientVersions . mockResolvedValue ( clientVersions ) ;
107+ }
99108}
100109
101110declare module "../../src/types" {
@@ -117,7 +126,7 @@ describe("RoomWidgetClient", () => {
117126 let client : MatrixClient ;
118127
119128 beforeEach ( ( ) => {
120- widgetApi = new MockWidgetApi ( ) as unknown as MockedObject < WidgetApi > ;
129+ widgetApi = new MockWidgetApi ( [ UnstableApiVersion . MSC2762_UPDATE_STATE ] ) as unknown as MockedObject < WidgetApi > ;
121130 } ) ;
122131
123132 afterEach ( ( ) => {
@@ -668,10 +677,55 @@ describe("RoomWidgetClient", () => {
668677 detail : { data : { state : [ event ] } } ,
669678 } ) ,
670679 ) ;
680+ // Allow the getClientVersions promise to resolve
681+ await new Promise < void > ( ( resolve ) => setTimeout ( resolve , 0 ) ) ;
671682 // It should now have changed the room state
672683 expect ( room ! . currentState . getStateEvents ( "org.example.foo" , "bar" ) ?. getEffectiveEvent ( ) ) . toEqual ( event ) ;
673684 } ) ;
674685
686+ describe ( "without support for update_state" , ( ) => {
687+ beforeEach ( ( ) => {
688+ widgetApi = new MockWidgetApi ( [ ] ) as unknown as MockedObject < WidgetApi > ;
689+ } ) ;
690+
691+ it ( "receives" , async ( ) => {
692+ await makeClient ( { receiveState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
693+ expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
694+ expect ( widgetApi . requestCapabilityToReceiveState ) . toHaveBeenCalledWith ( "org.example.foo" , "bar" ) ;
695+
696+ const emittedEvent = new Promise < MatrixEvent > ( ( resolve ) => client . once ( ClientEvent . Event , resolve ) ) ;
697+ const emittedSync = new Promise < SyncState > ( ( resolve ) => client . once ( ClientEvent . Sync , resolve ) ) ;
698+ widgetApi . emit (
699+ `action:${ WidgetApiToWidgetAction . SendEvent } ` ,
700+ new CustomEvent ( `action:${ WidgetApiToWidgetAction . SendEvent } ` , { detail : { data : event } } ) ,
701+ ) ;
702+
703+ // The client should've emitted about the received event
704+ expect ( ( await emittedEvent ) . getEffectiveEvent ( ) ) . toEqual ( event ) ;
705+ expect ( await emittedSync ) . toEqual ( SyncState . Syncing ) ;
706+ // It should've also inserted the event into the room object
707+ const room = client . getRoom ( "!1:example.org" ) ;
708+ expect ( room ) . not . toBeNull ( ) ;
709+ expect ( room ! . currentState . getStateEvents ( "org.example.foo" , "bar" ) ?. getEffectiveEvent ( ) ) . toEqual ( event ) ;
710+ } ) ;
711+
712+ it ( "backfills" , async ( ) => {
713+ widgetApi . readStateEvents . mockImplementation ( async ( eventType , limit , stateKey ) =>
714+ eventType === "org.example.foo" && ( limit ?? Infinity ) > 0 && stateKey === "bar"
715+ ? [ event as IRoomEvent ]
716+ : [ ] ,
717+ ) ;
718+
719+ await makeClient ( { receiveState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
720+ expect ( widgetApi . requestCapabilityForRoomTimeline ) . toHaveBeenCalledWith ( "!1:example.org" ) ;
721+ expect ( widgetApi . requestCapabilityToReceiveState ) . toHaveBeenCalledWith ( "org.example.foo" , "bar" ) ;
722+
723+ const room = client . getRoom ( "!1:example.org" ) ;
724+ expect ( room ) . not . toBeNull ( ) ;
725+ expect ( room ! . currentState . getStateEvents ( "org.example.foo" , "bar" ) ?. getEffectiveEvent ( ) ) . toEqual ( event ) ;
726+ } ) ;
727+ } ) ;
728+
675729 it ( "ignores state updates for other rooms" , async ( ) => {
676730 const init = makeClient ( { receiveState : [ { eventType : "org.example.foo" , stateKey : "bar" } ] } ) ;
677731 // Client needs to be told that the room state is loaded
0 commit comments