@@ -314,34 +314,51 @@ describe("RoomListViewModel", () => {
314
314
} ) ;
315
315
} ) ;
316
316
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" , ( ) => {
319
324
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 ) ;
322
329
323
330
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 ) ;
325
341
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 ) ;
330
346
act ( ( ) => RoomListStoreV3 . instance . emit ( LISTS_UPDATE_EVENT ) ) ;
331
347
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 ) ;
334
350
} ) ;
335
351
336
- it ( "should recalculate active index when active room changes " , ( ) => {
352
+ it ( "active room and active index are updated when another room is opened " , ( ) => {
337
353
const { rooms } = mockAndCreateRooms ( ) ;
338
- const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
354
+ const roomId = rooms [ 5 ] . roomId ;
355
+ jest . spyOn ( SdkContextClass . instance . roomViewStore , "getRoomId" ) . mockImplementation ( ( ) => roomId ) ;
339
356
340
- // No active room yet
341
- expect ( vm . current . activeIndex ) . toBeUndefined ( ) ;
357
+ const { result : vm } = renderHook ( ( ) => useRoomListViewModel ( ) ) ;
358
+ expectActiveRoom ( vm . current , 5 , roomId ) ;
342
359
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 ] ;
345
362
act ( ( ) => {
346
363
dispatcher . dispatch (
347
364
{
@@ -353,8 +370,76 @@ describe("RoomListViewModel", () => {
353
370
) ;
354
371
} ) ;
355
372
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 ) ;
358
443
} ) ;
359
444
} ) ;
360
445
} ) ;
0 commit comments