@@ -314,34 +314,51 @@ describe("RoomListViewModel", () => {
314314 } ) ;
315315 } ) ;
316316
317- describe ( "active index" , ( ) => {
318- it ( "should recalculate active index when list of rooms change" , ( ) => {
317+ describe ( "Sticky room and active index" , ( ) => {
318+ function expectActiveRoom ( vm : ReturnType < typeof useRoomListViewModel > , i : number , roomId : string ) {
319+ expect ( vm . activeIndex ) . toEqual ( i ) ;
320+ expect ( vm . rooms [ i ] . roomId ) . toEqual ( roomId ) ;
321+ }
322+
323+ it ( "active room and active index are retained on order change" , ( ) => {
319324 const { rooms } = mockAndCreateRooms ( ) ;
320- // Let's say that the first room is the active room initially
321- jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => rooms [ 0 ] . roomId ) ;
325+
326+ // Let's say that the room at index 5 is active
327+ const roomId = rooms [ 5 ] . roomId ;
328+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
322329
323330 const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
324- expect ( vm . current . activeIndex ) . toEqual ( 0 ) ;
331+ expect ( vm . current . activeIndex ) . toEqual ( 5 ) ;
332+
333+ // Let's say that room at index 9 moves to index 5
334+ const room9 = rooms [ 9 ] ;
335+ rooms . splice ( 9 , 1 ) ;
336+ rooms . splice ( 5 , 0 , room9 ) ;
337+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
338+
339+ // Active room index should still be 5
340+ expectActiveRoom ( vm . current , 5 , roomId ) ;
325341
326- // Let's say that a new room is added and that becomes active
327- const newRoom = mkStubRoom ( "bar :matrix.org" , "Bar" , undefined ) ;
328- jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => newRoom . roomId ) ;
329- rooms . push ( newRoom ) ;
342+ // Let's add 2 new rooms from index 0
343+ const newRoom1 = mkStubRoom ( "bar1 :matrix.org" , "Bar 1 " , undefined ) ;
344+ const newRoom2 = mkStubRoom ( "bar2:matrix.org" , "Bar 2" , undefined ) ;
345+ rooms . unshift ( newRoom1 , newRoom2 ) ;
330346 act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
331347
332- // Now the active room should be the last room which we just added
333- expect ( vm . current . activeIndex ) . toEqual ( rooms . length - 1 ) ;
348+ // Active room index should still be 5
349+ expectActiveRoom ( vm . current , 5 , roomId ) ;
334350 } ) ;
335351
336- it ( "should recalculate active index when active room changes " , ( ) => {
352+ it ( "active room and active index are updated when another room is opened " , ( ) => {
337353 const { rooms } = mockAndCreateRooms ( ) ;
338- const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
354+ const roomId = rooms [ 5 ] . roomId ;
355+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
339356
340- // No active room yet
341- expect ( vm . current . activeIndex ) . toBeUndefined ( ) ;
357+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
358+ expectActiveRoom ( vm . current , 5 , roomId ) ;
342359
343- // Let's say that room at index 5 becomes active
344- const room = rooms [ 5 ] ;
360+ // Let's say that room at index 9 becomes active
361+ const room = rooms [ 9 ] ;
345362 act ( ( ) => {
346363 dispatcher . dispatch (
347364 {
@@ -353,8 +370,76 @@ describe("RoomListViewModel", () => {
353370 ) ;
354371 } ) ;
355372
356- // We expect index 5 to be active now
357- expect ( vm . current . activeIndex ) . toEqual ( 5 ) ;
373+ // Active room index should change to reflect new room
374+ expectActiveRoom ( vm . current , 9 , room . roomId ) ;
375+ } ) ;
376+
377+ it ( "active room and active index are updated when active index spills out of rooms array bounds" , ( ) => {
378+ const { rooms } = mockAndCreateRooms ( ) ;
379+ // Let's say that the room at index 5 is active
380+ const roomId = rooms [ 5 ] . roomId ;
381+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
382+
383+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
384+ expectActiveRoom ( vm . current , 5 , roomId ) ;
385+
386+ // Let's say that we remove rooms from the start of the array
387+ for ( let i = 0 ; i < 4 ; ++ i ) {
388+ // We should be able to do 4 deletions before we run out of rooms
389+ rooms . splice ( 0 , 1 ) ;
390+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
391+ expectActiveRoom ( vm . current , 5 , roomId ) ;
392+ }
393+
394+ // If we remove one more room from the start, there's not going to be enough rooms
395+ // to maintain the active index.
396+ rooms . splice ( 0 , 1 ) ;
397+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
398+ expectActiveRoom ( vm . current , 0 , roomId ) ;
399+ } ) ;
400+
401+ it ( "active room and active index are retained when rooms that appear after the active room are deleted" , ( ) => {
402+ const { rooms } = mockAndCreateRooms ( ) ;
403+ // Let's say that the room at index 5 is active
404+ const roomId = rooms [ 5 ] . roomId ;
405+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
406+
407+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
408+ expectActiveRoom ( vm . current , 5 , roomId ) ;
409+
410+ // Let's say that we remove rooms from the start of the array
411+ for ( let i = 0 ; i < 4 ; ++ i ) {
412+ // Deleting rooms after index 5 (active) should not update the active index
413+ rooms . splice ( 6 , 1 ) ;
414+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
415+ expectActiveRoom ( vm . current , 5 , roomId ) ;
416+ }
417+ } ) ;
418+
419+ it ( "active room index becomes undefined when active room is deleted" , ( ) => {
420+ const { rooms } = mockAndCreateRooms ( ) ;
421+ // Let's say that the room at index 5 is active
422+ let roomId : string | undefined = rooms [ 5 ] . roomId ;
423+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
424+
425+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
426+ expectActiveRoom ( vm . current , 5 , roomId ) ;
427+
428+ // Let's remove the active room (i.e room at index 5)
429+ rooms . splice ( 5 , 1 ) ;
430+ roomId = undefined ;
431+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
432+ expect ( vm . current . activeIndex ) . toBeUndefined ( ) ;
433+ } ) ;
434+
435+ it ( "active room index is initially undefined" , ( ) => {
436+ mockAndCreateRooms ( ) ;
437+
438+ // Let's say that there's no active room currently
439+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => undefined ) ;
440+
441+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
442+ expect ( vm . current . activeIndex ) . toEqual ( undefined ) ;
358443 } ) ;
359444 } ) ;
360445} ) ;
0 commit comments