diff --git a/rtv/config.py b/rtv/config.py index 702e11e..a679128 100644 --- a/rtv/config.py +++ b/rtv/config.py @@ -17,7 +17,7 @@ PACKAGE = os.path.dirname(__file__) HOME = os.path.expanduser('~') TEMPLATE = os.path.join(PACKAGE, 'templates') DEFAULT_CONFIG = os.path.join(TEMPLATE, 'rtv.cfg') -DEFAULT_MAILCAP = os.path.join(TEMPLATE 'mailcap') +DEFAULT_MAILCAP = os.path.join(TEMPLATE, 'mailcap') XDG_HOME = os.getenv('XDG_CONFIG_HOME', os.path.join(HOME, '.config')) CONFIG = os.path.join(XDG_HOME, 'rtv', 'rtv.cfg') MAILCAP = os.path.join(XDG_HOME, '.mailcap') diff --git a/tests/test_config.py b/tests/test_config.py index a934fc2..6cda44a 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -69,7 +69,8 @@ def test_config_get_args(): '--monochrome', '--non-persistent', '--clear-auth', - '--copy-config',] + '--copy-config', + '--enable-media'] with mock.patch('sys.argv', ['rtv']): config_dict = Config.get_args() @@ -90,6 +91,7 @@ def test_config_get_args(): assert config['link'] == 'https://reddit.com/permalink •' assert config['config'] == 'configfile.cfg' assert config['copy_config'] is True + assert config['enable_media'] is True def test_config_from_file(): @@ -102,7 +104,8 @@ def test_config_from_file(): 'clear_auth': True, 'log': 'logfile.log', 'link': 'https://reddit.com/permalink •', - 'subreddit': 'cfb'} + 'subreddit': 'cfb', + 'enable_media': True} bindings = { 'REFRESH': 'r, ', diff --git a/tests/test_submission.py b/tests/test_submission.py index bd62e81..d66b8ca 100644 --- a/tests/test_submission.py +++ b/tests/test_submission.py @@ -264,20 +264,19 @@ def test_submission_urlview(submission_page, terminal, refresh_token): submission_page.config.refresh_token = refresh_token submission_page.oauth.authorize() - # Positive Case + # Submission case data = submission_page.content.get(submission_page.nav.absolute_index) - data['body'] = 'test comment body' + data['body'] = 'test comment body ❤' with mock.patch.object(terminal, 'open_urlview') as open_urlview, \ - mock.patch('subprocess.Popen'): submission_page.controller.trigger('b') - open_urlview.assert_called_with('test comment body') + open_urlview.assert_called_with('test comment body ❤') - # Negative Case + # Subreddit case data = submission_page.content.get(submission_page.nav.absolute_index) data['text'] = '' data['body'] = '' - data['url_full'] = 'http://test.url.com' + data['url_full'] = 'http://test.url.com ❤' with mock.patch.object(terminal, 'open_urlview') as open_urlview, \ mock.patch('subprocess.Popen'): submission_page.controller.trigger('b') - open_urlview.assert_called_with('http://test.url.com') + open_urlview.assert_called_with('http://test.url.com ❤') diff --git a/tests/test_subreddit.py b/tests/test_subreddit.py index 4165ff4..e0c5665 100644 --- a/tests/test_subreddit.py +++ b/tests/test_subreddit.py @@ -101,11 +101,11 @@ def test_subreddit_open(subreddit_page, terminal, config): config.history.add.assert_called_with(data['url_full']) # Open the selected link externally - with mock.patch.object(terminal, 'open_browser'), \ + with mock.patch.object(terminal, 'open_link'), \ mock.patch.object(config.history, 'add'): data['url_type'] = 'external' subreddit_page.controller.trigger('o') - assert terminal.open_browser.called + assert terminal.open_link.called config.history.add.assert_called_with(data['url_full']) # Open the selected link within rtv diff --git a/tests/test_terminal.py b/tests/test_terminal.py index e5e5b40..827eb4a 100644 --- a/tests/test_terminal.py +++ b/tests/test_terminal.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import re import os import curses import codecs @@ -10,7 +11,7 @@ import pytest from rtv.docs import HELP, COMMENT_EDIT_FILE from rtv.objects import Color -from rtv.exceptions import TemporaryFileError +from rtv.exceptions import TemporaryFileError, MailcapEntryNotFound try: from unittest import mock @@ -181,6 +182,13 @@ def test_show_notification(terminal, stdscr, use_ascii): terminal.config['ascii'] = use_ascii + # Multi-line messages should be automatically split + text = 'line 1\nline 2\nline3' + terminal.show_notification(text) + assert stdscr.subwin.nlines == 5 + assert stdscr.subwin.addstr.call_count == len(text) + stdscr.reset_mock() + # The whole message should fit in 40x80 text = HELP.strip().splitlines() terminal.show_notification(text) @@ -341,6 +349,107 @@ def test_open_editor_error(terminal): os.remove(data['filename']) +def test_open_link_mailcap(terminal): + + url = 'http://www.test.com' + + class MockMimeParser(object): + pattern = re.compile('') + + mock_mime_parser = MockMimeParser() + + with mock.patch.object(terminal, 'open_browser'), \ + mock.patch('rtv.terminal.mime_parsers') as mime_parsers: + mime_parsers.parsers = [mock_mime_parser] + + # Pass through to open_browser if media is disabled + terminal.config['enable_media'] = False + terminal.open_link(url) + assert terminal.open_browser.called + terminal.open_browser.reset_mock() + + # Invalid content type + terminal.config['enable_media'] = True + mock_mime_parser.get_mimetype = lambda url: (url, None) + terminal.open_link(url) + assert terminal.open_browser.called + terminal.open_browser.reset_mock() + + # Text/html defers to open_browser + mock_mime_parser.get_mimetype = lambda url: (url, 'text/html') + terminal.open_link(url) + assert terminal.open_browser.called + terminal.open_browser.reset_mock() + + +def test_open_link_subprocess(terminal): + + url = 'http://www.test.com' + addstr = terminal.stdscr.subwin.addstr + + error_status = 'Program exited with status'.encode('utf-8') + + with mock.patch('time.sleep'), \ + mock.patch('os.system'), \ + mock.patch('six.moves.input') as six_input, \ + mock.patch.object(terminal, 'get_mailcap_entry'): + + six_input.return_values = 'y' + + def reset_mock(): + six_input.reset_mock() + os.system.reset_mock() + addstr.reset_mock() + + # Non-blocking success + reset_mock() + entry = ('echo ""', 'echo %s') + terminal.get_mailcap_entry.return_value = entry + terminal.open_link(url) + assert not six_input.called + assert error_status not in addstr.call_args[0][2] + + # Non-blocking failure + reset_mock() + entry = ('fake .', 'fake %s') + terminal.get_mailcap_entry.return_value = entry + terminal.open_link(url) + assert not six_input.called + assert error_status in addstr.call_args[0][2] + + # needsterminal success + reset_mock() + entry = ('echo ""', 'echo %s; needsterminal') + terminal.get_mailcap_entry.return_value = entry + terminal.open_link(url) + assert not six_input.called + assert not addstr.called + + # needsterminal failure + reset_mock() + entry = ('fake .', 'fake %s; needsterminal') + terminal.get_mailcap_entry.return_value = entry + terminal.open_link(url) + assert not six_input.called + assert error_status in addstr.call_args[0][2] + + # copiousoutput success + reset_mock() + entry = ('echo ""', 'echo %s; needsterminal; copiousoutput') + terminal.get_mailcap_entry.return_value = entry + terminal.open_link(url) + assert six_input.called + assert not addstr.called + + # copiousoutput failure + reset_mock() + entry = ('fake .', 'fake %s; needsterminal; copiousoutput') + terminal.get_mailcap_entry.return_value = entry + terminal.open_link(url) + assert six_input.called + assert error_status in addstr.call_args[0][2] + + def test_open_browser(terminal): url = 'http://www.test.com' @@ -363,7 +472,7 @@ def test_open_browser(terminal): def test_open_pager(terminal, stdscr): - data = "Hello World!" + data = "Hello World! ❤" def side_effect(args, stdin=None): assert stdin is not None @@ -381,4 +490,4 @@ def test_open_pager(terminal, stdscr): Popen.side_effect = side_effect terminal.open_pager(data) message = 'Could not open pager fake'.encode('ascii') - assert stdscr.addstr.called_with(0, 0, message) \ No newline at end of file + assert stdscr.addstr.called_with(0, 0, message)