Skip to content

Commit

Permalink
views: Update user info popup to display custom profile fields.
Browse files Browse the repository at this point in the history
This commit updates the user information popup to display the custom
profile fields stored in the model, including processing additional data
received from the model in _fetch_user_data.

All fields except the Person picker field are strings, so if a Person
picker field is present, it is converted to a string of usernames
separate by commas.

Tests added and updated.

Fixes #1338.
  • Loading branch information
theViz343 authored and neiljp committed Jul 14, 2023
1 parent bad0c71 commit 3081df9
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 9 deletions.
70 changes: 65 additions & 5 deletions tests/ui_tools/test_popups.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from zulipterminal.api_types import Message
from zulipterminal.config.keys import is_command_key, keys_for_command
from zulipterminal.config.ui_mappings import EDIT_MODE_CAPTIONS
from zulipterminal.helper import TidiedUserInfo
from zulipterminal.helper import CustomProfileData, TidiedUserInfo
from zulipterminal.ui_tools.messages import MessageBox
from zulipterminal.ui_tools.views import (
AboutView,
Expand Down Expand Up @@ -271,6 +271,15 @@ def mock_external_classes(
return_value="Tue Mar 13 10:55 AM",
)

mocked_user_name_from_id = {
11: "Human 1",
12: "Human 2",
13: "Human 3",
}
self.controller.model.user_name_from_id = mocker.Mock(
side_effect=lambda param: mocked_user_name_from_id.get(param, "(No name)")
)

self.user_info_view = UserInfoView(
self.controller, 10000, "User Info (up/down scrolls)", "USER_INFO"
)
Expand Down Expand Up @@ -334,26 +343,77 @@ def mock_external_classes(
)
def test__fetch_user_data(
self,
mocker: MockerFixture,
to_vary_in_each_user: Dict[str, Any],
expected_key: str,
expected_value: Optional[str],
) -> None:
data = dict(self.user_data, **to_vary_in_each_user)

mocker.patch.object(self.controller.model, "get_user_info", return_value=data)
self.controller.model.get_user_info.return_value = data

display_data = self.user_info_view._fetch_user_data(self.controller, 1)
display_data, custom_profile_data = self.user_info_view._fetch_user_data(
self.controller, 1
)

assert display_data.get(expected_key, None) == expected_value

@pytest.mark.parametrize(
[
"to_vary_in_each_user",
"expected_value",
],
[
case(
[],
{},
id="user_has_no_custom_profile_data",
),
case(
[
{
"label": "Biography",
"value": "Simplicity",
"type": 2,
"order": 2,
},
{
"label": "Mentor",
"value": [11, 12],
"type": 6,
"order": 7,
},
],
{"Biography": "Simplicity", "Mentor": "Human 1, Human 2"},
id="user_has_custom_profile_data",
),
],
)
def test__fetch_user_data__custom_profile_data(
self,
to_vary_in_each_user: List[CustomProfileData],
expected_value: Dict[str, str],
) -> None:
data = dict(self.user_data)
data["custom_profile_data"] = to_vary_in_each_user

self.controller.model.get_user_info.return_value = data

display_data, custom_profile_data = self.user_info_view._fetch_user_data(
self.controller, 1
)

assert custom_profile_data == expected_value

def test__fetch_user_data_USER_NOT_FOUND(self, mocker: MockerFixture) -> None:
mocker.patch.object(self.controller.model, "get_user_info", return_value=dict())

display_data = self.user_info_view._fetch_user_data(self.controller, 1)
display_data, custom_profile_data = self.user_info_view._fetch_user_data(
self.controller, 1
)

assert display_data["Name"] == "(Unavailable)"
assert display_data["Error"] == "User data not found"
assert custom_profile_data == {}

@pytest.mark.parametrize(
"key", {*keys_for_command("GO_BACK"), *keys_for_command("USER_INFO")}
Expand Down
34 changes: 30 additions & 4 deletions zulipterminal/ui_tools/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1084,13 +1084,20 @@ def __init__(

class UserInfoView(PopUpView):
def __init__(self, controller: Any, user_id: int, title: str, command: str) -> None:
display_data = self._fetch_user_data(controller, user_id)
display_data, display_custom_profile_data = self._fetch_user_data(
controller, user_id
)

user_details = [
(key, value) for key, value in display_data.items() if key != "Name"
]
user_view_content = [(display_data["Name"], user_details)]

if display_custom_profile_data:
user_view_content.extend(
[("Additional Details", list(display_custom_profile_data.items()))]
)

popup_width, column_widths = self.calculate_table_widths(
user_view_content, len(title)
)
Expand All @@ -1099,16 +1106,19 @@ def __init__(self, controller: Any, user_id: int, title: str, command: str) -> N
super().__init__(controller, widgets, command, popup_width, title)

@staticmethod
def _fetch_user_data(controller: Any, user_id: int) -> Dict[str, Any]:
def _fetch_user_data(
controller: Any, user_id: int
) -> Tuple[Dict[str, str], Dict[str, str]]:
# Get user data from model
data: TidiedUserInfo = controller.model.get_user_info(user_id)

display_custom_profile_data = {}
if not data:
display_data = {
"Name": "(Unavailable)",
"Error": "User data not found",
}
return display_data
return (display_data, display_custom_profile_data)

# Style the data obtained to make it displayable
display_data = {"Name": data["full_name"]}
Expand Down Expand Up @@ -1144,7 +1154,23 @@ def _fetch_user_data(controller: Any, user_id: int) -> Dict[str, Any]:
if data["last_active"]:
display_data["Last active"] = data["last_active"]

return display_data
# This will be an empty dict in case of bot users
custom_profile_data = data["custom_profile_data"]

if custom_profile_data:
for field in custom_profile_data:
if field["type"] == 6: # Person picker
user_names = [
controller.model.user_name_from_id(user)
for user in field["value"]
]
field["value"] = ", ".join(user_names)
# After conversion of field type 6, all values are str
assert isinstance(field["value"], str)

display_custom_profile_data[field["label"]] = field["value"]

return (display_data, display_custom_profile_data)


class HelpView(PopUpView):
Expand Down

0 comments on commit 3081df9

Please sign in to comment.