diff --git a/tests/model/test_model.py b/tests/model/test_model.py index 45886dfa29..e1074d9b38 100644 --- a/tests/model/test_model.py +++ b/tests/model/test_model.py @@ -237,6 +237,7 @@ def test_register_initial_desired_events(self, mocker, initial_data): "update_display_settings", "user_settings", "realm_emoji", + "realm_user", ] fetch_event_types = [ "realm", @@ -3346,6 +3347,48 @@ def test__handle_subscription_event_subscribers_one_user_multiple_streams( new_subscribers = model.stream_dict[stream_id]["subscribers"] assert new_subscribers == expected_subscribers + @pytest.mark.parametrize( + "person, changed_details", + [ + ( + {"full_name": "New Full Name"}, + "full_name", + ), + ({"timezone": "New Timezone"}, "timezone"), + ({"is_billing_admin": False}, "is_billing_admin"), + ({"role": 10}, "role"), + ( + {"avatar_url": "new_avatar_url", "avatar_version": 21}, + "avatar_url", + ), + ({"new_email": "new_display@email.com"}, "email"), + ( + {"delivery_email": "new_delivery@email.com"}, + "delivery_email", + ), + ], + ids=[ + "full_name", + "timezone", + "billing_admin_role", + "role", + "avatar", + "display_email", + "delivery_email", + ], + ) + def test__handle_realm_user_event( + self, person, changed_details, model, initial_data + ): + # For testing purposes, initial_data["realm_users"][1] from the initial_data fixture is used here. + person["user_id"] = 11 + event = {"type": "realm_user", "op": "update", "id": 1000, "person": person} + model._handle_realm_user_event(event) + assert ( + initial_data["realm_users"][1][changed_details] + == event["person"][changed_details] + ) + @pytest.mark.parametrize("value", [True, False]) def test__handle_user_settings_event(self, mocker, model, value): setting = "send_private_typing_notifications" diff --git a/zulipterminal/api_types.py b/zulipterminal/api_types.py index e7b3c15e8d..ab445da787 100644 --- a/zulipterminal/api_types.py +++ b/zulipterminal/api_types.py @@ -167,6 +167,37 @@ class ReactionEvent(TypedDict): message_id: int +class RealmUserEventPerson(TypedDict, total=False): + user_id: int + + full_name: str + + avatar_url: str + avatar_source: str + avatar_url_medium: str + avatar_version: int + + # NOTE: This field will be removed in future as it is redundant with the user_id + # email: str + timezone: str + + role: int + + email: str + + new_email: str + + delivery_email: str + + is_billing_admin: bool + + +class RealmUserEvent(TypedDict): + type: Literal["realm_user"] + op: Literal["update"] + person: RealmUserEventPerson + + class SubscriptionEvent(TypedDict): type: Literal["subscription"] op: str @@ -249,4 +280,5 @@ class UpdateGlobalNotificationsEvent(TypedDict): UpdateRealmEmojiEvent, UpdateUserSettingsEvent, UpdateGlobalNotificationsEvent, + RealmUserEvent, ] diff --git a/zulipterminal/model.py b/zulipterminal/model.py index 508c3ccc16..5c08b76b21 100644 --- a/zulipterminal/model.py +++ b/zulipterminal/model.py @@ -154,6 +154,7 @@ def __init__(self, controller: Any) -> None: ("update_display_settings", self._handle_update_display_settings_event), ("user_settings", self._handle_user_settings_event), ("realm_emoji", self._handle_update_emoji_event), + ("realm_user", self._handle_realm_user_event), ] ) @@ -1830,6 +1831,27 @@ def _handle_update_display_settings_event(self, event: Event) -> None: view.message_view.log[msg_pos] = msg_w_list[0] self.controller.update_screen() + def _handle_realm_user_event(self, event: Event) -> None: + """ + Handle change to user(s) metadata (Eg: full_name, timezone, etc.) + """ + assert event["type"] == "realm_user" + if event["op"] == "update": + # realm_users has 'email' attribute and not 'new_email' + if "new_email" in event["person"]: + event["person"]["email"] = event["person"].pop("new_email") + updated_details = event["person"] + # Role is not present under self.initial_data, + # but exists only under self.initial_data["realm_users"] + if "role" not in event["person"]: + # check if the event contains details of current user or some other user in the org + if updated_details["user_id"] == self.user_id: + self.initial_data.update(updated_details) + for realm_user in self.initial_data["realm_users"]: + if realm_user["user_id"] == updated_details["user_id"]: + realm_user.update(updated_details) + break + def _register_desired_events(self, *, fetch_data: bool = False) -> str: fetch_types = None if not fetch_data else self.initial_data_to_fetch event_types = list(self.event_actions)