diff --git a/tests/helper/test_helper.py b/tests/helper/test_helper.py index 3dc7d1fe1ed..586da742e71 100644 --- a/tests/helper/test_helper.py +++ b/tests/helper/test_helper.py @@ -9,6 +9,7 @@ hash_util_decode, index_messages, notify, + notify_if_message_sent_outside_narrow, powerset, ) @@ -309,6 +310,31 @@ def test_display_error_if_present(mocker, response, footer_updated): set_footer_text.assert_not_called() +@pytest.mark.parametrize(['req', 'narrow', 'footer_updated'], [ + ({'type': 'private', 'to': 'foo@gmail.com', 'content': 'bar'}, + [['is', 'private']], False), + ({'type': 'private', 'to': 'bar@chat.zulip.com', 'content': 'foo'}, + [['pm_with', 'foo@chat.zulip.com']], True), + ({'type': 'stream', 'to': 'ZT', 'subject': '1', 'content': 'foo'}, + [['stream', 'ZT'], ['topic', '1']], False), + ({'type': 'stream', 'to': 'here', 'subject': 'pytest', 'content': 'py'}, + [['stream', 'test here']], True) +]) +def test_notify_if_message_sent_outside_narrow(mocker, req, narrow, + footer_updated): + controller = mocker.Mock() + set_footer_text = controller.view.set_footer_text + controller.model.narrow = narrow + + notify_if_message_sent_outside_narrow(req, controller) + + if footer_updated: + set_footer_text.assert_called_once_with( + 'Message is sent outside of current narrow.', 3) + else: + set_footer_text.assert_not_called() + + @pytest.mark.parametrize('quoted_string, expected_unquoted_string', [ ('(no.20topic)', '(no topic)'), ('.3Cstrong.3Exss.3C.2Fstrong.3E', 'xss'), diff --git a/tests/model/test_model.py b/tests/model/test_model.py index 9606205bd5f..7c285955b21 100644 --- a/tests/model/test_model.py +++ b/tests/model/test_model.py @@ -23,6 +23,8 @@ def mock_external_classes(self, mocker: Any) -> None: mocker.patch('zulipterminal.model.Model._start_presence_updates') self.display_error_if_present = mocker.patch( 'zulipterminal.model.display_error_if_present') + self.notify_if_message_sent_outside_narrow = mocker.patch( + 'zulipterminal.model.notify_if_message_sent_outside_narrow') @pytest.fixture def model(self, mocker, initial_data, user_profile, @@ -481,6 +483,9 @@ def test_send_private_message(self, mocker, model, assert result == return_value self.display_error_if_present.assert_called_once_with(response, self.controller) + if result == 'success': + self.notify_if_message_sent_outside_narrow.assert_called_once_with( + req, self.controller) def test_send_private_message_with_no_recipients(self, model, content="hi!", @@ -507,6 +512,10 @@ def test_send_stream_message(self, mocker, model, self.display_error_if_present.assert_called_once_with(response, self.controller) + if result == 'success': + self.notify_if_message_sent_outside_narrow.assert_called_once_with( + req, self.controller) + @pytest.mark.parametrize('response, return_value', [ ({'result': 'success'}, True), ({'result': 'some_failure'}, False), diff --git a/zulipterminal/helper.py b/zulipterminal/helper.py index 0ad98fcadab..802c7ad1bea 100644 --- a/zulipterminal/helper.py +++ b/zulipterminal/helper.py @@ -651,6 +651,28 @@ def display_error_if_present(response: Dict[str, Any], controller: Any controller.view.set_footer_text(response['msg'], 3) +def notify_if_message_sent_outside_narrow(request: Dict[str, Any], + controller: Any) -> None: + current_narrow = controller.model.narrow + + if request['type'] == 'stream': + stream_narrow = [['stream', request['to']]] + topic_narrow = stream_narrow + [['topic', request['subject']]] + + if (current_narrow != stream_narrow + and current_narrow != topic_narrow): + controller.view.set_footer_text( + 'Message is sent outside of current narrow.', 3) + elif request['type'] == 'private': + pm_narrow = [['is', 'private']] + pm_with_narrow = [['pm_with', request['to']]] + + if (current_narrow != pm_narrow + and current_narrow != pm_with_narrow): + controller.view.set_footer_text( + 'Message is sent outside of current narrow.', 3) + + def hash_util_decode(string: str) -> str: """ Returns a decoded string given a hash_util_encode() [present in diff --git a/zulipterminal/model.py b/zulipterminal/model.py index 7cab5cf1bcf..ee78efeeeed 100644 --- a/zulipterminal/model.py +++ b/zulipterminal/model.py @@ -37,6 +37,7 @@ index_messages, initial_index, notify, + notify_if_message_sent_outside_narrow, set_count, ) from zulipterminal.ui_tools.utils import create_msg_box_list @@ -385,6 +386,9 @@ def send_private_message(self, recipients: List[str], } response = self.client.send_message(request) display_error_if_present(response, self.controller) + # FIXME: Is there a better way? + if response['result'] == 'success': + notify_if_message_sent_outside_narrow(request, self.controller) return response['result'] == 'success' else: raise RuntimeError('Empty recipients list.') @@ -399,6 +403,8 @@ def send_stream_message(self, stream: str, topic: str, } response = self.client.send_message(request) display_error_if_present(response, self.controller) + if response['result'] == 'success': + notify_if_message_sent_outside_narrow(request, self.controller) return response['result'] == 'success' def update_private_message(self, msg_id: int, content: str) -> bool: @@ -423,6 +429,13 @@ def update_stream_message(self, topic: str, message_id: int, response = self.client.update_message(request) display_error_if_present(response, self.controller) + if response['result'] == 'success': + old_topic = self.index['messages'][message_id].get('subject', None) + new_topic = request['topic'] + view = self.controller.view + if old_topic != new_topic: + view.set_footer_text('Topic changed', 3) + return response['result'] == 'success' def fetch_custom_emojis(self) -> NamedEmojiData: