Skip to content

Commit 5fde88b

Browse files
committed
button/views/core: Support opening external links in browser.
This commit uses the open_in_browser() function (previously view_in_browser()) to handle opening all external links as well as internal media links in the browser. Now, pressing ENTER on any MsgLinkButton will: - Open the link in the browser, if the link is an external link or an internal media link. - Narrow to the message in ZT, if the link is an internal link. i.e. near_message_url. Tests amended.
1 parent 4c168f0 commit 5fde88b

File tree

6 files changed

+27
-24
lines changed

6 files changed

+27
-24
lines changed

tests/core/test_core.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -272,25 +272,23 @@ def test_narrow_to_all_mentions(
272272
msg_ids = {widget.original_widget.message['id'] for widget in widgets}
273273
assert msg_ids == id_list
274274

275-
@pytest.mark.parametrize('server_url', [
276-
'https://chat.zulip.org/',
277-
'https://foo.zulipchat.com/',
275+
@pytest.mark.parametrize('url', [
276+
'https://chat.zulip.org/#narrow/stream/test',
277+
'https://chat.zulip.org/user_uploads/abcd/efg.png',
278+
'https://github.com/',
278279
])
279-
def test_view_in_browser(self, mocker, controller, message_fixture,
280-
server_url):
280+
def test_open_in_browser(self, mocker, controller, message_fixture, url):
281281
# Set DISPLAY environ to be able to run test in CI
282282
os.environ['DISPLAY'] = ':0'
283-
controller.model.server_url = server_url
284-
message_id = message_fixture['id']
283+
285284
mocked_get = mocker.patch(CORE + '.webbrowser.get')
286285
mocked_open = mocker.patch(CORE + '.webbrowser.open')
287286

288-
controller.view_in_browser(message_fixture)
289-
url = mocked_open.call_args[0][0]
287+
controller.open_in_browser(url)
288+
called_url = mocked_open.call_args[0][0]
290289

291290
assert mocked_open.call_count == 1
292-
assert url.startswith(controller.model.server_url)
293-
assert url.endswith('/{}'.format(message_id))
291+
assert called_url == url
294292

295293
def test_main(self, mocker, controller):
296294
controller.view.palette = {

tests/ui_tools/test_buttons.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,19 +369,21 @@ def test_update_widget(self, mocker, caption, expected_cursor_position,
369369
@pytest.mark.parametrize([
370370
'link',
371371
'handle_narrow_link_called',
372+
'open_in_browser_called',
372373
],
373374
[
374-
(SERVER_URL + '/#narrow/stream/1-Stream-1', True),
375-
(SERVER_URL + '/user_uploads/some/path/image.png', False),
376-
('https://foo.com', False),
375+
(SERVER_URL + '/#narrow/stream/1-Stream-1', True, False),
376+
(SERVER_URL + '/user_uploads/some/path/image.png', False, True),
377+
('https://foo.com', False, True),
377378
],
378379
ids=[
379380
'internal_narrow_link',
380381
'internal_media_link',
381382
'external_link',
382383
]
383384
)
384-
def test_handle_link(self, mocker, link, handle_narrow_link_called):
385+
def test_handle_link(self, mocker, link, handle_narrow_link_called,
386+
open_in_browser_called):
385387
self.controller.model.server_url = SERVER_URL
386388
self.handle_narrow_link = (
387389
mocker.patch(BUTTONS + '.MessageLinkButton.handle_narrow_link')
@@ -391,6 +393,7 @@ def test_handle_link(self, mocker, link, handle_narrow_link_called):
391393
mocked_button.handle_link()
392394

393395
assert self.handle_narrow_link.called == handle_narrow_link_called
396+
assert self.controller.open_in_browser.called == open_in_browser_called
394397

395398
@pytest.mark.parametrize('stream_data, expected_response', [
396399
('206-zulip-terminal', dict(stream_id=206, stream_name=None)),

tests/ui_tools/test_popups.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,14 +516,15 @@ def test_keypress_exit_popup(self, key, widget_size):
516516
assert self.controller.exit_popup.called
517517

518518
@pytest.mark.parametrize('key', keys_for_command('VIEW_IN_BROWSER'))
519-
def test_keypress_view_in_browser(self, widget_size,
519+
def test_keypress_view_in_browser(self, mocker, widget_size,
520520
message_fixture, key):
521521
size = widget_size(self.msg_info_view)
522+
self.msg_info_view.server_url = 'https://chat.zulip.org/'
523+
mocker.patch(VIEWS + '.near_message_url')
522524

523525
self.msg_info_view.keypress(size, key)
524526

525-
(self.controller.view_in_browser.
526-
assert_called_once_with(message_fixture))
527+
assert self.controller.open_in_browser.called
527528

528529
def test_height_noreactions(self):
529530
expected_height = 4

zulipterminal/core.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from zulipterminal.config.themes import ThemeSpec
1818
from zulipterminal.helper import LINUX, asynch, suppress_output
1919
from zulipterminal.model import Model
20-
from zulipterminal.server_url import near_message_url
2120
from zulipterminal.ui import Screen, View
2221
from zulipterminal.ui_tools.utils import create_msg_box_list
2322
from zulipterminal.ui_tools.views import (
@@ -255,10 +254,7 @@ def show_edit_history(
255254
'area:msg'
256255
)
257256

258-
def view_in_browser(self, message: Message) -> None:
259-
# Truncate extra '/' from the server url.
260-
url = near_message_url(self.model.server_url[:-1], message)
261-
257+
def open_in_browser(self, url: str) -> None:
262258
# Don't try to open web browser if running without a GUI
263259
if (LINUX and not os.environ.get('DISPLAY')
264260
and os.environ.get('TERM')):

zulipterminal/ui_tools/buttons.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ def handle_link(self, *_: Any) -> None:
341341
server_url = self.model.server_url
342342
if self.link.startswith(urljoin(server_url, '/#narrow/')):
343343
self.handle_narrow_link()
344+
else:
345+
self.controller.open_in_browser(self.link)
344346

345347
@staticmethod
346348
def _decode_stream_data(encoded_stream_data: str) -> DecodedStream:

zulipterminal/ui_tools/views.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
match_stream,
3030
match_user,
3131
)
32+
from zulipterminal.server_url import near_message_url
3233
from zulipterminal.ui_tools.boxes import MessageBox, PanelSearchBox
3334
from zulipterminal.ui_tools.buttons import (
3435
HomeButton,
@@ -1227,6 +1228,7 @@ def __init__(self, controller: Any, msg: Message, title: str,
12271228
self.topic_links = topic_links
12281229
self.message_links = message_links
12291230
self.time_mentions = time_mentions
1231+
self.server_url = controller.model.server_url
12301232
date_and_time = controller.model.formatted_local_time(
12311233
msg['timestamp'], show_seconds=True, show_year=True
12321234
)
@@ -1351,7 +1353,8 @@ def keypress(self, size: urwid_Size, key: str) -> str:
13511353
time_mentions=self.time_mentions,
13521354
)
13531355
elif is_command_key('VIEW_IN_BROWSER', key):
1354-
self.controller.view_in_browser(self.msg)
1356+
url = near_message_url(self.server_url[:-1], self.msg)
1357+
self.controller.open_in_browser(url)
13551358
return super().keypress(size, key)
13561359

13571360

0 commit comments

Comments
 (0)