3030from tests .server import FakeChannel
3131from tests .test_utils import make_awaitable
3232from tests .test_utils .event_injection import inject_event
33+ from tests .unittest import override_config
3334
3435
3536class BaseRelationsTestCase (unittest .HomeserverTestCase ):
@@ -355,30 +356,67 @@ def test_ignore_invalid_room(self) -> None:
355356 self .assertEqual (200 , channel .code , channel .json_body )
356357 self .assertNotIn ("m.relations" , channel .json_body ["unsigned" ])
357358
359+ def _assert_edit_bundle (
360+ self , event_json : JsonDict , edit_event_id : str , edit_event_content : JsonDict
361+ ) -> None :
362+ """
363+ Assert that the given event has a correctly-serialised edit event in its
364+ bundled aggregations
365+
366+ Args:
367+ event_json: the serialised event to be checked
368+ edit_event_id: the ID of the edit event that we expect to be bundled
369+ edit_event_content: the content of that event, excluding the 'm.relates_to`
370+ property
371+ """
372+ relations_dict = event_json ["unsigned" ].get ("m.relations" )
373+ self .assertIn (RelationTypes .REPLACE , relations_dict )
374+
375+ m_replace_dict = relations_dict [RelationTypes .REPLACE ]
376+ for key in [
377+ "event_id" ,
378+ "sender" ,
379+ "origin_server_ts" ,
380+ "content" ,
381+ "type" ,
382+ "unsigned" ,
383+ ]:
384+ self .assertIn (key , m_replace_dict )
385+
386+ expected_edit_content = {
387+ "m.relates_to" : {
388+ "event_id" : event_json ["event_id" ],
389+ "rel_type" : "m.replace" ,
390+ }
391+ }
392+ expected_edit_content .update (edit_event_content )
393+
394+ self .assert_dict (
395+ {
396+ "event_id" : edit_event_id ,
397+ "sender" : self .user_id ,
398+ "content" : expected_edit_content ,
399+ "type" : "m.room.message" ,
400+ },
401+ m_replace_dict ,
402+ )
403+
358404 def test_edit (self ) -> None :
359405 """Test that a simple edit works."""
360406
361407 new_body = {"msgtype" : "m.text" , "body" : "I've been edited!" }
408+ edit_event_content = {
409+ "msgtype" : "m.text" ,
410+ "body" : "foo" ,
411+ "m.new_content" : new_body ,
412+ }
362413 channel = self ._send_relation (
363414 RelationTypes .REPLACE ,
364415 "m.room.message" ,
365- content = { "msgtype" : "m.text" , "body" : "foo" , "m.new_content" : new_body } ,
416+ content = edit_event_content ,
366417 )
367418 edit_event_id = channel .json_body ["event_id" ]
368419
369- def assert_bundle (event_json : JsonDict ) -> None :
370- """Assert the expected values of the bundled aggregations."""
371- relations_dict = event_json ["unsigned" ].get ("m.relations" )
372- self .assertIn (RelationTypes .REPLACE , relations_dict )
373-
374- m_replace_dict = relations_dict [RelationTypes .REPLACE ]
375- for key in ["event_id" , "sender" , "origin_server_ts" ]:
376- self .assertIn (key , m_replace_dict )
377-
378- self .assert_dict (
379- {"event_id" : edit_event_id , "sender" : self .user_id }, m_replace_dict
380- )
381-
382420 # /event should return the *original* event
383421 channel = self .make_request (
384422 "GET" ,
@@ -389,7 +427,7 @@ def assert_bundle(event_json: JsonDict) -> None:
389427 self .assertEqual (
390428 channel .json_body ["content" ], {"body" : "Hi!" , "msgtype" : "m.text" }
391429 )
392- assert_bundle (channel .json_body )
430+ self . _assert_edit_bundle (channel .json_body , edit_event_id , edit_event_content )
393431
394432 # Request the room messages.
395433 channel = self .make_request (
@@ -398,7 +436,11 @@ def assert_bundle(event_json: JsonDict) -> None:
398436 access_token = self .user_token ,
399437 )
400438 self .assertEqual (200 , channel .code , channel .json_body )
401- assert_bundle (self ._find_event_in_chunk (channel .json_body ["chunk" ]))
439+ self ._assert_edit_bundle (
440+ self ._find_event_in_chunk (channel .json_body ["chunk" ]),
441+ edit_event_id ,
442+ edit_event_content ,
443+ )
402444
403445 # Request the room context.
404446 # /context should return the edited event.
@@ -408,7 +450,9 @@ def assert_bundle(event_json: JsonDict) -> None:
408450 access_token = self .user_token ,
409451 )
410452 self .assertEqual (200 , channel .code , channel .json_body )
411- assert_bundle (channel .json_body ["event" ])
453+ self ._assert_edit_bundle (
454+ channel .json_body ["event" ], edit_event_id , edit_event_content
455+ )
412456 self .assertEqual (channel .json_body ["event" ]["content" ], new_body )
413457
414458 # Request sync, but limit the timeline so it becomes limited (and includes
@@ -420,7 +464,11 @@ def assert_bundle(event_json: JsonDict) -> None:
420464 self .assertEqual (200 , channel .code , channel .json_body )
421465 room_timeline = channel .json_body ["rooms" ]["join" ][self .room ]["timeline" ]
422466 self .assertTrue (room_timeline ["limited" ])
423- assert_bundle (self ._find_event_in_chunk (room_timeline ["events" ]))
467+ self ._assert_edit_bundle (
468+ self ._find_event_in_chunk (room_timeline ["events" ]),
469+ edit_event_id ,
470+ edit_event_content ,
471+ )
424472
425473 # Request search.
426474 channel = self .make_request (
@@ -437,7 +485,45 @@ def assert_bundle(event_json: JsonDict) -> None:
437485 "results"
438486 ]
439487 ]
440- assert_bundle (self ._find_event_in_chunk (chunk ))
488+ self ._assert_edit_bundle (
489+ self ._find_event_in_chunk (chunk ),
490+ edit_event_id ,
491+ edit_event_content ,
492+ )
493+
494+ @override_config ({"experimental_features" : {"msc3925_inhibit_edit" : True }})
495+ def test_edit_inhibit_replace (self ) -> None :
496+ """
497+ If msc3925_inhibit_edit is enabled, then the original event should not be
498+ replaced.
499+ """
500+
501+ new_body = {"msgtype" : "m.text" , "body" : "I've been edited!" }
502+ edit_event_content = {
503+ "msgtype" : "m.text" ,
504+ "body" : "foo" ,
505+ "m.new_content" : new_body ,
506+ }
507+ channel = self ._send_relation (
508+ RelationTypes .REPLACE ,
509+ "m.room.message" ,
510+ content = edit_event_content ,
511+ )
512+ edit_event_id = channel .json_body ["event_id" ]
513+
514+ # /context should return the *original* event.
515+ channel = self .make_request (
516+ "GET" ,
517+ f"/rooms/{ self .room } /context/{ self .parent_id } " ,
518+ access_token = self .user_token ,
519+ )
520+ self .assertEqual (200 , channel .code , channel .json_body )
521+ self .assertEqual (
522+ channel .json_body ["event" ]["content" ], {"body" : "Hi!" , "msgtype" : "m.text" }
523+ )
524+ self ._assert_edit_bundle (
525+ channel .json_body ["event" ], edit_event_id , edit_event_content
526+ )
441527
442528 def test_multi_edit (self ) -> None :
443529 """Test that multiple edits, including attempts by people who
@@ -455,10 +541,15 @@ def test_multi_edit(self) -> None:
455541 )
456542
457543 new_body = {"msgtype" : "m.text" , "body" : "I've been edited!" }
544+ edit_event_content = {
545+ "msgtype" : "m.text" ,
546+ "body" : "foo" ,
547+ "m.new_content" : new_body ,
548+ }
458549 channel = self ._send_relation (
459550 RelationTypes .REPLACE ,
460551 "m.room.message" ,
461- content = { "msgtype" : "m.text" , "body" : "foo" , "m.new_content" : new_body } ,
552+ content = edit_event_content ,
462553 )
463554 edit_event_id = channel .json_body ["event_id" ]
464555
@@ -480,16 +571,8 @@ def test_multi_edit(self) -> None:
480571 self .assertEqual (200 , channel .code , channel .json_body )
481572
482573 self .assertEqual (channel .json_body ["event" ]["content" ], new_body )
483-
484- relations_dict = channel .json_body ["event" ]["unsigned" ].get ("m.relations" )
485- self .assertIn (RelationTypes .REPLACE , relations_dict )
486-
487- m_replace_dict = relations_dict [RelationTypes .REPLACE ]
488- for key in ["event_id" , "sender" , "origin_server_ts" ]:
489- self .assertIn (key , m_replace_dict )
490-
491- self .assert_dict (
492- {"event_id" : edit_event_id , "sender" : self .user_id }, m_replace_dict
574+ self ._assert_edit_bundle (
575+ channel .json_body ["event" ], edit_event_id , edit_event_content
493576 )
494577
495578 def test_edit_reply (self ) -> None :
@@ -502,11 +585,15 @@ def test_edit_reply(self) -> None:
502585 )
503586 reply = channel .json_body ["event_id" ]
504587
505- new_body = {"msgtype" : "m.text" , "body" : "I've been edited!" }
588+ edit_event_content = {
589+ "msgtype" : "m.text" ,
590+ "body" : "foo" ,
591+ "m.new_content" : {"msgtype" : "m.text" , "body" : "I've been edited!" },
592+ }
506593 channel = self ._send_relation (
507594 RelationTypes .REPLACE ,
508595 "m.room.message" ,
509- content = { "msgtype" : "m.text" , "body" : "foo" , "m.new_content" : new_body } ,
596+ content = edit_event_content ,
510597 parent_id = reply ,
511598 )
512599 edit_event_id = channel .json_body ["event_id" ]
@@ -549,28 +636,22 @@ def test_edit_reply(self) -> None:
549636
550637 # We expect that the edit relation appears in the unsigned relations
551638 # section.
552- relations_dict = result_event_dict ["unsigned" ].get ("m.relations" )
553- self .assertIn (RelationTypes .REPLACE , relations_dict , desc )
554-
555- m_replace_dict = relations_dict [RelationTypes .REPLACE ]
556- for key in ["event_id" , "sender" , "origin_server_ts" ]:
557- self .assertIn (key , m_replace_dict , desc )
558-
559- self .assert_dict (
560- {"event_id" : edit_event_id , "sender" : self .user_id }, m_replace_dict
639+ self ._assert_edit_bundle (
640+ result_event_dict , edit_event_id , edit_event_content
561641 )
562642
563643 def test_edit_edit (self ) -> None :
564644 """Test that an edit cannot be edited."""
565645 new_body = {"msgtype" : "m.text" , "body" : "Initial edit" }
646+ edit_event_content = {
647+ "msgtype" : "m.text" ,
648+ "body" : "Wibble" ,
649+ "m.new_content" : new_body ,
650+ }
566651 channel = self ._send_relation (
567652 RelationTypes .REPLACE ,
568653 "m.room.message" ,
569- content = {
570- "msgtype" : "m.text" ,
571- "body" : "Wibble" ,
572- "m.new_content" : new_body ,
573- },
654+ content = edit_event_content ,
574655 )
575656 edit_event_id = channel .json_body ["event_id" ]
576657
@@ -599,8 +680,7 @@ def test_edit_edit(self) -> None:
599680 )
600681
601682 # The relations information should not include the edit to the edit.
602- relations_dict = channel .json_body ["unsigned" ].get ("m.relations" )
603- self .assertIn (RelationTypes .REPLACE , relations_dict )
683+ self ._assert_edit_bundle (channel .json_body , edit_event_id , edit_event_content )
604684
605685 # /context should return the event updated for the *first* edit
606686 # (The edit to the edit should be ignored.)
@@ -611,13 +691,8 @@ def test_edit_edit(self) -> None:
611691 )
612692 self .assertEqual (200 , channel .code , channel .json_body )
613693 self .assertEqual (channel .json_body ["event" ]["content" ], new_body )
614-
615- m_replace_dict = relations_dict [RelationTypes .REPLACE ]
616- for key in ["event_id" , "sender" , "origin_server_ts" ]:
617- self .assertIn (key , m_replace_dict )
618-
619- self .assert_dict (
620- {"event_id" : edit_event_id , "sender" : self .user_id }, m_replace_dict
694+ self ._assert_edit_bundle (
695+ channel .json_body ["event" ], edit_event_id , edit_event_content
621696 )
622697
623698 # Directly requesting the edit should not have the edit to the edit applied.
0 commit comments