Skip to content

Commit 8689d12

Browse files
rsashankneiljp
authored andcommitted
api_types/model: Fetch stream email address from endpoint if required.
Updated method to retrieve the stream email address from stream_dict, fetching from a new endpoint introduced in ZFL 226 if not available in the dict (ensuring compatibility across server versions). Introduced a new method to call the endpoint for fetching the email address. Added tests. Updated api_types.
1 parent 005402a commit 8689d12

File tree

3 files changed

+70
-7
lines changed

3 files changed

+70
-7
lines changed

tests/model/test_model.py

+53-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import pytest
88
from pytest import param as case
9+
from pytest_mock import MockerFixture
910
from zulip import Client, ZulipError
1011

1112
from zulipterminal.config.symbols import STREAM_TOPIC_SEPARATOR
@@ -564,25 +565,73 @@ def test_topics_in_stream(self, mocker, model, topics_index, fetched, stream_id=
564565
assert model.index["topics"][stream_id] is not return_value
565566

566567
@pytest.mark.parametrize(
567-
"email_address_stream_dict, expected_return_value",
568+
"response, expected_return_value",
568569
[
569-
({"email_address": "[email protected]"}, "[email protected]"),
570-
({}, None),
570+
(
571+
{"result": "success", "msg": "", "email": "[email protected]"},
572+
573+
),
574+
(
575+
{"result": "error", "msg": "Invalid stream ID", "code": "BAD_REQUEST"},
576+
None,
577+
),
578+
],
579+
ids=["valid_email_returned", "no_email_returned"],
580+
)
581+
def test__fetch_stream_email_from_endpoint(
582+
self,
583+
mocker: MockerFixture,
584+
model: Any,
585+
response: Dict[str, str],
586+
expected_return_value: Optional[str],
587+
stream_id: int = 1,
588+
) -> None:
589+
self.client.call_endpoint = mocker.Mock(return_value=response)
590+
591+
result = model._fetch_stream_email_from_endpoint(stream_id)
592+
593+
self.client.call_endpoint.assert_called_once_with(
594+
f"/streams/{stream_id}/email_address", method="GET"
595+
)
596+
assert result == expected_return_value
597+
598+
@pytest.mark.parametrize(
599+
"email_address_stream_dict, email_fetch_response, "
600+
"expected_fetched, expected_return_value",
601+
[
602+
(
603+
{"email_address": "[email protected]"},
604+
None,
605+
False,
606+
607+
),
608+
609+
({}, None, True, None),
571610
],
572611
ids=[
573612
"email_present_in_dict:ZFL<226",
574-
"email_absent_from_dict:ZFL>=226",
613+
"email_absent_from_dict_and_fetched_ok:ZFL>=226",
614+
"email_absent_from_dict_and_fetch_failed:ZFL>=226",
575615
],
576616
)
577617
def test_get_stream_email_address(
578618
self,
619+
mocker: MockerFixture,
579620
model: Any,
580621
email_address_stream_dict: Dict[str, str],
622+
email_fetch_response: Optional[str],
623+
expected_fetched: bool,
581624
expected_return_value: Optional[str],
582625
stream_id: int = 1,
583626
) -> None:
584627
model.stream_dict[stream_id] = email_address_stream_dict
628+
model._fetch_stream_email_from_endpoint = mocker.Mock(
629+
return_value=email_fetch_response
630+
)
631+
585632
result = model.get_stream_email_address(stream_id)
633+
634+
assert model._fetch_stream_email_from_endpoint.called == expected_fetched
586635
assert result == expected_return_value
587636

588637
# pre server v3 provide user_id or id as a property within user key

zulipterminal/api_types.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ class Subscription(TypedDict):
237237
push_notifications: Optional[bool]
238238
audible_notifications: Optional[bool]
239239
pin_to_top: bool
240-
email_address: str
240+
email_address: NotRequired[str] # Replaced by new endpoint in Zulip 7.5 (ZFL 226)
241241

242242
is_muted: bool
243243

zulipterminal/model.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -906,16 +906,30 @@ def topics_in_stream(self, stream_id: int) -> List[str]:
906906

907907
return list(self.index["topics"][stream_id])
908908

909+
def _fetch_stream_email_from_endpoint(self, stream_id: int) -> Optional[str]:
910+
"""
911+
Endpoint added in Zulip 7.5 (ZFL 226)
912+
"""
913+
url = f"/streams/{stream_id}/email_address"
914+
915+
response = self.client.call_endpoint(url, method="GET")
916+
917+
if response.get("result") == "success":
918+
email_address = response.get("email", "")
919+
return str(email_address)
920+
return None
921+
909922
def get_stream_email_address(self, stream_id: int) -> Optional[str]:
910923
"""
911924
Returns the stream email address, or None if it is unavailable.
925+
Beyond Zulip 7.5 / ZFL226, this requires a call to the server.
912926
"""
913927
if stream_id not in self.stream_dict:
914928
raise RuntimeError("Invalid stream id.")
915929
stream = self.stream_dict[stream_id]
916-
# FIXME: This field was removed from the subscription data in Zulip 7.5 / ZFL226
917-
# We should use the new /streams/{stream_id}/email_address endpoint instead
918930
stream_email = stream.get("email_address", None)
931+
if stream_email is None:
932+
stream_email = self._fetch_stream_email_from_endpoint(stream_id)
919933
return stream_email
920934

921935
@staticmethod

0 commit comments

Comments
 (0)