diff --git a/.travis.yml b/.travis.yml index afbaa887..a41339cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,6 @@ before_script: # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics # command to run tests -script: pytest --cov=onionshare test/ +script: pytest --cov=onionshare tests/ after_success: - coveralls diff --git a/BUILD.md b/BUILD.md index 1feedf49..00d24cd2 100644 --- a/BUILD.md +++ b/BUILD.md @@ -137,8 +137,30 @@ This will prompt you to codesign three binaries and execute one unsigned binary. ## Tests -OnionShare includes PyTest unit tests. To run the tests: +OnionShare includes PyTest unit tests. To run the tests, first install some dependencies: ```sh -pytest test/ +pip3 install -r install/requirements-tests.txt ``` + +If you'd like to run the CLI-based tests that Travis runs: + +```sh +pytest tests/ +``` + +If you would like to run the GUI unit tests in 'local only mode': + +```sh +cd tests_gui_local/ +./run_unit_tests.sh +``` + +If you would like to run the GUI unit tests in 'tor' (bundled) mode: + +```sh +cd tests_gui_tor/ +./run_unit_tests.sh +``` + +Keep in mind that the Tor tests take a lot longer to run than local mode, but they are also more comprehensive. diff --git a/MANIFEST.in b/MANIFEST.in index c8a4d87c..71af3740 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -10,4 +10,4 @@ include install/onionshare.desktop include install/onionshare.appdata.xml include install/onionshare80.xpm include install/scripts/onionshare-nautilus.py -include test/*.py +include tests/*.py diff --git a/install/check_lacked_trans.py b/install/check_lacked_trans.py index 027edab1..1caa6b27 100644 --- a/install/check_lacked_trans.py +++ b/install/check_lacked_trans.py @@ -59,7 +59,7 @@ def main(): files_in(dir, 'onionshare_gui/share_mode') + \ files_in(dir, 'onionshare_gui/receive_mode') + \ files_in(dir, 'install/scripts') + \ - files_in(dir, 'test') + files_in(dir, 'tests') pysrc = [p for p in src if p.endswith('.py')] lang_code = args.lang_code diff --git a/install/requirements-tests.txt b/install/requirements-tests.txt new file mode 100644 index 00000000..0d9c1581 --- /dev/null +++ b/install/requirements-tests.txt @@ -0,0 +1,11 @@ +atomicwrites==1.2.1 +attrs==18.2.0 +more-itertools==4.3.0 +pluggy==0.6.0 +py==1.6.0 +pytest==3.4.2 +pytest-faulthandler==1.5.0 +pytest-ordering==0.5 +pytest-qt==3.1.0 +six==1.11.0 +urllib3==1.23 diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py index 4c21de76..6b156f7e 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode.py @@ -37,7 +37,7 @@ class Mode(QtWidgets.QWidget): starting_server_error = QtCore.pyqtSignal(str) set_server_active = QtCore.pyqtSignal(bool) - def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None): + def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None, local_only=False): super(Mode, self).__init__() self.common = common self.qtapp = qtapp @@ -54,12 +54,15 @@ class Mode(QtWidgets.QWidget): # The web object gets created in init() self.web = None + # Local mode is passed from OnionShareGui + self.local_only = local_only + # Threads start out as None self.onion_thread = None self.web_thread = None # Server status - self.server_status = ServerStatus(self.common, self.qtapp, self.app) + self.server_status = ServerStatus(self.common, self.qtapp, self.app, None, self.local_only) self.server_status.server_started.connect(self.start_server) self.server_status.server_stopped.connect(self.stop_server) self.server_status.server_canceled.connect(self.cancel_server) diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 8b61a18e..83f3a7e0 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -121,7 +121,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.setStatusBar(self.status_bar) # Share mode - self.share_mode = ShareMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, filenames) + self.share_mode = ShareMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, filenames, self.local_only) self.share_mode.init() self.share_mode.server_status.server_started.connect(self.update_server_status_indicator) self.share_mode.server_status.server_stopped.connect(self.update_server_status_indicator) @@ -135,7 +135,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.share_mode.set_server_active.connect(self.set_server_active) # Receive mode - self.receive_mode = ReceiveMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray) + self.receive_mode = ReceiveMode(self.common, qtapp, app, self.status_bar, self.server_status_label, self.system_tray, None, self.local_only) self.receive_mode.init() self.receive_mode.server_status.server_started.connect(self.update_server_status_indicator) self.receive_mode.server_status.server_stopped.connect(self.update_server_status_indicator) diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py index 9afceb38..32135ca4 100644 --- a/onionshare_gui/server_status.py +++ b/onionshare_gui/server_status.py @@ -44,7 +44,7 @@ class ServerStatus(QtWidgets.QWidget): STATUS_WORKING = 1 STATUS_STARTED = 2 - def __init__(self, common, qtapp, app, file_selection=None): + def __init__(self, common, qtapp, app, file_selection=None, local_only=False): super(ServerStatus, self).__init__() self.common = common @@ -56,17 +56,23 @@ class ServerStatus(QtWidgets.QWidget): self.app = app self.web = None + self.local_only = local_only self.resizeEvent(None) # Shutdown timeout layout self.shutdown_timeout_label = QtWidgets.QLabel(strings._('gui_settings_shutdown_timeout', True)) self.shutdown_timeout = QtWidgets.QDateTimeEdit() - # Set proposed timeout to be 5 minutes into the future self.shutdown_timeout.setDisplayFormat("hh:mm A MMM d, yy") - self.shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300)) - # Onion services can take a little while to start, so reduce the risk of it expiring too soon by setting the minimum to 2 min from now - self.shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(120)) + if self.local_only: + # For testing + self.shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(15)) + self.shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime()) + else: + # Set proposed timeout to be 5 minutes into the future + self.shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300)) + # Onion services can take a little while to start, so reduce the risk of it expiring too soon by setting the minimum to 60s from now + self.shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(60)) self.shutdown_timeout.setCurrentSection(QtWidgets.QDateTimeEdit.MinuteSection) shutdown_timeout_layout = QtWidgets.QHBoxLayout() shutdown_timeout_layout.addWidget(self.shutdown_timeout_label) @@ -154,7 +160,8 @@ class ServerStatus(QtWidgets.QWidget): Reset the timeout in the UI after stopping a share """ self.shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300)) - self.shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(120)) + if not self.local_only: + self.shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(60)) def update(self): """ @@ -255,8 +262,11 @@ class ServerStatus(QtWidgets.QWidget): """ if self.status == self.STATUS_STOPPED: if self.common.settings.get('shutdown_timeout'): - # Get the timeout chosen, stripped of its seconds. This prevents confusion if the share stops at (say) 37 seconds past the minute chosen - self.timeout = self.shutdown_timeout.dateTime().toPyDateTime().replace(second=0, microsecond=0) + if self.local_only: + self.timeout = self.shutdown_timeout.dateTime().toPyDateTime() + else: + # Get the timeout chosen, stripped of its seconds. This prevents confusion if the share stops at (say) 37 seconds past the minute chosen + self.timeout = self.shutdown_timeout.dateTime().toPyDateTime().replace(second=0, microsecond=0) # If the timeout has actually passed already before the user hit Start, refuse to start the server. if QtCore.QDateTime.currentDateTime().toPyDateTime() > self.timeout: Alert(self.common, strings._('gui_server_timeout_expired', QtWidgets.QMessageBox.Warning)) diff --git a/test/__init__.py b/tests/__init__.py similarity index 100% rename from test/__init__.py rename to tests/__init__.py diff --git a/test/conftest.py b/tests/conftest.py similarity index 100% rename from test/conftest.py rename to tests/conftest.py diff --git a/test/test_helpers.py b/tests/test_helpers.py similarity index 100% rename from test/test_helpers.py rename to tests/test_helpers.py diff --git a/test/test_onionshare.py b/tests/test_onionshare.py similarity index 100% rename from test/test_onionshare.py rename to tests/test_onionshare.py diff --git a/test/test_onionshare_common.py b/tests/test_onionshare_common.py similarity index 100% rename from test/test_onionshare_common.py rename to tests/test_onionshare_common.py diff --git a/test/test_onionshare_settings.py b/tests/test_onionshare_settings.py similarity index 100% rename from test/test_onionshare_settings.py rename to tests/test_onionshare_settings.py diff --git a/test/test_onionshare_strings.py b/tests/test_onionshare_strings.py similarity index 100% rename from test/test_onionshare_strings.py rename to tests/test_onionshare_strings.py diff --git a/test/test_onionshare_web.py b/tests/test_onionshare_web.py similarity index 100% rename from test/test_onionshare_web.py rename to tests/test_onionshare_web.py diff --git a/tests_gui_local/__init__.py b/tests_gui_local/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests_gui_local/commontests.py b/tests_gui_local/commontests.py new file mode 100644 index 00000000..de1ad9ab --- /dev/null +++ b/tests_gui_local/commontests.py @@ -0,0 +1,307 @@ +import os +import requests +import socket +import socks +import zipfile + +from PyQt5 import QtCore, QtTest +from onionshare import strings + +class CommonTests(object): + def test_gui_loaded(self): + '''Test that the GUI actually is shown''' + self.assertTrue(self.gui.show) + + def test_windowTitle_seen(self): + '''Test that the window title is OnionShare''' + self.assertEqual(self.gui.windowTitle(), 'OnionShare') + + def test_settings_button_is_visible(self): + '''Test that the settings button is visible''' + self.assertTrue(self.gui.settings_button.isVisible()) + + def test_server_status_bar_is_visible(self): + '''Test that the status bar is visible''' + self.assertTrue(self.gui.status_bar.isVisible()) + + def test_info_widget_is_not_visible(self, mode): + '''Test that the info widget along top of screen is not shown''' + if mode == 'receive': + self.assertFalse(self.gui.receive_mode.info_widget.isVisible()) + if mode == 'share': + self.assertFalse(self.gui.share_mode.info_widget.isVisible()) + + def test_info_widget_is_visible(self, mode): + '''Test that the info widget along top of screen is shown''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.info_widget.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.info_widget.isVisible()) + + def test_click_mode(self, mode): + '''Test that we can switch Mode by clicking the button''' + if mode == 'receive': + QtTest.QTest.mouseClick(self.gui.receive_mode_button, QtCore.Qt.LeftButton) + self.assertTrue(self.gui.mode, self.gui.MODE_RECEIVE) + if mode == 'share': + QtTest.QTest.mouseClick(self.gui.share_mode_button, QtCore.Qt.LeftButton) + self.assertTrue(self.gui.mode, self.gui.MODE_SHARE) + + def test_history_is_visible(self, mode): + '''Test that the History section is visible and that the relevant widget is present''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.uploads.isVisible()) + self.assertTrue(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.downloads.isVisible()) + self.assertTrue(self.gui.share_mode.downloads.no_downloads_label.isVisible()) + + def test_server_working_on_start_button_pressed(self, mode): + '''Test we can start the service''' + # Should be in SERVER_WORKING state + if mode == 'receive': + QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.receive_mode.server_status.status, 1) + if mode == 'share': + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.share_mode.server_status.status, 1) + + def test_server_status_indicator_says_starting(self, mode): + '''Test that the Server Status indicator shows we are Starting''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) + if mode == 'share': + self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) + + def test_settings_button_is_hidden(self): + '''Test that the settings button is hidden when the server starts''' + self.assertFalse(self.gui.settings_button.isVisible()) + + def test_a_server_is_started(self, mode): + '''Test that the server has started''' + QtTest.QTest.qWait(2000) + # Should now be in SERVER_STARTED state + if mode == 'receive': + self.assertEqual(self.gui.receive_mode.server_status.status, 2) + if mode == 'share': + self.assertEqual(self.gui.share_mode.server_status.status, 2) + + def test_a_web_server_is_running(self): + '''Test that the web server has started''' + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + self.assertEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) + + def test_have_a_slug(self, mode, public_mode): + '''Test that we have a valid slug''' + if mode == 'receive': + if not public_mode: + self.assertRegex(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') + else: + self.assertIsNone(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') + if mode == 'share': + if not public_mode: + self.assertRegex(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') + else: + self.assertIsNone(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') + + + def test_url_description_shown(self, mode): + '''Test that the URL label is showing''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.server_status.url_description.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.server_status.url_description.isVisible()) + + def test_have_copy_url_button(self, mode): + '''Test that the Copy URL button is shown''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.server_status.copy_url_button.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.server_status.copy_url_button.isVisible()) + + def test_server_status_indicator_says_started(self, mode): + '''Test that the Server Status indicator shows we are started''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_started', True)) + if mode == 'share': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_started', True)) + + def test_web_page(self, mode, string, public_mode): + '''Test that the web page contains a string''' + s = socks.socksocket() + s.settimeout(60) + s.connect(('127.0.0.1', self.gui.app.port)) + + if not public_mode: + if mode == 'receive': + path = '/{}'.format(self.gui.receive_mode.server_status.web.slug) + if mode == 'share': + path = '/{}'.format(self.gui.share_mode.server_status.web.slug) + else: + path = '/' + + http_request = 'GET {} HTTP/1.0\r\n'.format(path) + http_request += 'Host: 127.0.0.1\r\n' + http_request += '\r\n' + s.sendall(http_request.encode('utf-8')) + + with open('/tmp/webpage', 'wb') as file_to_write: + while True: + data = s.recv(1024) + if not data: + break + file_to_write.write(data) + file_to_write.close() + + f = open('/tmp/webpage') + self.assertTrue(string in f.read()) + f.close() + + def test_history_widgets_present(self, mode): + '''Test that the relevant widgets are present in the history view after activity has taken place''' + if mode == 'receive': + self.assertFalse(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) + self.assertTrue(self.gui.receive_mode.uploads.clear_history_button.isVisible()) + if mode == 'share': + self.assertFalse(self.gui.share_mode.downloads.no_downloads_label.isVisible()) + self.assertTrue(self.gui.share_mode.downloads.clear_history_button.isVisible()) + + def test_counter_incremented(self, mode, count): + '''Test that the counter has incremented''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.uploads_completed, count) + if mode == 'share': + self.assertEquals(self.gui.share_mode.downloads_completed, count) + + def test_server_is_stopped(self, mode, stay_open): + '''Test that the server stops when we click Stop''' + if mode == 'receive': + QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEquals(self.gui.receive_mode.server_status.status, 0) + if mode == 'share': + if stay_open: + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEquals(self.gui.share_mode.server_status.status, 0) + + def test_web_service_is_stopped(self): + '''Test that the web server also stopped''' + QtTest.QTest.qWait(2000) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + # We should be closed by now. Fail if not! + self.assertNotEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) + + def test_server_status_indicator_says_closed(self, mode, stay_open): + '''Test that the Server Status indicator shows we closed''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped', True)) + if mode == 'share': + if stay_open: + self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_stopped', True)) + else: + self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('closing_automatically', True)) + + # Auto-stop timer tests + def test_set_timeout(self, mode, timeout): + '''Test that the timeout can be set''' + timer = QtCore.QDateTime.currentDateTime().addSecs(timeout) + if mode == 'receive': + self.gui.receive_mode.server_status.shutdown_timeout.setDateTime(timer) + self.assertTrue(self.gui.receive_mode.server_status.shutdown_timeout.dateTime(), timer) + if mode == 'share': + self.gui.share_mode.server_status.shutdown_timeout.setDateTime(timer) + self.assertTrue(self.gui.share_mode.server_status.shutdown_timeout.dateTime(), timer) + + def test_timeout_widget_hidden(self, mode): + '''Test that the timeout widget is hidden when share has started''' + if mode == 'receive': + self.assertFalse(self.gui.receive_mode.server_status.shutdown_timeout_container.isVisible()) + if mode == 'share': + self.assertFalse(self.gui.share_mode.server_status.shutdown_timeout_container.isVisible()) + + def test_server_timed_out(self, mode, wait): + '''Test that the server has timed out after the timer ran out''' + QtTest.QTest.qWait(wait) + # We should have timed out now + if mode == 'receive': + self.assertEqual(self.gui.receive_mode.server_status.status, 0) + if mode == 'share': + self.assertEqual(self.gui.share_mode.server_status.status, 0) + + # Receive-specific tests + def test_upload_file(self, public_mode, expected_file): + '''Test that we can upload the file''' + files = {'file[]': open('/tmp/test.txt', 'rb')} + if not public_mode: + path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, self.gui.receive_mode.web.slug) + else: + path = 'http://127.0.0.1:{}/upload'.format(self.gui.app.port) + response = requests.post(path, files=files) + QtTest.QTest.qWait(2000) + self.assertTrue(os.path.isfile(expected_file)) + + # Share-specific tests + def test_file_selection_widget_has_a_file(self): + '''Test that the number of files in the list is 1''' + self.assertEqual(self.gui.share_mode.server_status.file_selection.get_num_files(), 1) + + def test_deleting_only_file_hides_delete_button(self): + '''Test that clicking on the file item shows the delete button. Test that deleting the only item in the list hides the delete button''' + rect = self.gui.share_mode.server_status.file_selection.file_list.visualItemRect(self.gui.share_mode.server_status.file_selection.file_list.item(0)) + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) + # Delete button should be visible + self.assertTrue(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + # Click delete, and since there's no more files, the delete button should be hidden + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.delete_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + + def test_add_a_file_and_delete_using_its_delete_widget(self): + '''Test that we can also delete a file by clicking on its [X] widget''' + self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.item(0).item_button, QtCore.Qt.LeftButton) + self.assertEquals(self.gui.share_mode.server_status.file_selection.get_num_files(), 0) + + def test_file_selection_widget_readd_files(self): + '''Re-add some files to the list so we can share''' + self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') + self.gui.share_mode.server_status.file_selection.file_list.add_file('/tmp/test.txt') + self.assertEqual(self.gui.share_mode.server_status.file_selection.get_num_files(), 2) + + def test_add_delete_buttons_hidden(self): + '''Test that the add and delete buttons are hidden when the server starts''' + self.assertFalse(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) + self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + + def test_download_share(self, public_mode): + '''Test that we can download the share''' + s = socks.socksocket() + s.settimeout(60) + s.connect(('127.0.0.1', self.gui.app.port)) + + if public_mode: + path = '/download' + else: + path = '{}/download'.format(self.gui.share_mode.web.slug) + + http_request = 'GET {} HTTP/1.0\r\n'.format(path) + http_request += 'Host: 127.0.0.1\r\n' + http_request += '\r\n' + s.sendall(http_request.encode('utf-8')) + + with open('/tmp/download.zip', 'wb') as file_to_write: + while True: + data = s.recv(1024) + if not data: + break + file_to_write.write(data) + file_to_write.close() + + zip = zipfile.ZipFile('/tmp/download.zip') + QtTest.QTest.qWait(2000) + self.assertEquals('onionshare', zip.read('test.txt').decode('utf-8')) + + def test_add_button_visible(self): + '''Test that the add button should be visible''' + self.assertTrue(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) + diff --git a/tests_gui_local/conftest.py b/tests_gui_local/conftest.py new file mode 100644 index 00000000..8ac7efb8 --- /dev/null +++ b/tests_gui_local/conftest.py @@ -0,0 +1,160 @@ +import sys +# Force tests to look for resources in the source code tree +sys.onionshare_dev_mode = True + +import os +import shutil +import tempfile + +import pytest + +from onionshare import common, web, settings + +@pytest.fixture +def temp_dir_1024(): + """ Create a temporary directory that has a single file of a + particular size (1024 bytes). + """ + + tmp_dir = tempfile.mkdtemp() + tmp_file, tmp_file_path = tempfile.mkstemp(dir=tmp_dir) + with open(tmp_file, 'wb') as f: + f.write(b'*' * 1024) + return tmp_dir + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture +def temp_dir_1024_delete(): + """ Create a temporary directory that has a single file of a + particular size (1024 bytes). The temporary directory (including + the file inside) will be deleted after fixture usage. + """ + + with tempfile.TemporaryDirectory() as tmp_dir: + tmp_file, tmp_file_path = tempfile.mkstemp(dir=tmp_dir) + with open(tmp_file, 'wb') as f: + f.write(b'*' * 1024) + yield tmp_dir + + +@pytest.fixture +def temp_file_1024(): + """ Create a temporary file of a particular size (1024 bytes). """ + + with tempfile.NamedTemporaryFile(delete=False) as tmp_file: + tmp_file.write(b'*' * 1024) + return tmp_file.name + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture +def temp_file_1024_delete(): + """ + Create a temporary file of a particular size (1024 bytes). + The temporary file will be deleted after fixture usage. + """ + + with tempfile.NamedTemporaryFile() as tmp_file: + tmp_file.write(b'*' * 1024) + tmp_file.flush() + yield tmp_file.name + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture(scope='session') +def custom_zw(): + zw = web.share_mode.ZipWriter( + common.Common(), + zip_filename=common.Common.random_string(4, 6), + processed_size_callback=lambda _: 'custom_callback' + ) + yield zw + zw.close() + os.remove(zw.zip_filename) + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture(scope='session') +def default_zw(): + zw = web.share_mode.ZipWriter(common.Common()) + yield zw + zw.close() + tmp_dir = os.path.dirname(zw.zip_filename) + shutil.rmtree(tmp_dir) + + +@pytest.fixture +def locale_en(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('en_US', 'UTF-8')) + + +@pytest.fixture +def locale_fr(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('fr_FR', 'UTF-8')) + + +@pytest.fixture +def locale_invalid(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('xx_XX', 'UTF-8')) + + +@pytest.fixture +def locale_ru(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('ru_RU', 'UTF-8')) + + +@pytest.fixture +def platform_darwin(monkeypatch): + monkeypatch.setattr('platform.system', lambda: 'Darwin') + + +@pytest.fixture # (scope="session") +def platform_linux(monkeypatch): + monkeypatch.setattr('platform.system', lambda: 'Linux') + + +@pytest.fixture +def platform_windows(monkeypatch): + monkeypatch.setattr('platform.system', lambda: 'Windows') + + +@pytest.fixture +def sys_argv_sys_prefix(monkeypatch): + monkeypatch.setattr('sys.argv', [sys.prefix]) + + +@pytest.fixture +def sys_frozen(monkeypatch): + monkeypatch.setattr('sys.frozen', True, raising=False) + + +@pytest.fixture +def sys_meipass(monkeypatch): + monkeypatch.setattr( + 'sys._MEIPASS', os.path.expanduser('~'), raising=False) + + +@pytest.fixture # (scope="session") +def sys_onionshare_dev_mode(monkeypatch): + monkeypatch.setattr('sys.onionshare_dev_mode', True, raising=False) + + +@pytest.fixture +def time_time_100(monkeypatch): + monkeypatch.setattr('time.time', lambda: 100) + + +@pytest.fixture +def time_strftime(monkeypatch): + monkeypatch.setattr('time.strftime', lambda _: 'Jun 06 2013 11:05:00') + +@pytest.fixture +def common_obj(): + return common.Common() + +@pytest.fixture +def settings_obj(sys_onionshare_dev_mode, platform_linux): + _common = common.Common() + _common.version = 'DUMMY_VERSION_1.2.3' + return settings.Settings(_common) diff --git a/tests_gui_local/onionshare_receive_mode_upload_test.py b/tests_gui_local/onionshare_receive_mode_upload_test.py new file mode 100644 index 00000000..bac622fb --- /dev/null +++ b/tests_gui_local/onionshare_receive_mode_upload_test.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, True) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + os.remove('/tmp/OnionShare/test.txt') + os.remove('/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_info_widget_is_not_visible(self): + CommonTests.test_info_widget_is_not_visible(self, 'receive') + + @pytest.mark.run(order=6) + def test_click_mode(self): + CommonTests.test_click_mode(self, 'receive') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'receive') + + @pytest.mark.run(order=8) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + + @pytest.mark.run(order=9) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'receive') + + @pytest.mark.run(order=10) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=11) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'receive') + + @pytest.mark.run(order=12) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=14) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'receive', False) + + @pytest.mark.run(order=15) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'receive') + + @pytest.mark.run(order=16) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'receive') + + @pytest.mark.run(order=17) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'receive') + + @pytest.mark.run(order=18) + def test_web_page(self): + CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', False) + + @pytest.mark.run(order=19) + def test_upload_file(self): + CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test.txt') + + @pytest.mark.run(order=20) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'receive') + + @pytest.mark.run(order=21) + def test_counter_incremented(self): + CommonTests.test_counter_incremented(self, 'receive', 1) + + @pytest.mark.run(order=22) + def test_upload_same_file_is_renamed(self): + CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=23) + def test_upload_count_incremented_again(self): + CommonTests.test_counter_incremented(self, 'receive', 2) + + @pytest.mark.run(order=24) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'receive', False) + + @pytest.mark.run(order=25) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=26) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py new file mode 100644 index 00000000..8ed385f5 --- /dev/null +++ b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": True, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, True) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + os.remove('/tmp/OnionShare/test.txt') + os.remove('/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_info_widget_is_not_visible(self): + CommonTests.test_info_widget_is_not_visible(self, 'receive') + + @pytest.mark.run(order=6) + def test_click_mode(self): + CommonTests.test_click_mode(self, 'receive') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'receive') + + @pytest.mark.run(order=8) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + + @pytest.mark.run(order=9) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'receive') + + @pytest.mark.run(order=10) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=11) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'receive') + + @pytest.mark.run(order=12) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=14) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'receive', True) + + @pytest.mark.run(order=15) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'receive') + + @pytest.mark.run(order=16) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'receive') + + @pytest.mark.run(order=17) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'receive') + + @pytest.mark.run(order=18) + def test_web_page(self): + CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', True) + + @pytest.mark.run(order=19) + def test_upload_file(self): + CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test.txt') + + @pytest.mark.run(order=20) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'receive') + + @pytest.mark.run(order=21) + def test_counter_incremented(self): + CommonTests.test_counter_incremented(self, 'receive', 1) + + @pytest.mark.run(order=22) + def test_upload_same_file_is_renamed(self): + CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=23) + def test_upload_count_incremented_again(self): + CommonTests.test_counter_incremented(self, 'receive', 2) + + @pytest.mark.run(order=24) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'receive', False) + + @pytest.mark.run(order=25) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=26) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_local/onionshare_share_mode_download_test.py b/tests_gui_local/onionshare_share_mode_download_test.py new file mode 100644 index 00000000..0ef03e97 --- /dev/null +++ b/tests_gui_local/onionshare_share_mode_download_test.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, True) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', False) + + @pytest.mark.run(order=18) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=19) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=20) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=21) + def test_web_page(self): + CommonTests.test_web_page(self, 'share', 'Total size', False) + + @pytest.mark.run(order=22) + def test_download_share(self): + CommonTests.test_download_share(self, False) + + @pytest.mark.run(order=23) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'share') + + @pytest.mark.run(order=24) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', False) + + @pytest.mark.run(order=25) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=26) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + + @pytest.mark.run(order=27) + def test_add_button_visible(self): + CommonTests.test_add_button_visible(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py new file mode 100644 index 00000000..417eb8b9 --- /dev/null +++ b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": True, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, True) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', True) + + @pytest.mark.run(order=18) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=19) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=20) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=21) + def test_web_page(self): + CommonTests.test_web_page(self, 'share', 'Total size', True) + + @pytest.mark.run(order=22) + def test_download_share(self): + CommonTests.test_download_share(self, True) + + @pytest.mark.run(order=23) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'share') + + @pytest.mark.run(order=24) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', False) + + @pytest.mark.run(order=25) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=26) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + + @pytest.mark.run(order=27) + def test_add_button_visible(self): + CommonTests.test_add_button_visible(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py new file mode 100644 index 00000000..c3177a38 --- /dev/null +++ b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": False, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": True, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, True) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', True) + + @pytest.mark.run(order=18) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=19) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=20) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=21) + def test_web_page(self): + CommonTests.test_web_page(self, 'share', 'Total size', True) + + @pytest.mark.run(order=22) + def test_download_share(self): + CommonTests.test_download_share(self, True) + + @pytest.mark.run(order=23) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'share') + + @pytest.mark.run(order=24) + def test_counter_incremented(self): + CommonTests.test_counter_incremented(self, 'share', 1) + + @pytest.mark.run(order=25) + def test_download_share_again(self): + CommonTests.test_download_share(self, True) + + @pytest.mark.run(order=26) + def test_counter_incremented_again(self): + CommonTests.test_counter_incremented(self, 'share', 2) + + @pytest.mark.run(order=27) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', True) + + @pytest.mark.run(order=28) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=29) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + + @pytest.mark.run(order=30) + def test_add_button_visible(self): + CommonTests.test_add_button_visible(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_local/onionshare_slug_persistent_test.py b/tests_gui_local/onionshare_slug_persistent_test.py new file mode 100644 index 00000000..05c9719a --- /dev/null +++ b/tests_gui_local/onionshare_slug_persistent_test.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + slug = '' + + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": True, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, True) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=6) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=8) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=9) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=10) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=11) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=12) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', False) + global slug + slug = self.gui.share_mode.server_status.web.slug + + @pytest.mark.run(order=13) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=14) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', True) + + @pytest.mark.run(order=15) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=16) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + + @pytest.mark.run(order=17) + def test_server_started_again(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=18) + def test_have_same_slug(self): + '''Test that we have the same slug''' + self.assertEqual(self.gui.share_mode.server_status.web.slug, slug) + + @pytest.mark.run(order=19) + def test_server_is_stopped_again(self): + CommonTests.test_server_is_stopped(self, 'share', True) + CommonTests.test_web_service_is_stopped(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_local/onionshare_timer_test.py b/tests_gui_local/onionshare_timer_test.py new file mode 100644 index 00000000..f36331b8 --- /dev/null +++ b/tests_gui_local/onionshare_timer_test.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, True, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": True, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, True) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_set_timeout(self): + CommonTests.test_set_timeout(self, 'share', 5) + + @pytest.mark.run(order=9) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=10) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=11) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=12) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=13) + def test_timeout_widget_hidden(self): + CommonTests.test_timeout_widget_hidden(self, 'share') + + @pytest.mark.run(order=14) + def test_timeout(self): + CommonTests.test_server_timed_out(self, 'share', 10000) + + @pytest.mark.run(order=15) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_local/run_unit_tests.sh b/tests_gui_local/run_unit_tests.sh new file mode 100755 index 00000000..d15f8a6e --- /dev/null +++ b/tests_gui_local/run_unit_tests.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +for test in `ls -1 | egrep ^onionshare_`; do + py.test-3 $test -vvv || exit 1 +done diff --git a/tests_gui_tor/__init__.py b/tests_gui_tor/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests_gui_tor/commontests.py b/tests_gui_tor/commontests.py new file mode 100644 index 00000000..a0d9bf5f --- /dev/null +++ b/tests_gui_tor/commontests.py @@ -0,0 +1,359 @@ +import os +import requests +import socket +import socks +import zipfile + +from PyQt5 import QtCore, QtTest +from onionshare import strings + +class CommonTests(object): + def test_gui_loaded(self): + '''Test that the GUI actually is shown''' + self.assertTrue(self.gui.show) + + def test_windowTitle_seen(self): + '''Test that the window title is OnionShare''' + self.assertEqual(self.gui.windowTitle(), 'OnionShare') + + def test_settings_button_is_visible(self): + '''Test that the settings button is visible''' + self.assertTrue(self.gui.settings_button.isVisible()) + + def test_server_status_bar_is_visible(self): + '''Test that the status bar is visible''' + self.assertTrue(self.gui.status_bar.isVisible()) + + def test_info_widget_is_not_visible(self, mode): + '''Test that the info widget along top of screen is not shown''' + if mode == 'receive': + self.assertFalse(self.gui.receive_mode.info_widget.isVisible()) + if mode == 'share': + self.assertFalse(self.gui.share_mode.info_widget.isVisible()) + + def test_info_widget_is_visible(self, mode): + '''Test that the info widget along top of screen is shown''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.info_widget.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.info_widget.isVisible()) + + def test_click_mode(self, mode): + '''Test that we can switch Mode by clicking the button''' + if mode == 'receive': + QtTest.QTest.mouseClick(self.gui.receive_mode_button, QtCore.Qt.LeftButton) + self.assertTrue(self.gui.mode, self.gui.MODE_RECEIVE) + if mode == 'share': + QtTest.QTest.mouseClick(self.gui.share_mode_button, QtCore.Qt.LeftButton) + self.assertTrue(self.gui.mode, self.gui.MODE_SHARE) + + def test_history_is_visible(self, mode): + '''Test that the History section is visible and that the relevant widget is present''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.uploads.isVisible()) + self.assertTrue(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.downloads.isVisible()) + self.assertTrue(self.gui.share_mode.downloads.no_downloads_label.isVisible()) + + def test_server_working_on_start_button_pressed(self, mode): + '''Test we can start the service''' + # Should be in SERVER_WORKING state + if mode == 'receive': + QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.receive_mode.server_status.status, 1) + if mode == 'share': + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.share_mode.server_status.status, 1) + + def test_server_status_indicator_says_starting(self, mode): + '''Test that the Server Status indicator shows we are Starting''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) + if mode == 'share': + self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) + + def test_settings_button_is_hidden(self): + '''Test that the settings button is hidden when the server starts''' + self.assertFalse(self.gui.settings_button.isVisible()) + + def test_a_server_is_started(self, mode): + '''Test that the server has started''' + QtTest.QTest.qWait(45000) + # Should now be in SERVER_STARTED state + if mode == 'receive': + self.assertEqual(self.gui.receive_mode.server_status.status, 2) + if mode == 'share': + self.assertEqual(self.gui.share_mode.server_status.status, 2) + + def test_a_web_server_is_running(self): + '''Test that the web server has started''' + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + self.assertEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) + + def test_have_a_slug(self, mode, public_mode): + '''Test that we have a valid slug''' + if mode == 'receive': + if not public_mode: + self.assertRegex(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') + else: + self.assertIsNone(self.gui.receive_mode.server_status.web.slug, r'(\w+)-(\w+)') + if mode == 'share': + if not public_mode: + self.assertRegex(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') + else: + self.assertIsNone(self.gui.share_mode.server_status.web.slug, r'(\w+)-(\w+)') + + def test_have_an_onion_service(self): + '''Test that we have a valid Onion URL''' + self.assertRegex(self.gui.app.onion_host, r'[a-z2-7].onion') + + def test_url_description_shown(self, mode): + '''Test that the URL label is showing''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.server_status.url_description.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.server_status.url_description.isVisible()) + + def test_have_copy_url_button(self, mode): + '''Test that the Copy URL button is shown''' + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.server_status.copy_url_button.isVisible()) + if mode == 'share': + self.assertTrue(self.gui.share_mode.server_status.copy_url_button.isVisible()) + + def test_server_status_indicator_says_started(self, mode): + '''Test that the Server Status indicator shows we are started''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_started', True)) + if mode == 'share': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_started', True)) + + def test_web_page(self, mode, string, public_mode): + '''Test that the web page contains a string''' + (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() + socks.set_default_proxy(socks.SOCKS5, socks_address, socks_port) + + s = socks.socksocket() + s.settimeout(60) + s.connect((self.gui.app.onion_host, 80)) + + if not public_mode: + if mode == 'receive': + path = '/{}'.format(self.gui.receive_mode.server_status.web.slug) + if mode == 'share': + path = '/{}'.format(self.gui.share_mode.server_status.web.slug) + else: + path = '/' + + http_request = 'GET {} HTTP/1.0\r\n'.format(path) + http_request += 'Host: {}\r\n'.format(self.gui.app.onion_host) + http_request += '\r\n' + s.sendall(http_request.encode('utf-8')) + + with open('/tmp/webpage', 'wb') as file_to_write: + while True: + data = s.recv(1024) + if not data: + break + file_to_write.write(data) + file_to_write.close() + + f = open('/tmp/webpage') + self.assertTrue(string in f.read()) + f.close() + + def test_history_widgets_present(self, mode): + '''Test that the relevant widgets are present in the history view after activity has taken place''' + if mode == 'receive': + self.assertFalse(self.gui.receive_mode.uploads.no_uploads_label.isVisible()) + self.assertTrue(self.gui.receive_mode.uploads.clear_history_button.isVisible()) + if mode == 'share': + self.assertFalse(self.gui.share_mode.downloads.no_downloads_label.isVisible()) + self.assertTrue(self.gui.share_mode.downloads.clear_history_button.isVisible()) + + def test_counter_incremented(self, mode, count): + '''Test that the counter has incremented''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.uploads_completed, count) + if mode == 'share': + self.assertEquals(self.gui.share_mode.downloads_completed, count) + + def test_server_is_stopped(self, mode, stay_open): + '''Test that the server stops when we click Stop''' + if mode == 'receive': + QtTest.QTest.mouseClick(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEquals(self.gui.receive_mode.server_status.status, 0) + if mode == 'share': + if stay_open: + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEquals(self.gui.share_mode.server_status.status, 0) + + def test_web_service_is_stopped(self): + '''Test that the web server also stopped''' + QtTest.QTest.qWait(2000) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + # We should be closed by now. Fail if not! + self.assertNotEqual(sock.connect_ex(('127.0.0.1',self.gui.app.port)), 0) + + def test_server_status_indicator_says_closed(self, mode, stay_open): + '''Test that the Server Status indicator shows we closed''' + if mode == 'receive': + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped', True)) + if mode == 'share': + if stay_open: + self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_stopped', True)) + else: + self.assertEquals(self.gui.share_mode.server_status_label.text(), strings._('closing_automatically', True)) + + def test_cancel_the_share(self, mode): + '''Test that we can cancel this share before it's started up ''' + if mode == 'share': + QtTest.QTest.mousePress(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) + QtTest.QTest.qWait(1000) + QtTest.QTest.mouseRelease(self.gui.share_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.share_mode.server_status.status, 0) + + if mode == 'receive': + QtTest.QTest.mousePress(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) + QtTest.QTest.qWait(1000) + QtTest.QTest.mouseRelease(self.gui.receive_mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(self.gui.receive_mode.server_status.status, 0) + + + # Auto-stop timer tests + def test_set_timeout(self, mode, timeout): + '''Test that the timeout can be set''' + timer = QtCore.QDateTime.currentDateTime().addSecs(timeout) + if mode == 'receive': + self.gui.receive_mode.server_status.shutdown_timeout.setDateTime(timer) + self.assertTrue(self.gui.receive_mode.server_status.shutdown_timeout.dateTime(), timer) + if mode == 'share': + self.gui.share_mode.server_status.shutdown_timeout.setDateTime(timer) + self.assertTrue(self.gui.share_mode.server_status.shutdown_timeout.dateTime(), timer) + + def test_timeout_widget_hidden(self, mode): + '''Test that the timeout widget is hidden when share has started''' + if mode == 'receive': + self.assertFalse(self.gui.receive_mode.server_status.shutdown_timeout_container.isVisible()) + if mode == 'share': + self.assertFalse(self.gui.share_mode.server_status.shutdown_timeout_container.isVisible()) + + def test_server_timed_out(self, mode, wait): + '''Test that the server has timed out after the timer ran out''' + QtTest.QTest.qWait(wait) + # We should have timed out now + if mode == 'receive': + self.assertEqual(self.gui.receive_mode.server_status.status, 0) + if mode == 'share': + self.assertEqual(self.gui.share_mode.server_status.status, 0) + + # Receive-specific tests + def test_upload_file(self, public_mode, expected_file): + '''Test that we can upload the file''' + (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() + session = requests.session() + session.proxies = {} + session.proxies['http'] = 'socks5h://{}:{}'.format(socks_address, socks_port) + + files = {'file[]': open('/tmp/test.txt', 'rb')} + if not public_mode: + path = 'http://{}/{}/upload'.format(self.gui.app.onion_host, self.gui.receive_mode.web.slug) + else: + path = 'http://{}/upload'.format(self.gui.app.onion_host) + response = session.post(path, files=files) + QtTest.QTest.qWait(4000) + self.assertTrue(os.path.isfile(expected_file)) + + # Share-specific tests + def test_file_selection_widget_has_a_file(self): + '''Test that the number of files in the list is 1''' + self.assertEqual(self.gui.share_mode.server_status.file_selection.get_num_files(), 1) + + def test_deleting_only_file_hides_delete_button(self): + '''Test that clicking on the file item shows the delete button. Test that deleting the only item in the list hides the delete button''' + rect = self.gui.share_mode.server_status.file_selection.file_list.visualItemRect(self.gui.share_mode.server_status.file_selection.file_list.item(0)) + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.viewport(), QtCore.Qt.LeftButton, pos=rect.center()) + # Delete button should be visible + self.assertTrue(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + # Click delete, and since there's no more files, the delete button should be hidden + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.delete_button, QtCore.Qt.LeftButton) + self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + + def test_add_a_file_and_delete_using_its_delete_widget(self): + '''Test that we can also delete a file by clicking on its [X] widget''' + self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') + QtTest.QTest.mouseClick(self.gui.share_mode.server_status.file_selection.file_list.item(0).item_button, QtCore.Qt.LeftButton) + self.assertEquals(self.gui.share_mode.server_status.file_selection.get_num_files(), 0) + + def test_file_selection_widget_readd_files(self): + '''Re-add some files to the list so we can share''' + self.gui.share_mode.server_status.file_selection.file_list.add_file('/etc/hosts') + self.gui.share_mode.server_status.file_selection.file_list.add_file('/tmp/test.txt') + self.assertEqual(self.gui.share_mode.server_status.file_selection.get_num_files(), 2) + + def test_add_delete_buttons_hidden(self): + '''Test that the add and delete buttons are hidden when the server starts''' + self.assertFalse(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) + self.assertFalse(self.gui.share_mode.server_status.file_selection.delete_button.isVisible()) + + def test_download_share(self, public_mode): + '''Test that we can download the share''' + (socks_address, socks_port) = self.gui.app.onion.get_tor_socks_port() + socks.set_default_proxy(socks.SOCKS5, socks_address, socks_port) + + s = socks.socksocket() + s.settimeout(60) + s.connect((self.gui.app.onion_host, 80)) + + if public_mode: + path = '/download' + else: + path = '{}/download'.format(self.gui.share_mode.web.slug) + + http_request = 'GET {} HTTP/1.0\r\n'.format(path) + http_request += 'Host: {}\r\n'.format(self.gui.app.onion_host) + http_request += '\r\n' + s.sendall(http_request.encode('utf-8')) + + with open('/tmp/download.zip', 'wb') as file_to_write: + while True: + data = s.recv(1024) + if not data: + break + file_to_write.write(data) + file_to_write.close() + + zip = zipfile.ZipFile('/tmp/download.zip') + QtTest.QTest.qWait(4000) + self.assertEquals('onionshare', zip.read('test.txt').decode('utf-8')) + + def test_add_button_visible(self): + '''Test that the add button should be visible''' + self.assertTrue(self.gui.share_mode.server_status.file_selection.add_button.isVisible()) + + + # Stealth tests + def test_copy_have_hidserv_auth_button(self, mode): + '''Test that the Copy HidservAuth button is shown''' + if mode == 'share': + self.assertTrue(self.gui.share_mode.server_status.copy_hidservauth_button.isVisible()) + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.server_status.copy_hidservauth_button.isVisible()) + + def test_hidserv_auth_string(self): + '''Test the validity of the HidservAuth string''' + self.assertRegex(self.gui.app.auth_string, r'HidServAuth %s [a-zA-Z1-9]' % self.gui.app.onion_host) + + + # Miscellaneous tests + def test_tor_killed_statusbar_message_shown(self, mode): + '''Test that the status bar message shows Tor was disconnected''' + self.gui.app.onion.cleanup(stop_tor=True) + QtTest.QTest.qWait(2500) + if mode == 'share': + self.assertTrue(self.gui.share_mode.status_bar.currentMessage(), strings._('gui_tor_connection_lost', True)) + if mode == 'receive': + self.assertTrue(self.gui.receive_mode.status_bar.currentMessage(), strings._('gui_tor_connection_lost', True)) diff --git a/tests_gui_tor/conftest.py b/tests_gui_tor/conftest.py new file mode 100644 index 00000000..8ac7efb8 --- /dev/null +++ b/tests_gui_tor/conftest.py @@ -0,0 +1,160 @@ +import sys +# Force tests to look for resources in the source code tree +sys.onionshare_dev_mode = True + +import os +import shutil +import tempfile + +import pytest + +from onionshare import common, web, settings + +@pytest.fixture +def temp_dir_1024(): + """ Create a temporary directory that has a single file of a + particular size (1024 bytes). + """ + + tmp_dir = tempfile.mkdtemp() + tmp_file, tmp_file_path = tempfile.mkstemp(dir=tmp_dir) + with open(tmp_file, 'wb') as f: + f.write(b'*' * 1024) + return tmp_dir + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture +def temp_dir_1024_delete(): + """ Create a temporary directory that has a single file of a + particular size (1024 bytes). The temporary directory (including + the file inside) will be deleted after fixture usage. + """ + + with tempfile.TemporaryDirectory() as tmp_dir: + tmp_file, tmp_file_path = tempfile.mkstemp(dir=tmp_dir) + with open(tmp_file, 'wb') as f: + f.write(b'*' * 1024) + yield tmp_dir + + +@pytest.fixture +def temp_file_1024(): + """ Create a temporary file of a particular size (1024 bytes). """ + + with tempfile.NamedTemporaryFile(delete=False) as tmp_file: + tmp_file.write(b'*' * 1024) + return tmp_file.name + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture +def temp_file_1024_delete(): + """ + Create a temporary file of a particular size (1024 bytes). + The temporary file will be deleted after fixture usage. + """ + + with tempfile.NamedTemporaryFile() as tmp_file: + tmp_file.write(b'*' * 1024) + tmp_file.flush() + yield tmp_file.name + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture(scope='session') +def custom_zw(): + zw = web.share_mode.ZipWriter( + common.Common(), + zip_filename=common.Common.random_string(4, 6), + processed_size_callback=lambda _: 'custom_callback' + ) + yield zw + zw.close() + os.remove(zw.zip_filename) + + +# pytest > 2.9 only needs @pytest.fixture +@pytest.yield_fixture(scope='session') +def default_zw(): + zw = web.share_mode.ZipWriter(common.Common()) + yield zw + zw.close() + tmp_dir = os.path.dirname(zw.zip_filename) + shutil.rmtree(tmp_dir) + + +@pytest.fixture +def locale_en(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('en_US', 'UTF-8')) + + +@pytest.fixture +def locale_fr(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('fr_FR', 'UTF-8')) + + +@pytest.fixture +def locale_invalid(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('xx_XX', 'UTF-8')) + + +@pytest.fixture +def locale_ru(monkeypatch): + monkeypatch.setattr('locale.getdefaultlocale', lambda: ('ru_RU', 'UTF-8')) + + +@pytest.fixture +def platform_darwin(monkeypatch): + monkeypatch.setattr('platform.system', lambda: 'Darwin') + + +@pytest.fixture # (scope="session") +def platform_linux(monkeypatch): + monkeypatch.setattr('platform.system', lambda: 'Linux') + + +@pytest.fixture +def platform_windows(monkeypatch): + monkeypatch.setattr('platform.system', lambda: 'Windows') + + +@pytest.fixture +def sys_argv_sys_prefix(monkeypatch): + monkeypatch.setattr('sys.argv', [sys.prefix]) + + +@pytest.fixture +def sys_frozen(monkeypatch): + monkeypatch.setattr('sys.frozen', True, raising=False) + + +@pytest.fixture +def sys_meipass(monkeypatch): + monkeypatch.setattr( + 'sys._MEIPASS', os.path.expanduser('~'), raising=False) + + +@pytest.fixture # (scope="session") +def sys_onionshare_dev_mode(monkeypatch): + monkeypatch.setattr('sys.onionshare_dev_mode', True, raising=False) + + +@pytest.fixture +def time_time_100(monkeypatch): + monkeypatch.setattr('time.time', lambda: 100) + + +@pytest.fixture +def time_strftime(monkeypatch): + monkeypatch.setattr('time.strftime', lambda _: 'Jun 06 2013 11:05:00') + +@pytest.fixture +def common_obj(): + return common.Common() + +@pytest.fixture +def settings_obj(sys_onionshare_dev_mode, platform_linux): + _common = common.Common() + _common.version = 'DUMMY_VERSION_1.2.3' + return settings.Settings(_common) diff --git a/tests_gui_tor/onionshare_receive_mode_upload_test.py b/tests_gui_tor/onionshare_receive_mode_upload_test.py new file mode 100644 index 00000000..5c2945f1 --- /dev/null +++ b/tests_gui_tor/onionshare_receive_mode_upload_test.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + os.remove('/tmp/OnionShare/test.txt') + os.remove('/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_info_widget_is_not_visible(self): + CommonTests.test_info_widget_is_not_visible(self, 'receive') + + @pytest.mark.run(order=6) + def test_click_mode(self): + CommonTests.test_click_mode(self, 'receive') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'receive') + + @pytest.mark.run(order=8) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + + @pytest.mark.run(order=9) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'receive') + + @pytest.mark.run(order=10) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=11) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'receive') + + @pytest.mark.run(order=12) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=14) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'receive', False) + + @pytest.mark.run(order=15) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=16) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'receive') + + @pytest.mark.run(order=17) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'receive') + + @pytest.mark.run(order=18) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'receive') + + @pytest.mark.run(order=19) + def test_web_page(self): + CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', False) + + @pytest.mark.run(order=20) + def test_upload_file(self): + CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test.txt') + + @pytest.mark.run(order=21) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'receive') + + @pytest.mark.run(order=22) + def test_counter_incremented(self): + CommonTests.test_counter_incremented(self, 'receive', 1) + + @pytest.mark.run(order=23) + def test_upload_same_file_is_renamed(self): + CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=24) + def test_upload_count_incremented_again(self): + CommonTests.test_counter_incremented(self, 'receive', 2) + + @pytest.mark.run(order=25) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'receive', False) + + @pytest.mark.run(order=26) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=27) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py b/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py new file mode 100644 index 00000000..86cde0d9 --- /dev/null +++ b/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": True, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + os.remove('/tmp/OnionShare/test.txt') + os.remove('/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_info_widget_is_not_visible(self): + CommonTests.test_info_widget_is_not_visible(self, 'receive') + + @pytest.mark.run(order=6) + def test_click_mode(self): + CommonTests.test_click_mode(self, 'receive') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'receive') + + @pytest.mark.run(order=8) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + + @pytest.mark.run(order=9) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'receive') + + @pytest.mark.run(order=10) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=11) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'receive') + + @pytest.mark.run(order=12) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=14) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'receive', True) + + @pytest.mark.run(order=15) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=16) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'receive') + + @pytest.mark.run(order=17) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'receive') + + @pytest.mark.run(order=18) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'receive') + + @pytest.mark.run(order=19) + def test_web_page(self): + CommonTests.test_web_page(self, 'receive', 'Select the files you want to send, then click', True) + + @pytest.mark.run(order=20) + def test_upload_file(self): + CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test.txt') + + @pytest.mark.run(order=21) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'receive') + + @pytest.mark.run(order=22) + def test_counter_incremented(self): + CommonTests.test_counter_incremented(self, 'receive', 1) + + @pytest.mark.run(order=23) + def test_upload_same_file_is_renamed(self): + CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test-2.txt') + + @pytest.mark.run(order=24) + def test_upload_count_incremented_again(self): + CommonTests.test_counter_incremented(self, 'receive', 2) + + @pytest.mark.run(order=25) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'receive', False) + + @pytest.mark.run(order=26) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=27) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_share_mode_cancel_share_test.py b/tests_gui_tor/onionshare_share_mode_cancel_share_test.py new file mode 100644 index 00000000..a2d1a06a --- /dev/null +++ b/tests_gui_tor/onionshare_share_mode_cancel_share_test.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_cancel_the_share(self): + CommonTests.test_cancel_the_share(self, 'share') + + @pytest.mark.run(order=18) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', False) + + @pytest.mark.run(order=19) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=20) + def test_add_button_visible(self): + CommonTests.test_add_button_visible(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_share_mode_download_test.py b/tests_gui_tor/onionshare_share_mode_download_test.py new file mode 100644 index 00000000..d1eb5b54 --- /dev/null +++ b/tests_gui_tor/onionshare_share_mode_download_test.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', False) + + @pytest.mark.run(order=18) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=19) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=20) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=21) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=22) + def test_web_page(self): + CommonTests.test_web_page(self, 'share', 'Total size', False) + + @pytest.mark.run(order=23) + def test_download_share(self): + CommonTests.test_download_share(self, False) + + @pytest.mark.run(order=24) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'share') + + @pytest.mark.run(order=25) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', False) + + @pytest.mark.run(order=26) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=27) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + + @pytest.mark.run(order=28) + def test_add_button_visible(self): + CommonTests.test_add_button_visible(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py b/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py new file mode 100644 index 00000000..4e5f1114 --- /dev/null +++ b/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": True, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', True) + + @pytest.mark.run(order=18) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=19) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=20) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=21) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=22) + def test_web_page(self): + CommonTests.test_web_page(self, 'share', 'Total size', True) + + @pytest.mark.run(order=23) + def test_download_share(self): + CommonTests.test_download_share(self, True) + + @pytest.mark.run(order=24) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'share') + + @pytest.mark.run(order=25) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', False) + + @pytest.mark.run(order=26) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=27) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + + @pytest.mark.run(order=28) + def test_add_button_visible(self): + CommonTests.test_add_button_visible(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py b/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py new file mode 100644 index 00000000..78cd1578 --- /dev/null +++ b/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": False, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": True, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', True) + + @pytest.mark.run(order=18) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=19) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=20) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=21) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=22) + def test_web_page(self): + CommonTests.test_web_page(self, 'share', 'Total size', True) + + @pytest.mark.run(order=23) + def test_download_share(self): + CommonTests.test_download_share(self, True) + + @pytest.mark.run(order=24) + def test_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, 'share') + + @pytest.mark.run(order=25) + def test_counter_incremented(self): + CommonTests.test_counter_incremented(self, 'share', 1) + + @pytest.mark.run(order=26) + def test_download_share_again(self): + CommonTests.test_download_share(self, True) + + @pytest.mark.run(order=27) + def test_counter_incremented_again(self): + CommonTests.test_counter_incremented(self, 'share', 2) + + @pytest.mark.run(order=28) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', True) + + @pytest.mark.run(order=29) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=30) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + + @pytest.mark.run(order=31) + def test_add_button_visible(self): + CommonTests.test_add_button_visible(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_share_mode_persistent_test.py b/tests_gui_tor/onionshare_share_mode_persistent_test.py new file mode 100644 index 00000000..a2d429b2 --- /dev/null +++ b/tests_gui_tor/onionshare_share_mode_persistent_test.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + slug = '' + onion_host = '' + + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": True, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=6) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=8) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=9) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=10) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=11) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=12) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', False) + global slug + slug = self.gui.share_mode.server_status.web.slug + + @pytest.mark.run(order=13) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + global onion_host + onion_host = self.gui.app.onion_host + + @pytest.mark.run(order=14) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=15) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', True) + + @pytest.mark.run(order=16) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + @pytest.mark.run(order=17) + def test_server_status_indicator_says_closed(self): + CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + + @pytest.mark.run(order=18) + def test_server_started_again(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=19) + def test_have_same_slug(self): + '''Test that we have the same slug''' + self.assertEqual(self.gui.share_mode.server_status.web.slug, slug) + + @pytest.mark.run(order=20) + def test_have_same_onion(self): + '''Test that we have the same onion''' + self.assertEqual(self.gui.app.onion_host, onion_host) + + @pytest.mark.run(order=21) + def test_server_is_stopped_again(self): + CommonTests.test_server_is_stopped(self, 'share', True) + CommonTests.test_web_service_is_stopped(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_share_mode_stealth_test.py b/tests_gui_tor/onionshare_share_mode_stealth_test.py new file mode 100644 index 00000000..948e834a --- /dev/null +++ b/tests_gui_tor/onionshare_share_mode_stealth_test.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": True, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', False) + + @pytest.mark.run(order=18) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=19) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=20) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=21) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=22) + def test_copy_have_hidserv_auth_button(self): + CommonTests.test_copy_have_hidserv_auth_button(self, 'share') + + @pytest.mark.run(order=23) + def test_hidserv_auth_string(self): + CommonTests.test_hidserv_auth_string(self) + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py b/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py new file mode 100644 index 00000000..3eeea9bc --- /dev/null +++ b/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', False) + + @pytest.mark.run(order=18) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=19) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=20) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=21) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=22) + def test_tor_killed_statusbar_message_shown(self): + CommonTests.test_tor_killed_statusbar_message_shown(self, 'share') + + @pytest.mark.run(order=23) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', False) + + @pytest.mark.run(order=24) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_timer_test.py b/tests_gui_tor/onionshare_timer_test.py new file mode 100644 index 00000000..865b3a8b --- /dev/null +++ b/tests_gui_tor/onionshare_timer_test.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": True, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_set_timeout(self): + CommonTests.test_set_timeout(self, 'share', 120) + + @pytest.mark.run(order=9) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=10) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=11) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=12) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=13) + def test_timeout_widget_hidden(self): + CommonTests.test_timeout_widget_hidden(self, 'share') + + @pytest.mark.run(order=14) + def test_timeout(self): + CommonTests.test_server_timed_out(self, 'share', 125000) + + @pytest.mark.run(order=15) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/onionshare_tor_connection_killed_test.py b/tests_gui_tor/onionshare_tor_connection_killed_test.py new file mode 100644 index 00000000..3eeea9bc --- /dev/null +++ b/tests_gui_tor/onionshare_tor_connection_killed_test.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +import os +import sys +import unittest +import pytest +import json + +from PyQt5 import QtWidgets + +from onionshare.common import Common +from onionshare.web import Web +from onionshare import onion, strings +from onionshare_gui import * + +from .commontests import CommonTests + +app = QtWidgets.QApplication(sys.argv) + +class OnionShareGuiTest(unittest.TestCase): + '''Test the OnionShare GUI''' + @classmethod + def setUpClass(cls): + '''Create the GUI''' + # Create our test file + testfile = open('/tmp/test.txt', 'w') + testfile.write('onionshare') + testfile.close() + common = Common() + common.define_css() + + # Start the Onion + strings.load_strings(common) + + testonion = onion.Onion(common) + global qtapp + qtapp = Application(common) + app = OnionShare(common, testonion, False, 0) + + web = Web(common, False, True) + + test_settings = { + "auth_password": "", + "auth_type": "no_auth", + "autoupdate_timestamp": "", + "close_after_first_download": True, + "connection_type": "bundled", + "control_port_address": "127.0.0.1", + "control_port_port": 9051, + "downloads_dir": "/tmp/OnionShare", + "hidservauth_string": "", + "no_bridges": True, + "private_key": "", + "public_mode": False, + "receive_allow_receiver_shutdown": True, + "save_private_key": False, + "shutdown_timeout": False, + "slug": "", + "socks_address": "127.0.0.1", + "socks_port": 9050, + "socket_file_path": "/var/run/tor/control", + "systray_notifications": True, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_meek_lite_amazon": False, + "tor_bridges_use_custom_bridges": "", + "tor_bridges_use_obfs4": False, + "use_stealth": False, + "use_legacy_v2_onions": False, + "use_autoupdate": True, + "version": "1.3.1" + } + testsettings = '/tmp/testsettings.json' + open(testsettings, 'w').write(json.dumps(test_settings)) + + cls.gui = OnionShareGui(common, testonion, qtapp, app, ['/tmp/test.txt'], testsettings, False) + + @classmethod + def tearDownClass(cls): + '''Clean up after tests''' + os.remove('/tmp/test.txt') + + @pytest.mark.run(order=1) + def test_gui_loaded(self): + CommonTests.test_gui_loaded(self) + + @pytest.mark.run(order=2) + def test_windowTitle_seen(self): + CommonTests.test_windowTitle_seen(self) + + @pytest.mark.run(order=3) + def test_settings_button_is_visible(self): + CommonTests.test_settings_button_is_visible(self) + + @pytest.mark.run(order=4) + def test_server_status_bar_is_visible(self): + CommonTests.test_server_status_bar_is_visible(self) + + @pytest.mark.run(order=5) + def test_file_selection_widget_has_a_file(self): + CommonTests.test_file_selection_widget_has_a_file(self) + + @pytest.mark.run(order=6) + def test_info_widget_is_visible(self): + CommonTests.test_info_widget_is_visible(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_deleting_only_file_hides_delete_button(self): + CommonTests.test_deleting_only_file_hides_delete_button(self) + + @pytest.mark.run(order=9) + def test_add_a_file_and_delete_using_its_delete_widget(self): + CommonTests.test_add_a_file_and_delete_using_its_delete_widget(self) + + @pytest.mark.run(order=10) + def test_file_selection_widget_readd_files(self): + CommonTests.test_file_selection_widget_readd_files(self) + + @pytest.mark.run(order=11) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, 'share') + + @pytest.mark.run(order=12) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, 'share') + + @pytest.mark.run(order=13) + def test_add_delete_buttons_hidden(self): + CommonTests.test_add_delete_buttons_hidden(self) + + @pytest.mark.run(order=14) + def test_settings_button_is_hidden(self): + CommonTests.test_settings_button_is_hidden(self) + + @pytest.mark.run(order=15) + def test_a_server_is_started(self): + CommonTests.test_a_server_is_started(self, 'share') + + @pytest.mark.run(order=16) + def test_a_web_server_is_running(self): + CommonTests.test_a_web_server_is_running(self) + + @pytest.mark.run(order=17) + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, 'share', False) + + @pytest.mark.run(order=18) + def test_have_an_onion(self): + CommonTests.test_have_an_onion_service(self) + + @pytest.mark.run(order=19) + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, 'share') + + @pytest.mark.run(order=20) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, 'share') + + @pytest.mark.run(order=21) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, 'share') + + @pytest.mark.run(order=22) + def test_tor_killed_statusbar_message_shown(self): + CommonTests.test_tor_killed_statusbar_message_shown(self, 'share') + + @pytest.mark.run(order=23) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, 'share', False) + + @pytest.mark.run(order=24) + def test_web_service_is_stopped(self): + CommonTests.test_web_service_is_stopped(self) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests_gui_tor/run_unit_tests.sh b/tests_gui_tor/run_unit_tests.sh new file mode 100755 index 00000000..d15f8a6e --- /dev/null +++ b/tests_gui_tor/run_unit_tests.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +for test in `ls -1 | egrep ^onionshare_`; do + py.test-3 $test -vvv || exit 1 +done