@@ -291,34 +291,51 @@ describe("RoomListViewModel", () => {
291
291
} ) ;
292
292
} ) ;
293
293
294
- describe ( "active index" , ( ) => {
295
- it ( "should recalculate active index when list of rooms change" , ( ) => {
294
+ describe ( "Sticky room and active index" , ( ) => {
295
+ function expectActiveRoom ( vm : ReturnType < typeof useRoomListViewModel > , i : number , roomId : string ) {
296
+ expect ( vm . activeIndex ) . toEqual ( i ) ;
297
+ expect ( vm . rooms [ i ] . roomId ) . toEqual ( roomId ) ;
298
+ }
299
+
300
+ it ( "active room and active index are retained on order change" , ( ) => {
296
301
const { rooms } = mockAndCreateRooms ( ) ;
297
- // Let's say that the first room is the active room initially
298
- jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => rooms [ 0 ] . roomId ) ;
302
+
303
+ // Let's say that the room at index 5 is active
304
+ const roomId = rooms [ 5 ] . roomId ;
305
+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
299
306
300
307
const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
301
- expect ( vm . current . activeIndex ) . toEqual ( 0 ) ;
308
+ expect ( vm . current . activeIndex ) . toEqual ( 5 ) ;
309
+
310
+ // Let's say that room at index 9 moves to index 5
311
+ const room9 = rooms [ 9 ] ;
312
+ rooms . splice ( 9 , 1 ) ;
313
+ rooms . splice ( 5 , 0 , room9 ) ;
314
+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
315
+
316
+ // Active room index should still be 5
317
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
302
318
303
- // Let's say that a new room is added and that becomes active
304
- const newRoom = mkStubRoom ( "bar :matrix.org" , "Bar" , undefined ) ;
305
- jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => newRoom . roomId ) ;
306
- rooms . push ( newRoom ) ;
319
+ // Let's add 2 new rooms from index 0
320
+ const newRoom1 = mkStubRoom ( "bar1 :matrix.org" , "Bar 1 " , undefined ) ;
321
+ const newRoom2 = mkStubRoom ( "bar2:matrix.org" , "Bar 2" , undefined ) ;
322
+ rooms . unshift ( newRoom1 , newRoom2 ) ;
307
323
act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
308
324
309
- // Now the active room should be the last room which we just added
310
- expect ( vm . current . activeIndex ) . toEqual ( rooms . length - 1 ) ;
325
+ // Active room index should still be 5
326
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
311
327
} ) ;
312
328
313
- it ( "should recalculate active index when active room changes " , ( ) => {
329
+ it ( "active room and active index are updated when another room is opened " , ( ) => {
314
330
const { rooms } = mockAndCreateRooms ( ) ;
315
- const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
331
+ const roomId = rooms [ 5 ] . roomId ;
332
+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
316
333
317
- // No active room yet
318
- expect ( vm . current . activeIndex ) . toBeUndefined ( ) ;
334
+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
335
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
319
336
320
- // Let's say that room at index 5 becomes active
321
- const room = rooms [ 5 ] ;
337
+ // Let's say that room at index 9 becomes active
338
+ const room = rooms [ 9 ] ;
322
339
act ( ( ) => {
323
340
dispatcher . dispatch (
324
341
{
@@ -330,8 +347,76 @@ describe("RoomListViewModel", () => {
330
347
) ;
331
348
} ) ;
332
349
333
- // We expect index 5 to be active now
334
- expect ( vm . current . activeIndex ) . toEqual ( 5 ) ;
350
+ // Active room index should change to reflect new room
351
+ expectActiveRoom ( vm . current , 9 , room . roomId ) ;
352
+ } ) ;
353
+
354
+ it ( "active room and active index are updated when active index spills out of rooms array bounds" , ( ) => {
355
+ const { rooms } = mockAndCreateRooms ( ) ;
356
+ // Let's say that the room at index 5 is active
357
+ const roomId = rooms [ 5 ] . roomId ;
358
+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
359
+
360
+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
361
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
362
+
363
+ // Let's say that we remove rooms from the start of the array
364
+ for ( let i = 0 ; i < 4 ; ++ i ) {
365
+ // We should be able to do 4 deletions before we run out of rooms
366
+ rooms . splice ( 0 , 1 ) ;
367
+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
368
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
369
+ }
370
+
371
+ // If we remove one more room from the start, there's not going to be enough rooms
372
+ // to maintain the active index.
373
+ rooms . splice ( 0 , 1 ) ;
374
+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
375
+ expectActiveRoom ( vm . current , 0 , roomId ) ;
376
+ } ) ;
377
+
378
+ it ( "active room and active index are retained when rooms that appear after the active room are deleted" , ( ) => {
379
+ const { rooms } = mockAndCreateRooms ( ) ;
380
+ // Let's say that the room at index 5 is active
381
+ const roomId = rooms [ 5 ] . roomId ;
382
+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
383
+
384
+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
385
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
386
+
387
+ // Let's say that we remove rooms from the start of the array
388
+ for ( let i = 0 ; i < 4 ; ++ i ) {
389
+ // Deleting rooms after index 5 (active) should not update the active index
390
+ rooms . splice ( 6 , 1 ) ;
391
+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
392
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
393
+ }
394
+ } ) ;
395
+
396
+ it ( "active room index becomes undefined when active room is deleted" , ( ) => {
397
+ const { rooms } = mockAndCreateRooms ( ) ;
398
+ // Let's say that the room at index 5 is active
399
+ let roomId : string | undefined = rooms [ 5 ] . roomId ;
400
+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
401
+
402
+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
403
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
404
+
405
+ // Let's remove the active room (i.e room at index 5)
406
+ rooms . splice ( 5 , 1 ) ;
407
+ roomId = undefined ;
408
+ act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
409
+ expect ( vm . current . activeIndex ) . toBeUndefined ( ) ;
410
+ } ) ;
411
+
412
+ it ( "active room index is initially undefined" , ( ) => {
413
+ mockAndCreateRooms ( ) ;
414
+
415
+ // Let's say that there's no active room currently
416
+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => undefined ) ;
417
+
418
+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
419
+ expect ( vm . current . activeIndex ) . toEqual ( undefined ) ;
335
420
} ) ;
336
421
} ) ;
337
422
} ) ;
0 commit comments