1616import json
1717
1818import synapse .rest .admin
19- from synapse .api .constants import EventContentFields , EventTypes
19+ from synapse .api .constants import EventContentFields , EventTypes , RelationTypes
2020from synapse .rest .client .v1 import login , room
21- from synapse .rest .client .v2_alpha import sync
21+ from synapse .rest .client .v2_alpha import read_marker , sync
2222
2323from tests import unittest
2424from tests .server import TimedOutException
@@ -324,3 +324,157 @@ def test_sync_backwards_typing(self):
324324 "GET" , sync_url % (access_token , next_batch )
325325 )
326326 self .assertRaises (TimedOutException , self .render , request )
327+
328+
329+ class UnreadMessagesTestCase (unittest .HomeserverTestCase ):
330+ servlets = [
331+ synapse .rest .admin .register_servlets ,
332+ login .register_servlets ,
333+ read_marker .register_servlets ,
334+ room .register_servlets ,
335+ sync .register_servlets ,
336+ ]
337+
338+ def prepare (self , reactor , clock , hs ):
339+ self .url = "/sync?since=%s"
340+ self .next_batch = "s0"
341+
342+ # Register the first user (used to check the unread counts).
343+ self .user_id = self .register_user ("kermit" , "monkey" )
344+ self .tok = self .login ("kermit" , "monkey" )
345+
346+ # Create the room we'll check unread counts for.
347+ self .room_id = self .helper .create_room_as (self .user_id , tok = self .tok )
348+
349+ # Register the second user (used to send events to the room).
350+ self .user2 = self .register_user ("kermit2" , "monkey" )
351+ self .tok2 = self .login ("kermit2" , "monkey" )
352+
353+ # Change the power levels of the room so that the second user can send state
354+ # events.
355+ self .helper .send_state (
356+ self .room_id ,
357+ EventTypes .PowerLevels ,
358+ {
359+ "users" : {self .user_id : 100 , self .user2 : 100 },
360+ "users_default" : 0 ,
361+ "events" : {
362+ "m.room.name" : 50 ,
363+ "m.room.power_levels" : 100 ,
364+ "m.room.history_visibility" : 100 ,
365+ "m.room.canonical_alias" : 50 ,
366+ "m.room.avatar" : 50 ,
367+ "m.room.tombstone" : 100 ,
368+ "m.room.server_acl" : 100 ,
369+ "m.room.encryption" : 100 ,
370+ },
371+ "events_default" : 0 ,
372+ "state_default" : 50 ,
373+ "ban" : 50 ,
374+ "kick" : 50 ,
375+ "redact" : 50 ,
376+ "invite" : 0 ,
377+ },
378+ tok = self .tok ,
379+ )
380+
381+ # @unittest.DEBUG
382+ def test_unread_counts (self ):
383+ """Tests that /sync returns the right value for the unread count (MSC2654)."""
384+
385+ # Check that our own messages don't increase the unread count.
386+ self .helper .send (self .room_id , "hello" , tok = self .tok )
387+ self ._check_unread_count (0 )
388+
389+ # Join the new user and check that this doesn't increase the unread count.
390+ self .helper .join (room = self .room_id , user = self .user2 , tok = self .tok2 )
391+ self ._check_unread_count (0 )
392+
393+ # Check that the new user sending a message increases our unread count.
394+ res = self .helper .send (self .room_id , "hello" , tok = self .tok2 )
395+ self ._check_unread_count (1 )
396+
397+ # Send a read receipt to tell the server we've read the latest event.
398+ body = json .dumps ({"m.read" : res ["event_id" ]}).encode ("utf8" )
399+ request , channel = self .make_request (
400+ "POST" ,
401+ "/rooms/%s/read_markers" % self .room_id ,
402+ body ,
403+ access_token = self .tok ,
404+ )
405+ self .render (request )
406+ self .assertEqual (channel .code , 200 , channel .json_body )
407+
408+ # Check that the unread counter is back to 0.
409+ self ._check_unread_count (0 )
410+
411+ # Check that room name changes increase the unread counter.
412+ self .helper .send_state (
413+ self .room_id , "m.room.name" , {"name" : "my super room" }, tok = self .tok2 ,
414+ )
415+ self ._check_unread_count (1 )
416+
417+ # Check that room topic changes increase the unread counter.
418+ self .helper .send_state (
419+ self .room_id , "m.room.topic" , {"topic" : "welcome!!!" }, tok = self .tok2 ,
420+ )
421+ self ._check_unread_count (2 )
422+
423+ # Check that encrypted messages increase the unread counter.
424+ self .helper .send_event (self .room_id , EventTypes .Encrypted , {}, tok = self .tok2 )
425+ self ._check_unread_count (3 )
426+
427+ # Check that custom events with a body increase the unread counter.
428+ self .helper .send_event (
429+ self .room_id , "org.matrix.custom_type" , {"body" : "hello" }, tok = self .tok2 ,
430+ )
431+ self ._check_unread_count (4 )
432+
433+ # Check that edits don't increase the unread counter.
434+ self .helper .send_event (
435+ room_id = self .room_id ,
436+ type = EventTypes .Message ,
437+ content = {
438+ "body" : "hello" ,
439+ "msgtype" : "m.text" ,
440+ "m.relates_to" : {"rel_type" : RelationTypes .REPLACE },
441+ },
442+ tok = self .tok2 ,
443+ )
444+ self ._check_unread_count (4 )
445+
446+ # Check that notices don't increase the unread counter.
447+ self .helper .send_event (
448+ room_id = self .room_id ,
449+ type = EventTypes .Message ,
450+ content = {"body" : "hello" , "msgtype" : "m.notice" },
451+ tok = self .tok2 ,
452+ )
453+ self ._check_unread_count (4 )
454+
455+ # Check that tombstone events changes increase the unread counter.
456+ self .helper .send_state (
457+ self .room_id ,
458+ EventTypes .Tombstone ,
459+ {"replacement_room" : "!someroom:test" },
460+ tok = self .tok2 ,
461+ )
462+ self ._check_unread_count (5 )
463+
464+ def _check_unread_count (self , expected_count : True ):
465+ """Syncs and compares the unread count with the expected value."""
466+
467+ request , channel = self .make_request (
468+ "GET" , self .url % self .next_batch , access_token = self .tok ,
469+ )
470+ self .render (request )
471+
472+ self .assertEqual (channel .code , 200 , channel .json_body )
473+
474+ room_entry = channel .json_body ["rooms" ]["join" ][self .room_id ]
475+ self .assertEqual (
476+ room_entry ["org.matrix.msc2654.unread_count" ], expected_count , room_entry ,
477+ )
478+
479+ # Store the next batch for the next request.
480+ self .next_batch = channel .json_body ["next_batch" ]
0 commit comments