@@ -21,7 +21,7 @@ import { mocked, MockedObject } from "jest-mock";
2121import { ClientEvent , MatrixClient } from "matrix-js-sdk/src/client" ;
2222import { Room , RoomEvent } from "matrix-js-sdk/src/models/room" ;
2323import { MatrixEvent } from "matrix-js-sdk/src/models/event" ;
24- import { EventType } from "matrix-js-sdk/src/matrix" ;
24+ import { EventType , RoomStateEvent } from "matrix-js-sdk/src/matrix" ;
2525import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib" ;
2626import { fireEvent , render } from "@testing-library/react" ;
2727
@@ -31,6 +31,9 @@ import {
3131 unmockPlatformPeg ,
3232 wrapInMatrixClientContext ,
3333 flushPromises ,
34+ mkEvent ,
35+ setupAsyncStoreWithClient ,
36+ filterConsole ,
3437} from "../../test-utils" ;
3538import { MatrixClientPeg } from "../../../src/MatrixClientPeg" ;
3639import { Action } from "../../../src/dispatcher/actions" ;
@@ -49,6 +52,9 @@ import { createDmLocalRoom } from "../../../src/utils/dm/createDmLocalRoom";
4952import { UPDATE_EVENT } from "../../../src/stores/AsyncStore" ;
5053import { SdkContextClass , SDKContext } from "../../../src/contexts/SDKContext" ;
5154import VoipUserMapper from "../../../src/VoipUserMapper" ;
55+ import WidgetUtils from "../../../src/utils/WidgetUtils" ;
56+ import { WidgetType } from "../../../src/widgets/WidgetType" ;
57+ import WidgetStore from "../../../src/stores/WidgetStore" ;
5258
5359const RoomView = wrapInMatrixClientContext ( _RoomView ) ;
5460
@@ -59,6 +65,9 @@ describe("RoomView", () => {
5965 let roomCount = 0 ;
6066 let stores : SdkContextClass ;
6167
68+ // mute some noise
69+ filterConsole ( "RVS update" , "does not have an m.room.create event" , "Current version: 1" , "Version capability" ) ;
70+
6271 beforeEach ( async ( ) => {
6372 mockPlatformPeg ( { reload : ( ) => { } } ) ;
6473 stubClient ( ) ;
@@ -359,4 +368,90 @@ describe("RoomView", () => {
359368 } ) ;
360369 } ) ;
361370 } ) ;
371+
372+ describe ( "when there is a RoomView" , ( ) => {
373+ const widget1Id = "widget1" ;
374+ const widget2Id = "widget2" ;
375+ const otherUserId = "@other:example.com" ;
376+
377+ const addJitsiWidget = async ( id : string , user : string , ts ?: number ) : Promise < void > => {
378+ const widgetEvent = mkEvent ( {
379+ event : true ,
380+ room : room . roomId ,
381+ user,
382+ type : "im.vector.modular.widgets" ,
383+ content : {
384+ id,
385+ name : "Jitsi" ,
386+ type : WidgetType . JITSI . preferred ,
387+ url : "https://example.com" ,
388+ } ,
389+ skey : id ,
390+ ts,
391+ } ) ;
392+ room . addLiveEvents ( [ widgetEvent ] ) ;
393+ room . currentState . setStateEvents ( [ widgetEvent ] ) ;
394+ cli . emit ( RoomStateEvent . Events , widgetEvent , room . currentState , null ) ;
395+ await flushPromises ( ) ;
396+ } ;
397+
398+ beforeEach ( async ( ) => {
399+ jest . spyOn ( WidgetUtils , "setRoomWidget" ) ;
400+ const widgetStore = WidgetStore . instance ;
401+ await setupAsyncStoreWithClient ( widgetStore , cli ) ;
402+ getRoomViewInstance ( ) ;
403+ } ) ;
404+
405+ const itShouldNotRemoveTheLastWidget = ( ) : void => {
406+ it ( "should not remove the last widget" , ( ) : void => {
407+ expect ( WidgetUtils . setRoomWidget ) . not . toHaveBeenCalledWith ( room . roomId , widget2Id ) ;
408+ } ) ;
409+ } ;
410+
411+ describe ( "and there is a Jitsi widget from another user" , ( ) => {
412+ beforeEach ( async ( ) => {
413+ await addJitsiWidget ( widget1Id , otherUserId , 10_000 ) ;
414+ } ) ;
415+
416+ describe ( "and the current user adds a Jitsi widget after 10s" , ( ) => {
417+ beforeEach ( async ( ) => {
418+ await addJitsiWidget ( widget2Id , cli . getSafeUserId ( ) , 20_000 ) ;
419+ } ) ;
420+
421+ it ( "the last Jitsi widget should be removed" , ( ) => {
422+ expect ( WidgetUtils . setRoomWidget ) . toHaveBeenCalledWith ( room . roomId , widget2Id ) ;
423+ } ) ;
424+ } ) ;
425+
426+ describe ( "and the current user adds a Jitsi widget after two minutes" , ( ) => {
427+ beforeEach ( async ( ) => {
428+ await addJitsiWidget ( widget2Id , cli . getSafeUserId ( ) , 130_000 ) ;
429+ } ) ;
430+
431+ itShouldNotRemoveTheLastWidget ( ) ;
432+ } ) ;
433+
434+ describe ( "and the current user adds a Jitsi widget without timestamp" , ( ) => {
435+ beforeEach ( async ( ) => {
436+ await addJitsiWidget ( widget2Id , cli . getSafeUserId ( ) ) ;
437+ } ) ;
438+
439+ itShouldNotRemoveTheLastWidget ( ) ;
440+ } ) ;
441+ } ) ;
442+
443+ describe ( "and there is a Jitsi widget from another user without timestamp" , ( ) => {
444+ beforeEach ( async ( ) => {
445+ await addJitsiWidget ( widget1Id , otherUserId ) ;
446+ } ) ;
447+
448+ describe ( "and the current user adds a Jitsi widget" , ( ) => {
449+ beforeEach ( async ( ) => {
450+ await addJitsiWidget ( widget2Id , cli . getSafeUserId ( ) , 10_000 ) ;
451+ } ) ;
452+
453+ itShouldNotRemoveTheLastWidget ( ) ;
454+ } ) ;
455+ } ) ;
456+ } ) ;
362457} ) ;
0 commit comments