@@ -28,7 +28,8 @@ use matrix_sdk_test::{
28
28
} ;
29
29
use matrix_sdk_ui:: timeline:: { EventSendState , RoomExt , TimelineItemContent , VirtualTimelineItem } ;
30
30
use ruma:: {
31
- events:: room:: message:: RoomMessageEventContent , room_id, user_id, MilliSecondsSinceUnixEpoch ,
31
+ event_id, events:: room:: message:: RoomMessageEventContent , room_id, user_id,
32
+ MilliSecondsSinceUnixEpoch ,
32
33
} ;
33
34
use serde_json:: json;
34
35
use wiremock:: {
@@ -442,3 +443,67 @@ async fn test_sync_highlighted() {
442
443
// `m.room.tombstone` should be highlighted by default.
443
444
assert ! ( remote_event. is_highlighted( ) ) ;
444
445
}
446
+
447
+ #[ async_test]
448
+ async fn test_duplicate_maintains_correct_order ( ) {
449
+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
450
+ let ( client, server) = logged_in_client_with_server ( ) . await ;
451
+ let sync_settings = SyncSettings :: new ( ) . timeout ( Duration :: from_millis ( 3000 ) ) ;
452
+
453
+ let mut sync_builder = SyncResponseBuilder :: new ( ) ;
454
+ sync_builder. add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
455
+
456
+ mock_sync ( & server, sync_builder. build_json_sync_response ( ) , None ) . await ;
457
+ let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
458
+ server. reset ( ) . await ;
459
+
460
+ let room = client. get_room ( room_id) . unwrap ( ) ;
461
+ let timeline = room. timeline ( ) . await . unwrap ( ) ;
462
+
463
+ // At the beginning, the timeline is empty.
464
+ assert ! ( timeline. items( ) . await . is_empty( ) ) ;
465
+
466
+ let f = EventFactory :: new ( ) . sender ( user_id ! ( "@a:b.c" ) ) ;
467
+
468
+ // We receive an event F, from a sliding sync with timeline limit=1.
469
+ sync_builder. add_joined_room (
470
+ JoinedRoomBuilder :: new ( room_id)
471
+ . add_timeline_event ( f. text_msg ( "C" ) . event_id ( event_id ! ( "$c" ) ) . into_raw_sync ( ) ) ,
472
+ ) ;
473
+
474
+ mock_sync ( & server, sync_builder. build_json_sync_response ( ) , None ) . await ;
475
+ let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
476
+ server. reset ( ) . await ;
477
+
478
+ // The timeline item represents the message we just received.
479
+ let items = timeline. items ( ) . await ;
480
+ assert_eq ! ( items. len( ) , 2 ) ;
481
+
482
+ assert ! ( items[ 0 ] . is_day_divider( ) ) ;
483
+ let content = items[ 1 ] . as_event ( ) . unwrap ( ) . content ( ) . as_message ( ) . unwrap ( ) . body ( ) ;
484
+ assert_eq ! ( content, "C" ) ;
485
+
486
+ // We receive multiple events, and C is now the last one (because we supposedly
487
+ // increased the timeline limit).
488
+ sync_builder. add_joined_room (
489
+ JoinedRoomBuilder :: new ( room_id)
490
+ . add_timeline_event ( f. text_msg ( "A" ) . event_id ( event_id ! ( "$a" ) ) . into_raw_sync ( ) )
491
+ . add_timeline_event ( f. text_msg ( "B" ) . event_id ( event_id ! ( "$b" ) ) . into_raw_sync ( ) )
492
+ . add_timeline_event ( f. text_msg ( "C" ) . event_id ( event_id ! ( "$c" ) ) . into_raw_sync ( ) ) ,
493
+ ) ;
494
+
495
+ mock_sync ( & server, sync_builder. build_json_sync_response ( ) , None ) . await ;
496
+ let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
497
+ server. reset ( ) . await ;
498
+
499
+ let items = timeline. items ( ) . await ;
500
+ assert_eq ! ( items. len( ) , 4 , "{items:?}" ) ;
501
+
502
+ assert ! ( items[ 0 ] . is_day_divider( ) ) ;
503
+ let content = items[ 1 ] . as_event ( ) . unwrap ( ) . content ( ) . as_message ( ) . unwrap ( ) . body ( ) ;
504
+ assert_eq ! ( content, "A" ) ;
505
+ let content = items[ 2 ] . as_event ( ) . unwrap ( ) . content ( ) . as_message ( ) . unwrap ( ) . body ( ) ;
506
+ assert_eq ! ( content, "B" ) ;
507
+ let content = items[ 3 ] . as_event ( ) . unwrap ( ) . content ( ) . as_message ( ) . unwrap ( ) . body ( ) ;
508
+ assert_eq ! ( content, "C" ) ;
509
+ }
0 commit comments