@@ -32,10 +32,18 @@ use ruma::{
32
32
event_id,
33
33
events:: {
34
34
AnySyncTimelineEvent ,
35
+ poll:: unstable_start:: {
36
+ NewUnstablePollStartEventContent , UnstablePollAnswer , UnstablePollStartContentBlock ,
37
+ UnstablePollStartEventContent ,
38
+ } ,
35
39
receipt:: { ReceiptThread , ReceiptType } ,
36
- room:: message:: { Relation , ReplacementMetadata , RoomMessageEventContent } ,
40
+ room:: {
41
+ ImageInfo ,
42
+ message:: { Relation , ReplacementMetadata , RoomMessageEventContent } ,
43
+ } ,
44
+ sticker:: { StickerEventContent , StickerMediaSource } ,
37
45
} ,
38
- owned_event_id, room_id, user_id,
46
+ owned_event_id, owned_mxc_uri , room_id, user_id,
39
47
} ;
40
48
use stream_assert:: assert_pending;
41
49
use tokio:: task:: yield_now;
@@ -893,6 +901,168 @@ async fn test_thread_timeline_can_send_edit() {
893
901
assert_pending ! ( stream) ;
894
902
}
895
903
904
+ #[ async_test]
905
+ async fn test_send_sticker_thread ( ) {
906
+ // If I send a sticker to a threaded timeline, it just works (aka the system to
907
+ // set the threaded relationship does kick in).
908
+
909
+ let server = MatrixMockServer :: new ( ) . await ;
910
+ let client = server. client_builder ( ) . build ( ) . await ;
911
+
912
+ let room_id = room_id ! ( "!a:b.c" ) ;
913
+ let thread_root_event_id = owned_event_id ! ( "$root" ) ;
914
+ let threaded_event_id = event_id ! ( "$threaded_event" ) ;
915
+
916
+ let room = server. sync_joined_room ( & client, room_id) . await ;
917
+
918
+ let timeline = room
919
+ . timeline_builder ( )
920
+ . with_focus ( TimelineFocus :: Thread { root_event_id : thread_root_event_id. clone ( ) } )
921
+ . build ( )
922
+ . await
923
+ . unwrap ( ) ;
924
+
925
+ let ( initial_items, mut stream) = timeline. subscribe ( ) . await ;
926
+
927
+ // At first, the timeline is empty.
928
+ assert ! ( initial_items. is_empty( ) ) ;
929
+ assert_pending ! ( stream) ;
930
+
931
+ // Start the timeline with an in-thread event.
932
+ let f = EventFactory :: new ( ) ;
933
+ server
934
+ . sync_room (
935
+ & client,
936
+ JoinedRoomBuilder :: new ( room_id) . add_timeline_event (
937
+ f. text_msg ( "hello world" )
938
+ . sender ( * ALICE )
939
+ . event_id ( threaded_event_id)
940
+ . in_thread ( & thread_root_event_id, threaded_event_id)
941
+ . server_ts ( MilliSecondsSinceUnixEpoch :: now ( ) ) ,
942
+ ) ,
943
+ )
944
+ . await ;
945
+
946
+ // Sanity check: I receive the event and the date divider.
947
+ assert_let_timeout ! ( Some ( timeline_updates) = stream. next( ) ) ;
948
+ assert_eq ! ( timeline_updates. len( ) , 2 ) ;
949
+
950
+ server. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
951
+
952
+ let sent_event_id = event_id ! ( "$sent_msg" ) ;
953
+ server. mock_room_send ( ) . ok ( sent_event_id) . mount ( ) . await ;
954
+
955
+ let media_src = owned_mxc_uri ! ( "mxc://example.com/1" ) ;
956
+ timeline
957
+ . send (
958
+ StickerEventContent :: new ( "sticker!" . to_owned ( ) , ImageInfo :: new ( ) , media_src. clone ( ) )
959
+ . into ( ) ,
960
+ )
961
+ . await
962
+ . unwrap ( ) ;
963
+
964
+ // I get the local echo for the in-thread event.
965
+ assert_let_timeout ! ( Some ( timeline_updates) = stream. next( ) ) ;
966
+ assert_eq ! ( timeline_updates. len( ) , 1 ) ;
967
+
968
+ assert_let ! ( VectorDiff :: PushBack { value } = & timeline_updates[ 0 ] ) ;
969
+ let event_item = value. as_event ( ) . unwrap ( ) ;
970
+
971
+ // The content matches what we expect.
972
+ let sticker_item = event_item. content ( ) . as_sticker ( ) . unwrap ( ) ;
973
+ let content = sticker_item. content ( ) ;
974
+ assert_eq ! ( content. body, "sticker!" ) ;
975
+ assert_let ! ( StickerMediaSource :: Plain ( plain) = content. source. clone( ) ) ;
976
+ assert_eq ! ( plain, media_src) ;
977
+
978
+ // Then we're done.
979
+ assert_pending ! ( stream) ;
980
+ }
981
+
982
+ #[ async_test]
983
+ async fn test_send_poll_thread ( ) {
984
+ // If I send a poll to a threaded timeline, it just works (aka the system to
985
+ // set the threaded relationship does kick in).
986
+
987
+ let server = MatrixMockServer :: new ( ) . await ;
988
+ let client = server. client_builder ( ) . build ( ) . await ;
989
+
990
+ let room_id = room_id ! ( "!a:b.c" ) ;
991
+ let thread_root_event_id = owned_event_id ! ( "$root" ) ;
992
+ let threaded_event_id = event_id ! ( "$threaded_event" ) ;
993
+
994
+ let room = server. sync_joined_room ( & client, room_id) . await ;
995
+
996
+ let timeline = room
997
+ . timeline_builder ( )
998
+ . with_focus ( TimelineFocus :: Thread { root_event_id : thread_root_event_id. clone ( ) } )
999
+ . build ( )
1000
+ . await
1001
+ . unwrap ( ) ;
1002
+
1003
+ let ( initial_items, mut stream) = timeline. subscribe ( ) . await ;
1004
+
1005
+ // At first, the timeline is empty.
1006
+ assert ! ( initial_items. is_empty( ) ) ;
1007
+ assert_pending ! ( stream) ;
1008
+
1009
+ // Start the timeline with an in-thread event.
1010
+ let f = EventFactory :: new ( ) ;
1011
+ server
1012
+ . sync_room (
1013
+ & client,
1014
+ JoinedRoomBuilder :: new ( room_id) . add_timeline_event (
1015
+ f. text_msg ( "hello world" )
1016
+ . sender ( * ALICE )
1017
+ . event_id ( threaded_event_id)
1018
+ . in_thread ( & thread_root_event_id, threaded_event_id)
1019
+ . server_ts ( MilliSecondsSinceUnixEpoch :: now ( ) ) ,
1020
+ ) ,
1021
+ )
1022
+ . await ;
1023
+
1024
+ // Sanity check: I receive the event and the date divider.
1025
+ assert_let_timeout ! ( Some ( timeline_updates) = stream. next( ) ) ;
1026
+ assert_eq ! ( timeline_updates. len( ) , 2 ) ;
1027
+
1028
+ server. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
1029
+
1030
+ let sent_event_id = event_id ! ( "$sent_msg" ) ;
1031
+ server. mock_room_send ( ) . ok ( sent_event_id) . mount ( ) . await ;
1032
+
1033
+ timeline
1034
+ . send (
1035
+ UnstablePollStartEventContent :: New ( NewUnstablePollStartEventContent :: plain_text (
1036
+ "let's vote" ,
1037
+ UnstablePollStartContentBlock :: new (
1038
+ "what day is it today?" ,
1039
+ vec ! [
1040
+ UnstablePollAnswer :: new( "0" , "monday" ) ,
1041
+ UnstablePollAnswer :: new( "1" , "friday" ) ,
1042
+ ]
1043
+ . try_into ( )
1044
+ . unwrap ( ) ,
1045
+ ) ,
1046
+ ) )
1047
+ . into ( ) ,
1048
+ )
1049
+ . await
1050
+ . unwrap ( ) ;
1051
+
1052
+ // I get the local echo for the in-thread event.
1053
+ assert_let_timeout ! ( Some ( timeline_updates) = stream. next( ) ) ;
1054
+ assert_eq ! ( timeline_updates. len( ) , 1 ) ;
1055
+
1056
+ assert_let ! ( VectorDiff :: PushBack { value } = & timeline_updates[ 0 ] ) ;
1057
+ let event_item = value. as_event ( ) . unwrap ( ) ;
1058
+
1059
+ // The content is a poll.
1060
+ assert ! ( event_item. content( ) . is_poll( ) ) ;
1061
+
1062
+ // Then we're done.
1063
+ assert_pending ! ( stream) ;
1064
+ }
1065
+
896
1066
#[ async_test]
897
1067
async fn test_sending_read_receipt_with_no_events_doesnt_unset_read_flag ( ) {
898
1068
// If a thread timeline has no events, then marking it as read doesn't unset the
0 commit comments