@@ -1095,6 +1095,112 @@ async fn test_notification_client_sliding_sync_filters_out_events_from_ignored_u
1095
1095
} ;
1096
1096
}
1097
1097
1098
+ #[ cfg( feature = "unstable-msc4359" ) ]
1099
+ #[ async_test]
1100
+ async fn test_notification_client_sliding_sync_filters_out_events_from_do_not_disturb_rooms ( ) {
1101
+ let server = MatrixMockServer :: new ( ) . await ;
1102
+ let client = server. client_builder ( ) . build ( ) . await ;
1103
+
1104
+ let sender = user_id ! ( "@user:example.org" ) ;
1105
+ let my_user_id = client. user_id ( ) . unwrap ( ) . to_owned ( ) ;
1106
+
1107
+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
1108
+ let room_name = "The Maltese Falcon" ;
1109
+ let sender_display_name = "John Mastodon" ;
1110
+ let event_id = event_id ! ( "$example_event_id" ) ;
1111
+
1112
+ let raw_event = EventFactory :: new ( )
1113
+ . room ( room_id)
1114
+ . sender ( sender)
1115
+ . text_msg ( "Heya" )
1116
+ . event_id ( event_id)
1117
+ . into_raw_sync ( ) ;
1118
+
1119
+ let event_factory = EventFactory :: new ( ) . room ( room_id) ;
1120
+
1121
+ let sender_member_event = event_factory
1122
+ . member ( sender)
1123
+ . display_name ( sender_display_name)
1124
+ . membership ( MembershipState :: Join )
1125
+ . into_raw_sync ( ) ;
1126
+
1127
+ let own_member_event = event_factory
1128
+ . member ( & my_user_id)
1129
+ . display_name ( "My self" )
1130
+ . membership ( MembershipState :: Join )
1131
+ . into_raw_sync ( ) ;
1132
+
1133
+ let power_levels_event =
1134
+ event_factory. sender ( sender) . power_levels ( & mut BTreeMap :: new ( ) ) . into_raw_sync ( ) ;
1135
+
1136
+ let pos = Mutex :: new ( 0 ) ;
1137
+ Mock :: given ( SlidingSyncMatcher )
1138
+ . respond_with ( move |request : & Request | {
1139
+ let partial_request: PartialSlidingSyncRequest = request. body_json ( ) . unwrap ( ) ;
1140
+ // Repeat the transaction id in the response, to validate sticky parameters.
1141
+ let mut pos = pos. lock ( ) . unwrap ( ) ;
1142
+ * pos += 1 ;
1143
+ let pos_as_str = ( * pos) . to_string ( ) ;
1144
+ ResponseTemplate :: new ( 200 ) . set_body_json ( json ! ( {
1145
+ "txn_id" : partial_request. txn_id,
1146
+ "pos" : pos_as_str,
1147
+ "rooms" : {
1148
+ room_id: {
1149
+ "name" : room_name,
1150
+ "initial" : true ,
1151
+
1152
+ "required_state" : [
1153
+ // Sender's member information.
1154
+ sender_member_event,
1155
+
1156
+ // Own member information.
1157
+ own_member_event,
1158
+
1159
+ // Power levels.
1160
+ power_levels_event,
1161
+ ] ,
1162
+
1163
+ "timeline" : [
1164
+ raw_event,
1165
+ ]
1166
+ }
1167
+ } ,
1168
+
1169
+ "extensions" : {
1170
+ "account_data" : {
1171
+ "global" : [ {
1172
+ "type" : "dm.filament.do_not_disturb" ,
1173
+ "content" : {
1174
+ "rooms" : { room_id: { } }
1175
+ }
1176
+ } ]
1177
+ }
1178
+ }
1179
+ } ) )
1180
+ } )
1181
+ . mount ( server. server ( ) )
1182
+ . await ;
1183
+
1184
+ let dummy_sync_service = Arc :: new ( SyncService :: builder ( client. clone ( ) ) . build ( ) . await . unwrap ( ) ) ;
1185
+ let process_setup =
1186
+ NotificationProcessSetup :: SingleProcess { sync_service : dummy_sync_service } ;
1187
+ let notification_client = NotificationClient :: new ( client, process_setup) . await . unwrap ( ) ;
1188
+ let mut result = notification_client
1189
+ . get_notifications_with_sliding_sync ( & [ NotificationItemsRequest {
1190
+ room_id : room_id. to_owned ( ) ,
1191
+ event_ids : vec ! [ event_id. to_owned( ) ] ,
1192
+ } ] )
1193
+ . await
1194
+ . unwrap ( ) ;
1195
+
1196
+ let Some ( Ok ( item) ) = result. remove ( event_id) else {
1197
+ panic ! ( "fetching notification for {event_id} failed" ) ;
1198
+ } ;
1199
+ let NotificationStatus :: EventFilteredOut = item else {
1200
+ panic ! ( "notification for {event_id} was not filtered out" ) ;
1201
+ } ;
1202
+ }
1203
+
1098
1204
#[ async_test]
1099
1205
async fn test_notification_client_context_filters_out_events_from_ignored_users ( ) {
1100
1206
let server = MatrixMockServer :: new ( ) . await ;
@@ -1172,3 +1278,82 @@ async fn test_notification_client_context_filters_out_events_from_ignored_users(
1172
1278
1173
1279
assert_matches ! ( result, NotificationStatus :: EventFilteredOut ) ;
1174
1280
}
1281
+
1282
+ #[ cfg( feature = "unstable-msc4359" ) ]
1283
+ #[ async_test]
1284
+ async fn test_notification_client_context_filters_out_events_from_do_not_disturb_rooms ( ) {
1285
+ let server = MatrixMockServer :: new ( ) . await ;
1286
+ let client = server. client_builder ( ) . build ( ) . await ;
1287
+
1288
+ let sender = user_id ! ( "@user:example.org" ) ;
1289
+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
1290
+ let event_id = event_id ! ( "$example_event_id" ) ;
1291
+
1292
+ server. sync_joined_room ( & client, room_id) . await ;
1293
+
1294
+ // Add mock for sliding sync so we get the ignored user list from its account
1295
+ // data
1296
+ let pos = Mutex :: new ( 0 ) ;
1297
+ Mock :: given ( SlidingSyncMatcher )
1298
+ . respond_with ( move |request : & Request | {
1299
+ let partial_request: PartialSlidingSyncRequest = request. body_json ( ) . unwrap ( ) ;
1300
+ // Repeat the transaction id in the response, to validate sticky parameters.
1301
+ let mut pos = pos. lock ( ) . unwrap ( ) ;
1302
+ * pos += 1 ;
1303
+ let pos_as_str = ( * pos) . to_string ( ) ;
1304
+ ResponseTemplate :: new ( 200 ) . set_body_json ( json ! ( {
1305
+ "txn_id" : partial_request. txn_id,
1306
+ "pos" : pos_as_str,
1307
+ "rooms" : { } ,
1308
+
1309
+ "extensions" : {
1310
+ "account_data" : {
1311
+ "global" : [ {
1312
+ "type" : "dm.filament.do_not_disturb" ,
1313
+ "content" : {
1314
+ "rooms" : { room_id: { } }
1315
+ }
1316
+ } ]
1317
+ }
1318
+ }
1319
+ } ) )
1320
+ } )
1321
+ . mount ( server. server ( ) )
1322
+ . await ;
1323
+
1324
+ let event = EventFactory :: new ( )
1325
+ . room ( room_id)
1326
+ . sender ( sender)
1327
+ . text_msg ( "Heya" )
1328
+ . event_id ( event_id)
1329
+ . into_event ( ) ;
1330
+
1331
+ // Mock the /context response
1332
+ server
1333
+ . mock_room_event_context ( )
1334
+ . ok ( RoomContextResponseTemplate :: new ( event) . start ( "start" ) . end ( "end" ) )
1335
+ . mock_once ( )
1336
+ . mount ( )
1337
+ . await ;
1338
+
1339
+ let dummy_sync_service = Arc :: new ( SyncService :: builder ( client. clone ( ) ) . build ( ) . await . unwrap ( ) ) ;
1340
+ let process_setup =
1341
+ NotificationProcessSetup :: SingleProcess { sync_service : dummy_sync_service } ;
1342
+ let notification_client = NotificationClient :: new ( client, process_setup) . await . unwrap ( ) ;
1343
+
1344
+ // Call sync first so we get the list of ignored users in the notification
1345
+ // client This should still work in a real life usage
1346
+ let _ = notification_client
1347
+ . get_notifications_with_sliding_sync ( & [ NotificationItemsRequest {
1348
+ room_id : room_id. to_owned ( ) ,
1349
+ event_ids : vec ! [ event_id. to_owned( ) ] ,
1350
+ } ] )
1351
+ . await ;
1352
+
1353
+ // If the event is not found even though there was a mocked response for it, it
1354
+ // was discarded as expected.
1355
+ let result =
1356
+ notification_client. get_notification_with_context ( room_id, event_id) . await . unwrap ( ) ;
1357
+
1358
+ assert_matches ! ( result, NotificationStatus :: EventFilteredOut ) ;
1359
+ }
0 commit comments