@@ -4,10 +4,13 @@ use std::{
4
4
} ;
5
5
6
6
use assert_matches:: assert_matches;
7
- use matrix_sdk:: { config:: SyncSettings , test_utils:: logged_in_client_with_server} ;
7
+ use matrix_sdk:: {
8
+ config:: SyncSettings ,
9
+ test_utils:: { logged_in_client_with_server, mocks:: MatrixMockServer } ,
10
+ } ;
8
11
use matrix_sdk_test:: {
9
- async_test, event_factory :: EventFactory , mocks:: mock_encryption_state, JoinedRoomBuilder ,
10
- StateTestEvent , SyncResponseBuilder ,
12
+ async_test, mocks:: mock_encryption_state, JoinedRoomBuilder , StateTestEvent ,
13
+ SyncResponseBuilder ,
11
14
} ;
12
15
use matrix_sdk_ui:: {
13
16
notification_client:: {
@@ -1068,3 +1071,227 @@ async fn test_notification_client_mixed() {
1068
1071
assert_eq ! ( item. room_computed_display_name, sender_display_name) ;
1069
1072
assert_eq ! ( item. is_noisy, Some ( false ) ) ;
1070
1073
}
1074
+
1075
+ #[ async_test]
1076
+ async fn test_notification_client_sliding_sync_filters_out_events_from_ignored_users ( ) {
1077
+ let server = MatrixMockServer :: new ( ) . await ;
1078
+ let client = server. client_builder ( ) . build ( ) . await ;
1079
+
1080
+ let sender = user_id ! ( "@user:example.org" ) ;
1081
+ let my_user_id = client. user_id ( ) . unwrap ( ) . to_owned ( ) ;
1082
+
1083
+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
1084
+ let room_name = "The Maltese Falcon" ;
1085
+ let sender_display_name = "John Mastodon" ;
1086
+ let sender_avatar_url = "https://example.org/avatar.jpeg" ;
1087
+ let event_id = event_id ! ( "$example_event_id" ) ;
1088
+
1089
+ let raw_event = EventFactory :: new ( )
1090
+ . room ( room_id)
1091
+ . sender ( sender)
1092
+ . text_msg ( "Heya" )
1093
+ . event_id ( event_id)
1094
+ . into_raw_sync ( ) ;
1095
+
1096
+ let pos = Mutex :: new ( 0 ) ;
1097
+ Mock :: given ( SlidingSyncMatcher )
1098
+ . respond_with ( move |request : & Request | {
1099
+ let partial_request: PartialSlidingSyncRequest = request. body_json ( ) . unwrap ( ) ;
1100
+ // Repeat the transaction id in the response, to validate sticky parameters.
1101
+ let mut pos = pos. lock ( ) . unwrap ( ) ;
1102
+ * pos += 1 ;
1103
+ let pos_as_str = ( * pos) . to_string ( ) ;
1104
+ ResponseTemplate :: new ( 200 ) . set_body_json ( json ! ( {
1105
+ "txn_id" : partial_request. txn_id,
1106
+ "pos" : pos_as_str,
1107
+ "rooms" : {
1108
+ room_id: {
1109
+ "name" : room_name,
1110
+ "initial" : true ,
1111
+
1112
+ "required_state" : [
1113
+ // Sender's member information.
1114
+ {
1115
+ "content" : {
1116
+ "avatar_url" : sender_avatar_url,
1117
+ "displayname" : sender_display_name,
1118
+ "membership" : "join"
1119
+ } ,
1120
+ "room_id" : room_id,
1121
+ "event_id" : "$151800140517rfvjc:example.org" ,
1122
+ "membership" : "join" ,
1123
+ "origin_server_ts" : 151800140 ,
1124
+ "sender" : sender,
1125
+ "state_key" : sender,
1126
+ "type" : "m.room.member" ,
1127
+ "unsigned" : {
1128
+ "age" : 2970366 ,
1129
+ }
1130
+ } ,
1131
+
1132
+ // Own member information.
1133
+ {
1134
+ "content" : {
1135
+ "avatar_url" : null,
1136
+ "displayname" : "My Self" ,
1137
+ "membership" : "join"
1138
+ } ,
1139
+ "room_id" : room_id,
1140
+ "event_id" : "$151800140517rflkc:example.org" ,
1141
+ "membership" : "join" ,
1142
+ "origin_server_ts" : 151800140 ,
1143
+ "sender" : my_user_id. clone( ) ,
1144
+ "state_key" : my_user_id,
1145
+ "type" : "m.room.member" ,
1146
+ "unsigned" : {
1147
+ "age" : 2970366 ,
1148
+ }
1149
+ } ,
1150
+
1151
+ // Power levels.
1152
+ {
1153
+ "content" : {
1154
+ "ban" : 50 ,
1155
+ "events" : {
1156
+ "m.room.avatar" : 50 ,
1157
+ "m.room.canonical_alias" : 50 ,
1158
+ "m.room.history_visibility" : 100 ,
1159
+ "m.room.name" : 50 ,
1160
+ "m.room.power_levels" : 100 ,
1161
+ "m.room.message" : 25 ,
1162
+ } ,
1163
+ "events_default" : 0 ,
1164
+ "invite" : 0 ,
1165
+ "kick" : 50 ,
1166
+ "redact" : 50 ,
1167
+ "state_default" : 50 ,
1168
+ "users" : {
1169
+ "@example:localhost" : 100 ,
1170
+ sender: 0 ,
1171
+ } ,
1172
+ "users_default" : 0 ,
1173
+ } ,
1174
+ "event_id" : "$15139375512JaHAW:localhost" ,
1175
+ "origin_server_ts" : 151393755 ,
1176
+ "sender" : "@example:localhost" ,
1177
+ "state_key" : "" ,
1178
+ "type" : "m.room.power_levels" ,
1179
+ "unsigned" : {
1180
+ "age" : 703422 ,
1181
+ } ,
1182
+ } ,
1183
+ ] ,
1184
+
1185
+ "timeline" : [
1186
+ raw_event,
1187
+ ]
1188
+ }
1189
+ } ,
1190
+
1191
+ "extensions" : {
1192
+ "account_data" : {
1193
+ "global" : [ {
1194
+ "type" : "m.ignored_user_list" ,
1195
+ "content" : {
1196
+ "ignored_users" : { sender: { } }
1197
+ }
1198
+ } ]
1199
+ }
1200
+ }
1201
+ } ) )
1202
+ } )
1203
+ . mount ( server. server ( ) )
1204
+ . await ;
1205
+
1206
+ let dummy_sync_service = Arc :: new ( SyncService :: builder ( client. clone ( ) ) . build ( ) . await . unwrap ( ) ) ;
1207
+ let process_setup =
1208
+ NotificationProcessSetup :: SingleProcess { sync_service : dummy_sync_service } ;
1209
+ let notification_client = NotificationClient :: new ( client, process_setup) . await . unwrap ( ) ;
1210
+ let mut result = notification_client
1211
+ . get_notifications_with_sliding_sync ( & [ NotificationItemsRequest {
1212
+ room_id : room_id. to_owned ( ) ,
1213
+ event_ids : vec ! [ event_id. to_owned( ) ] ,
1214
+ } ] )
1215
+ . await
1216
+ . unwrap ( ) ;
1217
+
1218
+ let Some ( Ok ( item) ) = result. remove ( event_id) else {
1219
+ panic ! ( "fetching notification for {event_id} failed" ) ;
1220
+ } ;
1221
+ let NotificationStatus :: EventFilteredOut = item else {
1222
+ panic ! ( "notification for {event_id} was not filtered out" ) ;
1223
+ } ;
1224
+ }
1225
+
1226
+ #[ async_test]
1227
+ async fn test_notification_client_context_filters_out_events_from_ignored_users ( ) {
1228
+ let server = MatrixMockServer :: new ( ) . await ;
1229
+ let client = server. client_builder ( ) . build ( ) . await ;
1230
+
1231
+ let sender = user_id ! ( "@user:example.org" ) ;
1232
+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
1233
+ let event_id = event_id ! ( "$example_event_id" ) ;
1234
+
1235
+ server. sync_joined_room ( & client, room_id) . await ;
1236
+
1237
+ // Add mock for sliding sync so we get the ignored user list from its account
1238
+ // data
1239
+ let pos = Mutex :: new ( 0 ) ;
1240
+ Mock :: given ( SlidingSyncMatcher )
1241
+ . respond_with ( move |request : & Request | {
1242
+ let partial_request: PartialSlidingSyncRequest = request. body_json ( ) . unwrap ( ) ;
1243
+ // Repeat the transaction id in the response, to validate sticky parameters.
1244
+ let mut pos = pos. lock ( ) . unwrap ( ) ;
1245
+ * pos += 1 ;
1246
+ let pos_as_str = ( * pos) . to_string ( ) ;
1247
+ ResponseTemplate :: new ( 200 ) . set_body_json ( json ! ( {
1248
+ "txn_id" : partial_request. txn_id,
1249
+ "pos" : pos_as_str,
1250
+ "rooms" : { } ,
1251
+
1252
+ "extensions" : {
1253
+ "account_data" : {
1254
+ "global" : [ {
1255
+ "type" : "m.ignored_user_list" ,
1256
+ "content" : {
1257
+ "ignored_users" : { sender: { } }
1258
+ }
1259
+ } ]
1260
+ }
1261
+ }
1262
+ } ) )
1263
+ } )
1264
+ . mount ( server. server ( ) )
1265
+ . await ;
1266
+
1267
+ let event = EventFactory :: new ( )
1268
+ . room ( room_id)
1269
+ . sender ( sender)
1270
+ . text_msg ( "Heya" )
1271
+ . event_id ( event_id)
1272
+ . into_event ( ) ;
1273
+
1274
+ // Mock the /context response
1275
+ server. mock_room_event_context ( ) . ok ( event, "start" , "end" ) . mock_once ( ) . mount ( ) . await ;
1276
+
1277
+ let dummy_sync_service = Arc :: new ( SyncService :: builder ( client. clone ( ) ) . build ( ) . await . unwrap ( ) ) ;
1278
+ let process_setup =
1279
+ NotificationProcessSetup :: SingleProcess { sync_service : dummy_sync_service } ;
1280
+ let notification_client = NotificationClient :: new ( client, process_setup) . await . unwrap ( ) ;
1281
+
1282
+ // Call sync first so we get the list of ignored users in the notification
1283
+ // client This should still work in a real life usage
1284
+ let _ = notification_client
1285
+ . get_notifications_with_sliding_sync ( & [ NotificationItemsRequest {
1286
+ room_id : room_id. to_owned ( ) ,
1287
+ event_ids : vec ! [ event_id. to_owned( ) ] ,
1288
+ } ] )
1289
+ . await ;
1290
+
1291
+ // If the event is not found even though there was a mocked response for it, it
1292
+ // was discarded as expected
1293
+ let result =
1294
+ notification_client. get_notification_with_context ( room_id, event_id) . await . unwrap ( ) ;
1295
+
1296
+ assert ! ( result. is_none( ) ) ;
1297
+ }
0 commit comments