@@ -448,6 +448,33 @@ def test_room_creation_fails_with_invalid_initial_state(
448448 new_callable = AsyncMock ,
449449)
450450class TestAssignGroupsToManagedRoom (ModuleApiTestCase ):
451+ def assert_join_for_users (self , room_id : str , users : list [str ]) -> None :
452+ """Helper function to assert the list of users are joined to the room."""
453+ for member in users :
454+ path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
455+ channel = self .make_request (
456+ "GET" , path , access_token = self .creator_access_token
457+ )
458+ assert (
459+ channel .code == HTTPStatus .OK
460+ ), f"Expected 200 but got { channel .code } for member { member } "
461+ assert (
462+ channel .json_body ["membership" ] == "join"
463+ ), f"Expected membership to be join but got { channel .json_body ['membership' ]} for member { member } "
464+
465+ def assert_leave_for_users (self , room_id : str , users : list [str ]) -> None :
466+ """Helper function to assert the users have left the room."""
467+ for member in users :
468+ path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
469+ channel = self .make_request (
470+ "GET" , path , access_token = self .creator_access_token
471+ )
472+ assert (
473+ channel .code == HTTPStatus .OK
474+ ), f"Expected 200 but got { channel .code } for member { member } "
475+ assert (
476+ channel .json_body ["membership" ] == "leave"
477+ ), f"Expected membership to be leave but got { channel .json_body ['membership' ]} for member { member } "
451478
452479 def test_update_single_group_to_single_group (self , mock_get_group_members ) -> None :
453480 """Tests that managed room which already have groups can be updated and the
@@ -493,27 +520,10 @@ def get_group_members(group_id): # in real case this should return external_ids
493520 assert channel .code == HTTPStatus .OK , channel .result
494521
495522 # Check if the new member of the group is joined to the room
496- for member in new_group_members :
497- path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
498- channel = self .make_request (
499- "GET" , path , access_token = self .creator_access_token
500- )
501- assert (
502- channel .code == HTTPStatus .OK
503- ), f"Expected 200 but got { channel .code } for member { member } "
504- assert (
505- channel .json_body ["membership" ] == "join"
506- ), f"Expected membership to be join but got { channel .json_body ['membership' ]} for member { member } "
523+ self .assert_join_for_users (room_id , new_group_members )
507524
508525 # Check if the old member who is not in the new group is removed from the room
509- path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ test_member_1 } "
510- channel = self .make_request ("GET" , path , access_token = self .creator_access_token )
511- assert (
512- channel .code == HTTPStatus .OK
513- ), f"Expected 200 but got { channel .code } for member { test_member_1 } "
514- assert (
515- channel .json_body ["membership" ] == "leave"
516- ), f"Expected membership to be leave but got { channel .json_body ['membership' ]} for member { test_member_1 } "
526+ self .assert_leave_for_users (room_id , [test_member_1 ])
517527
518528 # Check the account data is updated
519529 room_account_data = self .get_success (
@@ -606,29 +616,8 @@ def get_members_by_group(
606616 member_should_not_be_in_room = [test_member_r ]
607617
608618 # Check if the new member of the group is joined to the room
609- for member in member_should_be_in_room :
610- path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
611- channel = self .make_request (
612- "GET" , path , access_token = self .creator_access_token
613- )
614- assert (
615- channel .code == HTTPStatus .OK
616- ), f"Expected 200 but got { channel .code } for member { member } "
617- assert (
618- channel .json_body ["membership" ] == "join"
619- ), f"Expected membership to be join but got { channel .json_body ['membership' ]} for member { member } "
620-
621- for member in member_should_not_be_in_room :
622- path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
623- channel = self .make_request (
624- "GET" , path , access_token = self .creator_access_token
625- )
626- assert (
627- channel .code == HTTPStatus .OK
628- ), f"Expected 200 but got { channel .code } for member { member } "
629- assert (
630- channel .json_body ["membership" ] == "leave"
631- ), f"Expected membership to be leave but got { channel .json_body ['membership' ]} for member { member } "
619+ self .assert_join_for_users (room_id , list (member_should_be_in_room ))
620+ self .assert_leave_for_users (room_id , member_should_not_be_in_room )
632621
633622 # Check the account data is updated
634623 room_account_data = self .get_success (
@@ -731,29 +720,8 @@ def get_members_by_group(
731720 member_should_not_be_in_room = [test_member_c ] + test_group_3_members
732721
733722 # Check if the new member of the group is joined to the room
734- for member in member_should_be_in_room :
735- path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
736- channel = self .make_request (
737- "GET" , path , access_token = self .creator_access_token
738- )
739- assert (
740- channel .code == HTTPStatus .OK
741- ), f"Expected 200 but got { channel .code } for member { member } "
742- assert (
743- channel .json_body ["membership" ] == "join"
744- ), f"Expected membership to be join but got { channel .json_body ['membership' ]} for member { member } "
745-
746- for member in member_should_not_be_in_room :
747- path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
748- channel = self .make_request (
749- "GET" , path , access_token = self .creator_access_token
750- )
751- assert (
752- channel .code == HTTPStatus .OK
753- ), f"Expected 200 but got { channel .code } for member { member } "
754- assert (
755- channel .json_body ["membership" ] == "leave"
756- ), f"Expected membership to be leave but got { channel .json_body ['membership' ]} for member { member } "
723+ self .assert_join_for_users (room_id , member_should_be_in_room )
724+ self .assert_leave_for_users (room_id , member_should_not_be_in_room )
757725
758726 # Check the account data is updated
759727 room_account_data = self .get_success (
@@ -763,6 +731,63 @@ def get_members_by_group(
763731 MANAGED_ROOM_TYPE : {"groups" : new_group_info }
764732 }, room_account_data
765733
734+ def test_user_from_removed_group_is_still_in_other_assigned_group (
735+ self , mock_get_group_members
736+ ) -> None :
737+ """
738+ Test the edge case when the member_r was both in group 1 and group 2, and
739+ group 2 was removed from the room.
740+ Old groups info: test_group_1, test_group_2
741+ New groups info: test_group_1
742+ """
743+ test_group_1 = "test_group_1"
744+ test_member_a = self .register_user ("test_member_a" , "password" )
745+ test_member_r = self .register_user ("test_member_r" , "password" )
746+
747+ test_group_2 = "test_group_2"
748+ test_member_b = self .register_user ("test_member_b" , "password" )
749+
750+ old_group_info = [test_group_1 , test_group_2 ]
751+ new_group_info = [test_group_1 ]
752+
753+ def get_group_members (group_id ):
754+ if group_id == test_group_1 :
755+ return [test_member_a , test_member_r ]
756+ elif group_id == test_group_2 :
757+ return [test_member_b , test_member_r ]
758+ return []
759+
760+ mock_get_group_members .side_effect = get_group_members
761+
762+ room_id = self ._create_managed_room (name = "Test Room" , groups = old_group_info )
763+ self ._test_get_membership (
764+ room_id ,
765+ [test_member_a , test_member_b , test_member_r ],
766+ expect_code = 200 ,
767+ )
768+ room_account_data = self .get_success (
769+ self .store .get_account_data_for_room (self .creator , room_id )
770+ )
771+ assert room_account_data == {
772+ MANAGED_ROOM_TYPE : {"groups" : old_group_info }
773+ }, room_account_data
774+
775+ # Now update the group information
776+ channel = self .make_request (
777+ method = "POST" ,
778+ path = self .BASE_PATH + f"/{ room_id } /groups" ,
779+ content = {"groups" : new_group_info },
780+ access_token = self .creator_access_token ,
781+ shorthand = False ,
782+ )
783+ assert channel .code == HTTPStatus .OK , channel .result
784+
785+ member_should_be_in_room = [test_member_a , test_member_r ]
786+ member_should_not_be_in_room = [test_member_b ]
787+
788+ self .assert_join_for_users (room_id , member_should_be_in_room )
789+ self .assert_leave_for_users (room_id , member_should_not_be_in_room )
790+
766791 def test_prevent_room_creator_membership_change (
767792 self , mock_get_group_members
768793 ) -> None :
@@ -933,17 +958,9 @@ def update_room_membership_side_effect(
933958
934959 # Since both members failed to be removed, they should still be in the room
935960 # and the new member should be joined to the room
936- for member in [test_member_1 , test_member_2 , test_member_3 ]:
937- path = f"/_matrix/client/v3/rooms/{ room_id } /state/m.room.member/{ member } "
938- channel = self .make_request (
939- "GET" , path , access_token = self .creator_access_token
940- )
941- assert (
942- channel .code == HTTPStatus .OK
943- ), f"Expected 200 but got { channel .code } for member { member } "
944- assert (
945- channel .json_body ["membership" ] == "join"
946- ), f"Expected membership to be join but got { channel .json_body ['membership' ]} for member { member } "
961+ self .assert_join_for_users (
962+ room_id , [test_member_1 , test_member_2 , test_member_3 ]
963+ )
947964
948965 # Check both metrics are incremented by 1 each
949966 new_value_unknown = famedly_control_user_sync_error .labels (
0 commit comments