Skip to content

Commit

Permalink
buttons: Support near stream and near topic narrow in MessageLinkButton.
Browse files Browse the repository at this point in the history
This extends the existing helper methods, _parse_narrow_link(),
_validate_narrow_link() and _switch_narrow_to(), and adds
_decode_message_id() to add support for near stream and near topic
narrow.

The near operator is used to set focus to a particular message (using
the anchor) while switching narrow.

Tests amended.
  • Loading branch information
preetmishra committed Aug 21, 2020
1 parent 989a0d7 commit caefdf6
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
64 changes: 64 additions & 0 deletions tests/ui_tools/test_buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ def test__decode_stream_data(self, stream_data, expected_response):

assert return_value == expected_response

@pytest.mark.parametrize('message_id, expected_return_value', [
('1', 1),
('foo', None),
])
def test__decode_message_id(self, message_id, expected_return_value):
return_value = MessageLinkButton._decode_message_id(message_id)

assert return_value == expected_return_value

@pytest.mark.parametrize('link, expected_parsed_link', [
(SERVER_URL + '/#narrow/stream/1-Stream-1',
{'narrow': 'stream',
Expand All @@ -106,20 +115,34 @@ def test__decode_stream_data(self, stream_data, expected_response):
(SERVER_URL + '/#narrow/stream/1-Stream-1/topic/foo.20bar',
{'narrow': 'stream:topic', 'topic_name': 'foo bar',
'stream': {'stream_id': 1, 'stream_name': None}}),
(SERVER_URL + '/#narrow/stream/1-Stream-1/near/1',
{'narrow': 'stream:near', 'message_id': 1,
'stream': {'stream_id': 1, 'stream_name': None}}),
(SERVER_URL + '/#narrow/stream/1-Stream-1/topic/foo/near/1',
{'narrow': 'stream:topic:near', 'topic_name': 'foo', 'message_id': 1,
'stream': {'stream_id': 1, 'stream_name': None}}),
(SERVER_URL + '/#narrow/foo',
{}),
(SERVER_URL + '/#narrow/stream/',
{}),
(SERVER_URL + '/#narrow/stream/1-Stream-1/topic/',
{}),
(SERVER_URL + '/#narrow/stream/1-Stream-1//near/',
{}),
(SERVER_URL + '/#narrow/stream/1-Stream-1/topic/foo/near/',
{}),
],
ids=[
'modern_stream_narrow_link',
'deprecated_stream_narrow_link',
'topic_narrow_link',
'stream_near_narrow_link',
'topic_near_narrow_link',
'invalid_narrow_link_1',
'invalid_narrow_link_2',
'invalid_narrow_link_3',
'invalid_narrow_link_4',
'invalid_narrow_link_5',
]
)
def test__parse_narrow_link(self, link, expected_parsed_link):
Expand Down Expand Up @@ -172,6 +195,32 @@ def test__parse_narrow_link(self, link, expected_parsed_link):
None,
[],
'Invalid topic name'),
({'narrow': 'stream:near', 'message_id': 1,
'stream': {'stream_id': 1, 'stream_name': None}},
True,
None,
None,
''),
({'narrow': 'stream:near', 'message_id': None,
'stream': {'stream_id': 1, 'stream_name': None}},
True,
None,
None,
'Invalid message ID'),
({'narrow': 'stream:topic:near', 'topic_name': 'Valid',
'message_id': 1,
'stream': {'stream_id': 1, 'stream_name': None}},
True,
None,
['Valid'],
''),
({'narrow': 'stream:topic:near', 'topic_name': 'Valid',
'message_id': None,
'stream': {'stream_id': 1, 'stream_name': None}},
True,
None,
['Valid'],
'Invalid message ID'),
({},
None,
None,
Expand All @@ -185,6 +234,10 @@ def test__parse_narrow_link(self, link, expected_parsed_link):
'invalid_deprecated_stream_narrow_parsed_link',
'valid_topic_narrow_parsed_link',
'invalid_topic_narrow_parsed_link',
'valid_stream_near_narrow_parsed_link',
'invalid_stream_near_narrow_parsed_link',
'valid_topic_near_narrow_parsed_link',
'invalid_topic_near_narrow_parsed_link',
'invalid_narrow_link',
]
)
Expand Down Expand Up @@ -277,10 +330,21 @@ def test__validate_and_patch_stream_data(self, stream_dict, parsed_link,
'stream': {'stream_id': 1, 'stream_name': 'Stream 1'}},
False,
True),
({'narrow': 'stream:near', 'message_id': 1,
'stream': {'stream_id': 1, 'stream_name': 'Stream 1'}},
True,
False),
({'narrow': 'stream:topic:near', 'topic_name': 'Foo',
'message_id': 1,
'stream': {'stream_id': 1, 'stream_name': 'Stream 1'}},
False,
True),
],
ids=[
'stream_narrow',
'topic_narrow',
'stream_near_narrow',
'topic_near_narrow',
]
)
def test__switch_narrow_to(self, parsed_link, narrow_to_stream_called,
Expand Down
44 changes: 44 additions & 0 deletions zulipterminal/ui_tools/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ def __init__(self, user_id: int, email: str) -> None:
'narrow': str,
'stream': StreamData,
'topic_name': str,
'message_id': Optional[int],
}, total=False)


Expand Down Expand Up @@ -311,6 +312,16 @@ def _decode_stream_data(encoded_stream_data: str) -> StreamData:
stream_name = hash_util_decode(encoded_stream_data)
return StreamData(stream_id=None, stream_name=stream_name)

@staticmethod
def _decode_message_id(message_id: str) -> Optional[int]:
"""
Returns either the compatible near message ID or None.
"""
try:
return int(message_id)
except ValueError:
return None

@classmethod
def _parse_narrow_link(cls, link: str) -> ParsedNarrowLink:
"""
Expand Down Expand Up @@ -341,6 +352,21 @@ def _parse_narrow_link(cls, link: str) -> ParsedNarrowLink:
parsed_link = dict(narrow='stream:topic', stream=stream_data,
topic_name=topic_name)

elif (len_fragments == 5 and fragments[1] == 'stream'
and fragments[3] == 'near'):
stream_data = cls._decode_stream_data(fragments[2])
message_id = cls._decode_message_id(fragments[4])
parsed_link = dict(narrow='stream:near', stream=stream_data,
message_id=message_id)

elif (len_fragments == 7 and fragments[1] == 'stream'
and fragments[3] == 'topic' and fragments[5] == 'near'):
stream_data = cls._decode_stream_data(fragments[2])
topic_name = hash_util_decode(fragments[4])
message_id = cls._decode_message_id(fragments[6])
parsed_link = dict(narrow='stream:topic:near', stream=stream_data,
topic_name=topic_name, message_id=message_id)

return parsed_link

def _validate_and_patch_stream_data(self,
Expand Down Expand Up @@ -396,6 +422,13 @@ def _validate_narrow_link(self, parsed_link: ParsedNarrowLink) -> str:
if topic_name not in self.model.topics_in_stream(stream_id):
return 'Invalid topic name'

# Validate message ID for near.
if 'near' in parsed_link['narrow']:
message_id = parsed_link.get('message_id')

if message_id is None:
return 'Invalid message ID'

return ''

def _switch_narrow_to(self, parsed_link: ParsedNarrowLink) -> None:
Expand All @@ -407,11 +440,22 @@ def _switch_narrow_to(self, parsed_link: ParsedNarrowLink) -> None:
self.stream_id = parsed_link['stream']['stream_id']
self.stream_name = parsed_link['stream']['stream_name']
self.controller.narrow_to_stream(self)
elif 'stream:near' == narrow:
self.stream_id = parsed_link['stream']['stream_id']
self.stream_name = parsed_link['stream']['stream_name']
self.message = dict(id=parsed_link['message_id'])
self.controller.narrow_to_stream(self)
elif 'stream:topic' == narrow:
self.stream_id = parsed_link['stream']['stream_id']
self.stream_name = parsed_link['stream']['stream_name']
self.topic_name = parsed_link['topic_name']
self.controller.narrow_to_topic(self)
elif 'stream:topic:near' == narrow:
self.stream_id = parsed_link['stream']['stream_id']
self.stream_name = parsed_link['stream']['stream_name']
self.topic_name = parsed_link['topic_name']
self.message = dict(id=parsed_link['message_id'])
self.controller.narrow_to_topic(self)

def handle_narrow_link(self) -> None:
"""
Expand Down

0 comments on commit caefdf6

Please sign in to comment.