diff --git a/onionshare/common.py b/onionshare/common.py index 28b282c2..cab1e747 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -211,6 +211,7 @@ class Common(object): color: #000000; padding: 10px; border: 1px solid #666666; + font-size: 12px; } """, @@ -248,11 +249,46 @@ class Common(object): border-radius: 5px; }""", + 'downloads_uploads_empty': """ + QWidget { + background-color: #ffffff; + border: 1px solid #999999; + } + QWidget QLabel { + background-color: none; + border: 0px; + } + """, + + 'downloads_uploads_empty_text': """ + QLabel { + color: #999999; + }""", + 'downloads_uploads_label': """ QLabel { font-weight: bold; font-size 14px; text-align: center; + background-color: none; + border: none; + }""", + + 'downloads_uploads_clear': """ + QPushButton { + color: #3f7fcf; + } + """, + + 'download_uploads_indicator': """ + QLabel { + color: #ffffff; + background-color: #f44449; + font-weight: bold; + font-size: 10px; + padding: 2px; + border-radius: 7px; + text-align: center; }""", 'downloads_uploads_progress_bar': """ @@ -261,7 +297,7 @@ class Common(object): background-color: #ffffff !important; text-align: center; color: #9b9b9b; - font-size: 12px; + font-size: 14px; } QProgressBar::chunk { background-color: #4e064f; diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode/__init__.py similarity index 93% rename from onionshare_gui/mode.py rename to onionshare_gui/mode/__init__.py index 6b156f7e..0971ff32 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode/__init__.py @@ -22,9 +22,9 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings from onionshare.common import ShutdownTimer -from .server_status import ServerStatus -from .threads import OnionThread -from .widgets import Alert +from ..server_status import ServerStatus +from ..threads import OnionThread +from ..widgets import Alert class Mode(QtWidgets.QWidget): """ @@ -49,8 +49,6 @@ class Mode(QtWidgets.QWidget): self.filenames = filenames - self.setMinimumWidth(450) - # The web object gets created in init() self.web = None @@ -72,24 +70,17 @@ class Mode(QtWidgets.QWidget): self.starting_server_step3.connect(self.start_server_step3) self.starting_server_error.connect(self.start_server_error) - # Primary action layout + # Primary action + # Note: It's up to the downstream Mode to add this to its layout self.primary_action_layout = QtWidgets.QVBoxLayout() self.primary_action_layout.addWidget(self.server_status) self.primary_action = QtWidgets.QWidget() self.primary_action.setLayout(self.primary_action_layout) - # Layout - self.layout = QtWidgets.QVBoxLayout() - self.layout.addWidget(self.primary_action) - # Hack to allow a minimum width on self.layout - min_width_widget = QtWidgets.QWidget() - min_width_widget.setMinimumWidth(450) - self.layout.addWidget(min_width_widget) - - self.horizontal_layout_wrapper = QtWidgets.QHBoxLayout() - self.horizontal_layout_wrapper.addLayout(self.layout) - - self.setLayout(self.horizontal_layout_wrapper) + # Hack to allow a minimum width on the main layout + # Note: It's up to the downstream Mode to add this to its layout + self.min_width_widget = QtWidgets.QWidget() + self.min_width_widget.setMinimumWidth(600) def init(self): """ diff --git a/onionshare_gui/mode/history.py b/onionshare_gui/mode/history.py new file mode 100644 index 00000000..8cfa0ed5 --- /dev/null +++ b/onionshare_gui/mode/history.py @@ -0,0 +1,553 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2018 Micah Lee + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" +import time +import subprocess +import os +from datetime import datetime +from PyQt5 import QtCore, QtWidgets, QtGui + +from onionshare import strings +from ..widgets import Alert + + +class HistoryItem(QtWidgets.QWidget): + """ + The base history item + """ + def __init__(self): + super(HistoryItem, self).__init__() + + def update(self): + pass + + def cancel(self): + pass + + +class DownloadHistoryItem(HistoryItem): + """ + Download history item, for share mode + """ + def __init__(self, common, id, total_bytes): + super(DownloadHistoryItem, self).__init__() + self.common = common + + self.id = id + self.total_bytes = total_bytes + self.downloaded_bytes = 0 + self.started = time.time() + self.started_dt = datetime.fromtimestamp(self.started) + + # Label + self.label = QtWidgets.QLabel(strings._('gui_download_in_progress').format(self.started_dt.strftime("%b %d, %I:%M%p"))) + + # Progress bar + self.progress_bar = QtWidgets.QProgressBar() + self.progress_bar.setTextVisible(True) + self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) + self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) + self.progress_bar.setMinimum(0) + self.progress_bar.setMaximum(total_bytes) + self.progress_bar.setValue(0) + self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) + self.progress_bar.total_bytes = total_bytes + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.progress_bar) + self.setLayout(layout) + + # Start at 0 + self.update(0) + + def update(self, downloaded_bytes): + self.downloaded_bytes = downloaded_bytes + + self.progress_bar.setValue(downloaded_bytes) + if downloaded_bytes == self.progress_bar.total_bytes: + pb_fmt = strings._('gui_download_upload_progress_complete').format( + self.common.format_seconds(time.time() - self.started)) + else: + elapsed = time.time() - self.started + if elapsed < 10: + # Wait a couple of seconds for the download rate to stabilize. + # This prevents a "Windows copy dialog"-esque experience at + # the beginning of the download. + pb_fmt = strings._('gui_download_upload_progress_starting').format( + self.common.human_readable_filesize(downloaded_bytes)) + else: + pb_fmt = strings._('gui_download_upload_progress_eta').format( + self.common.human_readable_filesize(downloaded_bytes), + self.estimated_time_remaining) + + self.progress_bar.setFormat(pb_fmt) + + def cancel(self): + self.progress_bar.setFormat(strings._('gui_canceled')) + + @property + def estimated_time_remaining(self): + return self.common.estimated_time_remaining(self.downloaded_bytes, + self.total_bytes, + self.started) + + +class UploadHistoryItemFile(QtWidgets.QWidget): + def __init__(self, common, filename): + super(UploadHistoryItemFile, self).__init__() + self.common = common + + self.common.log('UploadHistoryItemFile', '__init__', 'filename: {}'.format(filename)) + + self.filename = filename + self.started = datetime.now() + + # Filename label + self.filename_label = QtWidgets.QLabel(self.filename) + self.filename_label_width = self.filename_label.width() + + # File size label + self.filesize_label = QtWidgets.QLabel() + self.filesize_label.setStyleSheet(self.common.css['receive_file_size']) + self.filesize_label.hide() + + # Folder button + folder_pixmap = QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/open_folder.png'))) + folder_icon = QtGui.QIcon(folder_pixmap) + self.folder_button = QtWidgets.QPushButton() + self.folder_button.clicked.connect(self.open_folder) + self.folder_button.setIcon(folder_icon) + self.folder_button.setIconSize(folder_pixmap.rect().size()) + self.folder_button.setFlat(True) + self.folder_button.hide() + + # Layouts + layout = QtWidgets.QHBoxLayout() + layout.addWidget(self.filename_label) + layout.addWidget(self.filesize_label) + layout.addStretch() + layout.addWidget(self.folder_button) + self.setLayout(layout) + + def update(self, uploaded_bytes, complete): + self.filesize_label.setText(self.common.human_readable_filesize(uploaded_bytes)) + self.filesize_label.show() + + if complete: + self.folder_button.show() + + def rename(self, new_filename): + self.filename = new_filename + self.filename_label.setText(self.filename) + + def open_folder(self): + """ + Open the downloads folder, with the file selected, in a cross-platform manner + """ + self.common.log('UploadHistoryItemFile', 'open_folder') + + abs_filename = os.path.join(self.common.settings.get('downloads_dir'), self.filename) + + # Linux + if self.common.platform == 'Linux' or self.common.platform == 'BSD': + try: + # If nautilus is available, open it + subprocess.Popen(['nautilus', abs_filename]) + except: + Alert(self.common, strings._('gui_open_folder_error_nautilus').format(abs_filename)) + + # macOS + elif self.common.platform == 'Darwin': + # TODO: Implement opening folder with file selected in macOS + # This seems helpful: https://stackoverflow.com/questions/3520493/python-show-in-finder + self.common.log('UploadHistoryItemFile', 'open_folder', 'not implemented for Darwin yet') + + # Windows + elif self.common.platform == 'Windows': + # TODO: Implement opening folder with file selected in Windows + # This seems helpful: https://stackoverflow.com/questions/6631299/python-opening-a-folder-in-explorer-nautilus-mac-thingie + self.common.log('UploadHistoryItemFile', 'open_folder', 'not implemented for Windows yet') + + +class UploadHistoryItem(HistoryItem): + def __init__(self, common, id, content_length): + super(UploadHistoryItem, self).__init__() + self.common = common + self.id = id + self.content_length = content_length + self.started = datetime.now() + + # Label + self.label = QtWidgets.QLabel(strings._('gui_upload_in_progress', True).format(self.started.strftime("%b %d, %I:%M%p"))) + + # Progress bar + self.progress_bar = QtWidgets.QProgressBar() + self.progress_bar.setTextVisible(True) + self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) + self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) + self.progress_bar.setMinimum(0) + self.progress_bar.setValue(0) + self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) + + # This layout contains file widgets + self.files_layout = QtWidgets.QVBoxLayout() + self.files_layout.setContentsMargins(0, 0, 0, 0) + files_widget = QtWidgets.QWidget() + files_widget.setStyleSheet(self.common.css['receive_file']) + files_widget.setLayout(self.files_layout) + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.label) + layout.addWidget(self.progress_bar) + layout.addWidget(files_widget) + layout.addStretch() + self.setLayout(layout) + + # We're also making a dictionary of file widgets, to make them easier to access + self.files = {} + + def update(self, data): + """ + Using the progress from Web, update the progress bar and file size labels + for each file + """ + if data['action'] == 'progress': + total_uploaded_bytes = 0 + for filename in data['progress']: + total_uploaded_bytes += data['progress'][filename]['uploaded_bytes'] + + # Update the progress bar + self.progress_bar.setMaximum(self.content_length) + self.progress_bar.setValue(total_uploaded_bytes) + + elapsed = datetime.now() - self.started + if elapsed.seconds < 10: + pb_fmt = strings._('gui_download_upload_progress_starting').format( + self.common.human_readable_filesize(total_uploaded_bytes)) + else: + estimated_time_remaining = self.common.estimated_time_remaining( + total_uploaded_bytes, + self.content_length, + self.started.timestamp()) + pb_fmt = strings._('gui_download_upload_progress_eta').format( + self.common.human_readable_filesize(total_uploaded_bytes), + estimated_time_remaining) + + # Using list(progress) to avoid "RuntimeError: dictionary changed size during iteration" + for filename in list(data['progress']): + # Add a new file if needed + if filename not in self.files: + self.files[filename] = UploadHistoryItemFile(self.common, filename) + self.files_layout.addWidget(self.files[filename]) + + # Update the file + self.files[filename].update(data['progress'][filename]['uploaded_bytes'], data['progress'][filename]['complete']) + + elif data['action'] == 'rename': + self.files[data['old_filename']].rename(data['new_filename']) + self.files[data['new_filename']] = self.files.pop(data['old_filename']) + + elif data['action'] == 'finished': + # Hide the progress bar + self.progress_bar.hide() + + # Change the label + self.ended = self.started = datetime.now() + if self.started.year == self.ended.year and self.started.month == self.ended.month and self.started.day == self.ended.day: + if self.started.hour == self.ended.hour and self.started.minute == self.ended.minute: + text = strings._('gui_upload_finished', True).format( + self.started.strftime("%b %d, %I:%M%p") + ) + else: + text = strings._('gui_upload_finished_range', True).format( + self.started.strftime("%b %d, %I:%M%p"), + self.ended.strftime("%I:%M%p") + ) + else: + text = strings._('gui_upload_finished_range', True).format( + self.started.strftime("%b %d, %I:%M%p"), + self.ended.strftime("%b %d, %I:%M%p") + ) + self.label.setText(text) + + +class HistoryItemList(QtWidgets.QScrollArea): + """ + List of items + """ + def __init__(self, common): + super(HistoryItemList, self).__init__() + self.common = common + + self.items = {} + + # The layout that holds all of the items + self.items_layout = QtWidgets.QVBoxLayout() + self.items_layout.setContentsMargins(0, 0, 0, 0) + self.items_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + + # Wrapper layout that also contains a stretch + wrapper_layout = QtWidgets.QVBoxLayout() + wrapper_layout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize) + wrapper_layout.addLayout(self.items_layout) + wrapper_layout.addStretch() + + # The internal widget of the scroll area + widget = QtWidgets.QWidget() + widget.setLayout(wrapper_layout) + self.setWidget(widget) + self.setWidgetResizable(True) + + # Other scroll area settings + self.setBackgroundRole(QtGui.QPalette.Light) + self.verticalScrollBar().rangeChanged.connect(self.resizeScroll) + + def resizeScroll(self, minimum, maximum): + """ + Scroll to the bottom of the window when the range changes. + """ + self.verticalScrollBar().setValue(maximum) + + def add(self, id, item): + """ + Add a new item. Override this method. + """ + self.items[id] = item + self.items_layout.addWidget(item) + + def update(self, id, data): + """ + Update an item. Override this method. + """ + self.items[id].update(data) + + def cancel(self, id): + """ + Cancel an item. Override this method. + """ + self.items[id].cancel() + + def reset(self): + """ + Reset all items, emptying the list. Override this method. + """ + for item in self.items.values(): + self.items_layout.removeWidget(item) + item.close() + self.items = {} + + +class History(QtWidgets.QWidget): + """ + A history of what's happened so far in this mode. This contains an internal + object full of a scrollable list of items. + """ + def __init__(self, common, empty_image, empty_text, header_text): + super(History, self).__init__() + self.common = common + + self.setMinimumWidth(350) + + # In progress and completed counters + self.in_progress_count = 0 + self.completed_count = 0 + + # In progress and completed labels + self.in_progress_label = QtWidgets.QLabel() + self.in_progress_label.setStyleSheet(self.common.css['mode_info_label']) + self.completed_label = QtWidgets.QLabel() + self.completed_label.setStyleSheet(self.common.css['mode_info_label']) + + # Header + self.header_label = QtWidgets.QLabel(header_text) + self.header_label.setStyleSheet(self.common.css['downloads_uploads_label']) + clear_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) + clear_button.setStyleSheet(self.common.css['downloads_uploads_clear']) + clear_button.setFlat(True) + clear_button.clicked.connect(self.reset) + header_layout = QtWidgets.QHBoxLayout() + header_layout.addWidget(self.header_label) + header_layout.addStretch() + header_layout.addWidget(self.in_progress_label) + header_layout.addWidget(self.completed_label) + header_layout.addWidget(clear_button) + + # When there are no items + self.empty_image = QtWidgets.QLabel() + self.empty_image.setAlignment(QtCore.Qt.AlignCenter) + self.empty_image.setPixmap(empty_image) + self.empty_text = QtWidgets.QLabel(empty_text) + self.empty_text.setAlignment(QtCore.Qt.AlignCenter) + self.empty_text.setStyleSheet(self.common.css['downloads_uploads_empty_text']) + empty_layout = QtWidgets.QVBoxLayout() + empty_layout.addStretch() + empty_layout.addWidget(self.empty_image) + empty_layout.addWidget(self.empty_text) + empty_layout.addStretch() + self.empty = QtWidgets.QWidget() + self.empty.setStyleSheet(self.common.css['downloads_uploads_empty']) + self.empty.setLayout(empty_layout) + + # When there are items + self.item_list = HistoryItemList(self.common) + self.not_empty_layout = QtWidgets.QVBoxLayout() + self.not_empty_layout.addLayout(header_layout) + self.not_empty_layout.addWidget(self.item_list) + self.not_empty = QtWidgets.QWidget() + self.not_empty.setLayout(self.not_empty_layout) + + # Layout + layout = QtWidgets.QVBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(self.empty) + layout.addWidget(self.not_empty) + self.setLayout(layout) + + # Reset once at the beginning + self.reset() + + def add(self, id, item): + """ + Add a new item. + """ + self.common.log('History', 'add', 'id: {}, item: {}'.format(id, item)) + + # Hide empty, show not empty + self.empty.hide() + self.not_empty.show() + + # Add it to the list + self.item_list.add(id, item) + + def update(self, id, data): + """ + Update an item. + """ + self.item_list.update(id, data) + + def cancel(self, id): + """ + Cancel an item. + """ + self.item_list.cancel(id) + + def reset(self): + """ + Reset all items. + """ + self.item_list.reset() + + # Hide not empty, show empty + self.not_empty.hide() + self.empty.show() + + # Reset counters + self.completed_count = 0 + self.in_progress_count = 0 + self.update_completed() + self.update_in_progress() + + def update_completed(self): + """ + Update the 'completed' widget. + """ + if self.completed_count == 0: + image = self.common.get_resource_path('images/share_completed_none.png') + else: + image = self.common.get_resource_path('images/share_completed.png') + self.completed_label.setText(' {1:d}'.format(image, self.completed_count)) + self.completed_label.setToolTip(strings._('history_completed_tooltip').format(self.completed_count)) + + def update_in_progress(self): + """ + Update the 'in progress' widget. + """ + if self.in_progress_count == 0: + image = self.common.get_resource_path('images/share_in_progress_none.png') + else: + image = self.common.get_resource_path('images/share_in_progress.png') + self.in_progress_label.setText(' {1:d}'.format(image, self.in_progress_count)) + self.in_progress_label.setToolTip(strings._('history_in_progress_tooltip', True).format(self.in_progress_count)) + + +class ToggleHistory(QtWidgets.QPushButton): + """ + Widget for toggling showing or hiding the history, as well as keeping track + of the indicator counter if it's hidden + """ + def __init__(self, common, current_mode, history_widget, icon, selected_icon): + super(ToggleHistory, self).__init__() + self.common = common + self.current_mode = current_mode + self.history_widget = history_widget + self.icon = icon + self.selected_icon = selected_icon + + # Toggle button + self.setDefault(False) + self.setFixedWidth(35) + self.setFixedHeight(30) + self.setFlat(True) + self.setIcon(icon) + self.clicked.connect(self.toggle_clicked) + + # Keep track of indicator + self.indicator_count = 0 + self.indicator_label = QtWidgets.QLabel(parent=self) + self.indicator_label.setStyleSheet(self.common.css['download_uploads_indicator']) + self.update_indicator() + + def update_indicator(self, increment=False): + """ + Update the display of the indicator count. If increment is True, then + only increment the counter if Downloads is hidden. + """ + if increment and not self.history_widget.isVisible(): + self.indicator_count += 1 + + self.indicator_label.setText("{}".format(self.indicator_count)) + + if self.indicator_count == 0: + self.indicator_label.hide() + else: + size = self.indicator_label.sizeHint() + self.indicator_label.setGeometry(35-size.width(), 0, size.width(), size.height()) + self.indicator_label.show() + + def toggle_clicked(self): + """ + Toggle showing and hiding the history widget + """ + self.common.log('ToggleHistory', 'toggle_clicked') + + if self.history_widget.isVisible(): + self.history_widget.hide() + self.setIcon(self.icon) + self.setFlat(True) + else: + self.history_widget.show() + self.setIcon(self.selected_icon) + self.setFlat(False) + + # Reset the indicator count + self.indicator_count = 0 + self.update_indicator() diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/mode/receive_mode/__init__.py similarity index 52% rename from onionshare_gui/receive_mode/__init__.py rename to onionshare_gui/mode/receive_mode/__init__.py index 590dec65..b73acca2 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/mode/receive_mode/__init__.py @@ -22,8 +22,8 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings from onionshare.web import Web -from .uploads import Uploads -from ..mode import Mode +from ..history import History, ToggleHistory, UploadHistoryItem +from .. import Mode class ReceiveMode(Mode): """ @@ -46,41 +46,45 @@ class ReceiveMode(Mode): self.server_status.web = self.web self.server_status.update() - # Uploads - self.uploads = Uploads(self.common) - self.uploads_in_progress = 0 - self.uploads_completed = 0 - self.new_upload = False # For scrolling to the bottom of the uploads list + # Upload history + self.history = History( + self.common, + QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/uploads_transparent.png'))), + strings._('gui_no_uploads'), + strings._('gui_uploads') + ) + self.history.hide() - # Information about share, and show uploads button - self.info_in_progress_uploads_count = QtWidgets.QLabel() - self.info_in_progress_uploads_count.setStyleSheet(self.common.css['mode_info_label']) + # Toggle history + self.toggle_history = ToggleHistory( + self.common, self, self.history, + QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle.png')), + QtGui.QIcon(self.common.get_resource_path('images/uploads_toggle_selected.png')) + ) - self.info_completed_uploads_count = QtWidgets.QLabel() - self.info_completed_uploads_count.setStyleSheet(self.common.css['mode_info_label']) + # Receive mode warning + receive_warning = QtWidgets.QLabel(strings._('gui_receive_mode_warning', True)) + receive_warning.setMinimumHeight(80) + receive_warning.setWordWrap(True) - self.update_uploads_completed() - self.update_uploads_in_progress() + # Top bar + top_bar_layout = QtWidgets.QHBoxLayout() + top_bar_layout.addStretch() + top_bar_layout.addWidget(self.toggle_history) - self.info_layout = QtWidgets.QHBoxLayout() - self.info_layout.addStretch() - self.info_layout.addWidget(self.info_in_progress_uploads_count) - self.info_layout.addWidget(self.info_completed_uploads_count) + # Main layout + self.main_layout = QtWidgets.QVBoxLayout() + self.main_layout.addLayout(top_bar_layout) + self.main_layout.addWidget(receive_warning) + self.main_layout.addWidget(self.primary_action) + self.main_layout.addStretch() + self.main_layout.addWidget(self.min_width_widget) - self.info_widget = QtWidgets.QWidget() - self.info_widget.setLayout(self.info_layout) - self.info_widget.hide() - - # Receive mode info - self.receive_info = QtWidgets.QLabel(strings._('gui_receive_mode_warning', True)) - self.receive_info.setMinimumHeight(80) - self.receive_info.setWordWrap(True) - - # Layout - self.layout.insertWidget(0, self.receive_info) - self.layout.insertWidget(0, self.info_widget) - self.layout.addStretch() - self.horizontal_layout_wrapper.addWidget(self.uploads) + # Wrapper layout + self.wrapper_layout = QtWidgets.QHBoxLayout() + self.wrapper_layout.addLayout(self.main_layout) + self.wrapper_layout.addWidget(self.history) + self.setLayout(self.wrapper_layout) def get_stop_server_shutdown_timeout_text(self): """ @@ -119,7 +123,6 @@ class ReceiveMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - self.info_widget.hide() def handle_request_load(self, event): """ @@ -131,9 +134,11 @@ class ReceiveMode(Mode): """ Handle REQUEST_STARTED event. """ - self.uploads.add(event["data"]["id"], event["data"]["content_length"]) - self.uploads_in_progress += 1 - self.update_uploads_in_progress() + item = UploadHistoryItem(self.common, event["data"]["id"], event["data"]["content_length"]) + self.history.add(event["data"]["id"], item) + self.toggle_history.update_indicator(True) + self.history.in_progress_count += 1 + self.history.update_in_progress() self.system_tray.showMessage(strings._('systray_upload_started_title', True), strings._('systray_upload_started_message', True)) @@ -141,7 +146,10 @@ class ReceiveMode(Mode): """ Handle REQUEST_PROGRESS event. """ - self.uploads.update(event["data"]["id"], event["data"]["progress"]) + self.history.update(event["data"]["id"], { + 'action': 'progress', + 'progress': event["data"]["progress"] + }) def handle_request_close_server(self, event): """ @@ -154,67 +162,35 @@ class ReceiveMode(Mode): """ Handle REQUEST_UPLOAD_FILE_RENAMED event. """ - self.uploads.rename(event["data"]["id"], event["data"]["old_filename"], event["data"]["new_filename"]) + self.history.update(event["data"]["id"], { + 'action': 'rename', + 'old_filename': event["data"]["old_filename"], + 'new_filename': event["data"]["new_filename"] + }) def handle_request_upload_finished(self, event): """ Handle REQUEST_UPLOAD_FINISHED event. """ - self.uploads.finished(event["data"]["id"]) - # Update the total 'completed uploads' info - self.uploads_completed += 1 - self.update_uploads_completed() - # Update the 'in progress uploads' info - self.uploads_in_progress -= 1 - self.update_uploads_in_progress() + self.history.update(event["data"]["id"], { + 'action': 'finished' + }) + self.history.completed_count += 1 + self.history.in_progress_count -= 1 + self.history.update_completed() + self.history.update_in_progress() def on_reload_settings(self): """ We should be ok to re-enable the 'Start Receive Mode' button now. """ self.primary_action.show() - self.info_widget.show() def reset_info_counters(self): """ Set the info counters back to zero. """ - self.uploads_completed = 0 - self.uploads_in_progress = 0 - self.update_uploads_completed() - self.update_uploads_in_progress() - self.uploads.reset() - - def update_uploads_completed(self): - """ - Update the 'Uploads completed' info widget. - """ - if self.uploads_completed == 0: - image = self.common.get_resource_path('images/share_completed_none.png') - else: - image = self.common.get_resource_path('images/share_completed.png') - self.info_completed_uploads_count.setText(' {1:d}'.format(image, self.uploads_completed)) - self.info_completed_uploads_count.setToolTip(strings._('info_completed_uploads_tooltip', True).format(self.uploads_completed)) - - def update_uploads_in_progress(self): - """ - Update the 'Uploads in progress' info widget. - """ - if self.uploads_in_progress == 0: - image = self.common.get_resource_path('images/share_in_progress_none.png') - else: - image = self.common.get_resource_path('images/share_in_progress.png') - self.info_in_progress_uploads_count.setText(' {1:d}'.format(image, self.uploads_in_progress)) - self.info_in_progress_uploads_count.setToolTip(strings._('info_in_progress_uploads_tooltip', True).format(self.uploads_in_progress)) + self.history.reset() def update_primary_action(self): self.common.log('ReceiveMode', 'update_primary_action') - - # Show the info widget when the server is active - if self.server_status.status == self.server_status.STATUS_STARTED: - self.info_widget.show() - else: - self.info_widget.hide() - - # Resize window - self.adjustSize() diff --git a/onionshare_gui/share_mode/__init__.py b/onionshare_gui/mode/share_mode/__init__.py similarity index 73% rename from onionshare_gui/share_mode/__init__.py rename to onionshare_gui/mode/share_mode/__init__.py index 90fce49a..1c1f33ae 100644 --- a/onionshare_gui/share_mode/__init__.py +++ b/onionshare_gui/mode/share_mode/__init__.py @@ -26,10 +26,11 @@ from onionshare.common import Common from onionshare.web import Web from .file_selection import FileSelection -from .downloads import Downloads from .threads import CompressThread -from ..mode import Mode -from ..widgets import Alert +from .. import Mode +from ..history import History, ToggleHistory, DownloadHistoryItem +from ...widgets import Alert + class ShareMode(Mode): """ @@ -70,33 +71,31 @@ class ShareMode(Mode): self.filesize_warning.setStyleSheet(self.common.css['share_filesize_warning']) self.filesize_warning.hide() - # Downloads - self.downloads = Downloads(self.common) - self.downloads_in_progress = 0 - self.downloads_completed = 0 + # Download history + self.history = History( + self.common, + QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/downloads_transparent.png'))), + strings._('gui_no_downloads'), + strings._('gui_downloads') + ) + self.history.hide() - # Information about share, and show downloads button + # Info label self.info_label = QtWidgets.QLabel() - self.info_label.setStyleSheet(self.common.css['mode_info_label']) + self.info_label.hide() - self.info_in_progress_downloads_count = QtWidgets.QLabel() - self.info_in_progress_downloads_count.setStyleSheet(self.common.css['mode_info_label']) + # Toggle history + self.toggle_history = ToggleHistory( + self.common, self, self.history, + QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle.png')), + QtGui.QIcon(self.common.get_resource_path('images/downloads_toggle_selected.png')) + ) - self.info_completed_downloads_count = QtWidgets.QLabel() - self.info_completed_downloads_count.setStyleSheet(self.common.css['mode_info_label']) - - self.update_downloads_completed() - self.update_downloads_in_progress() - - self.info_layout = QtWidgets.QHBoxLayout() - self.info_layout.addWidget(self.info_label) - self.info_layout.addStretch() - self.info_layout.addWidget(self.info_in_progress_downloads_count) - self.info_layout.addWidget(self.info_completed_downloads_count) - - self.info_widget = QtWidgets.QWidget() - self.info_widget.setLayout(self.info_layout) - self.info_widget.hide() + # Top bar + top_bar_layout = QtWidgets.QHBoxLayout() + top_bar_layout.addWidget(self.info_label) + top_bar_layout.addStretch() + top_bar_layout.addWidget(self.toggle_history) # Primary action layout self.primary_action_layout.addWidget(self.filesize_warning) @@ -106,10 +105,18 @@ class ShareMode(Mode): # Status bar, zip progress bar self._zip_progress_bar = None - # Layout - self.layout.insertLayout(0, self.file_selection) - self.layout.insertWidget(0, self.info_widget) - self.horizontal_layout_wrapper.addWidget(self.downloads) + # Main layout + self.main_layout = QtWidgets.QVBoxLayout() + self.main_layout.addLayout(top_bar_layout) + self.main_layout.addLayout(self.file_selection) + self.main_layout.addWidget(self.primary_action) + self.main_layout.addWidget(self.min_width_widget) + + # Wrapper layout + self.wrapper_layout = QtWidgets.QHBoxLayout() + self.wrapper_layout.addLayout(self.main_layout) + self.wrapper_layout.addWidget(self.history) + self.setLayout(self.wrapper_layout) # Always start with focus on file selection self.file_selection.setFocus() @@ -199,9 +206,9 @@ class ShareMode(Mode): self._zip_progress_bar = None self.filesize_warning.hide() - self.downloads_in_progress = 0 - self.downloads_completed = 0 - self.update_downloads_in_progress() + self.history.in_progress_count = 0 + self.history.completed_count = 0 + self.history.update_in_progress() self.file_selection.file_list.adjustSize() def cancel_server_custom(self): @@ -209,7 +216,7 @@ class ShareMode(Mode): Stop the compression thread on cancel """ if self.compress_thread: - self.common.log('OnionShareGui', 'cancel_server: quitting compress thread') + self.common.log('ShareMode', 'cancel_server: quitting compress thread') self.compress_thread.quit() def handle_tor_broke_custom(self): @@ -217,7 +224,6 @@ class ShareMode(Mode): Connection to Tor broke. """ self.primary_action.hide() - self.info_widget.hide() def handle_request_load(self, event): """ @@ -233,9 +239,12 @@ class ShareMode(Mode): filesize = self.web.share_mode.gzip_filesize else: filesize = self.web.share_mode.download_filesize - self.downloads.add(event["data"]["id"], filesize) - self.downloads_in_progress += 1 - self.update_downloads_in_progress() + + item = DownloadHistoryItem(self.common, event["data"]["id"], filesize) + self.history.add(event["data"]["id"], item) + self.toggle_history.update_indicator(True) + self.history.in_progress_count += 1 + self.history.update_in_progress() self.system_tray.showMessage(strings._('systray_download_started_title', True), strings._('systray_download_started_message', True)) @@ -243,18 +252,17 @@ class ShareMode(Mode): """ Handle REQUEST_PROGRESS event. """ - self.downloads.update(event["data"]["id"], event["data"]["bytes"]) + self.history.update(event["data"]["id"], event["data"]["bytes"]) # Is the download complete? if event["data"]["bytes"] == self.web.share_mode.filesize: self.system_tray.showMessage(strings._('systray_download_completed_title', True), strings._('systray_download_completed_message', True)) - # Update the total 'completed downloads' info - self.downloads_completed += 1 - self.update_downloads_completed() - # Update the 'in progress downloads' info - self.downloads_in_progress -= 1 - self.update_downloads_in_progress() + # Update completed and in progress labels + self.history.completed_count += 1 + self.history.in_progress_count -= 1 + self.history.update_completed() + self.history.update_in_progress() # Close on finish? if self.common.settings.get('close_after_first_download'): @@ -263,19 +271,19 @@ class ShareMode(Mode): self.server_status_label.setText(strings._('closing_automatically', True)) else: if self.server_status.status == self.server_status.STATUS_STOPPED: - self.downloads.cancel(event["data"]["id"]) - self.downloads_in_progress = 0 - self.update_downloads_in_progress() + self.history.cancel(event["data"]["id"]) + self.history.in_progress_count = 0 + self.history.update_in_progress() def handle_request_canceled(self, event): """ Handle REQUEST_CANCELED event. """ - self.downloads.cancel(event["data"]["id"]) + self.history.cancel(event["data"]["id"]) - # Update the 'in progress downloads' info - self.downloads_in_progress -= 1 - self.update_downloads_in_progress() + # Update in progress count + self.history.in_progress_count -= 1 + self.history.update_in_progress() self.system_tray.showMessage(strings._('systray_download_canceled_title', True), strings._('systray_download_canceled_message', True)) def on_reload_settings(self): @@ -285,14 +293,16 @@ class ShareMode(Mode): """ if self.server_status.file_selection.get_num_files() > 0: self.primary_action.show() - self.info_widget.show() + self.info_label.show() def update_primary_action(self): + self.common.log('ShareMode', 'update_primary_action') + # Show or hide primary action layout file_count = self.file_selection.file_list.count() if file_count > 0: self.primary_action.show() - self.info_widget.show() + self.info_label.show() # Update the file count in the info label total_size_bytes = 0 @@ -308,42 +318,13 @@ class ShareMode(Mode): else: self.primary_action.hide() - self.info_widget.hide() - - # Resize window - self.adjustSize() + self.info_label.hide() def reset_info_counters(self): """ Set the info counters back to zero. """ - self.downloads_completed = 0 - self.downloads_in_progress = 0 - self.update_downloads_completed() - self.update_downloads_in_progress() - self.downloads.reset() - - def update_downloads_completed(self): - """ - Update the 'Downloads completed' info widget. - """ - if self.downloads_completed == 0: - image = self.common.get_resource_path('images/share_completed_none.png') - else: - image = self.common.get_resource_path('images/share_completed.png') - self.info_completed_downloads_count.setText(' {1:d}'.format(image, self.downloads_completed)) - self.info_completed_downloads_count.setToolTip(strings._('info_completed_downloads_tooltip', True).format(self.downloads_completed)) - - def update_downloads_in_progress(self): - """ - Update the 'Downloads in progress' info widget. - """ - if self.downloads_in_progress == 0: - image = self.common.get_resource_path('images/share_in_progress_none.png') - else: - image = self.common.get_resource_path('images/share_in_progress.png') - self.info_in_progress_downloads_count.setText(' {1:d}'.format(image, self.downloads_in_progress)) - self.info_in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(self.downloads_in_progress)) + self.history.reset() @staticmethod def _compute_total_size(filenames): diff --git a/onionshare_gui/share_mode/file_selection.py b/onionshare_gui/mode/share_mode/file_selection.py similarity index 98% rename from onionshare_gui/share_mode/file_selection.py rename to onionshare_gui/mode/share_mode/file_selection.py index 628ad5ef..6bfa7dbf 100644 --- a/onionshare_gui/share_mode/file_selection.py +++ b/onionshare_gui/mode/share_mode/file_selection.py @@ -22,7 +22,7 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings -from ..widgets import Alert, AddFileDialog +from ...widgets import Alert, AddFileDialog class DropHereLabel(QtWidgets.QLabel): """ @@ -89,7 +89,7 @@ class FileList(QtWidgets.QListWidget): self.setAcceptDrops(True) self.setIconSize(QtCore.QSize(32, 32)) self.setSortingEnabled(True) - self.setMinimumHeight(205) + self.setMinimumHeight(160) self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.drop_here_image = DropHereLabel(self.common, self, True) self.drop_here_text = DropHereLabel(self.common, self, False) @@ -261,6 +261,7 @@ class FileList(QtWidgets.QListWidget): # Item info widget, with a white background item_info_layout = QtWidgets.QHBoxLayout() + item_info_layout.setContentsMargins(0, 0, 0, 0) item_info_layout.addWidget(item_size) item_info_layout.addWidget(item.item_button) item_info = QtWidgets.QWidget() diff --git a/onionshare_gui/share_mode/threads.py b/onionshare_gui/mode/share_mode/threads.py similarity index 100% rename from onionshare_gui/share_mode/threads.py rename to onionshare_gui/mode/share_mode/threads.py diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 83f3a7e0..c2e6657b 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -23,8 +23,8 @@ from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings from onionshare.web import Web -from .share_mode import ShareMode -from .receive_mode import ReceiveMode +from .mode.share_mode import ShareMode +from .mode.receive_mode import ReceiveMode from .tor_connection_dialog import TorConnectionDialog from .settings_dialog import SettingsDialog @@ -45,6 +45,8 @@ class OnionShareGui(QtWidgets.QMainWindow): self.common = common self.common.log('OnionShareGui', '__init__') + self.setMinimumWidth(820) + self.setMinimumHeight(660) self.onion = onion self.qtapp = qtapp @@ -55,7 +57,6 @@ class OnionShareGui(QtWidgets.QMainWindow): self.setWindowTitle('OnionShare') self.setWindowIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png'))) - self.setMinimumWidth(850) # Load settings self.config = config @@ -66,7 +67,7 @@ class OnionShareGui(QtWidgets.QMainWindow): self.settings_action = menu.addAction(strings._('gui_settings_window_title', True)) self.settings_action.triggered.connect(self.open_settings) help_action = menu.addAction(strings._('gui_settings_button_help', True)) - help_action.triggered.connect(SettingsDialog.help_clicked) + help_action.triggered.connect(SettingsDialog.open_help) exit_action = menu.addAction(strings._('systray_menu_exit', True)) exit_action.triggered.connect(self.close) @@ -153,7 +154,7 @@ class OnionShareGui(QtWidgets.QMainWindow): # Layouts contents_layout = QtWidgets.QVBoxLayout() - contents_layout.setContentsMargins(10, 10, 10, 10) + contents_layout.setContentsMargins(10, 0, 10, 0) contents_layout.addWidget(self.receive_mode) contents_layout.addWidget(self.share_mode) @@ -194,8 +195,8 @@ class OnionShareGui(QtWidgets.QMainWindow): self.share_mode_button.setStyleSheet(self.common.css['mode_switcher_selected_style']) self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) - self.share_mode.show() self.receive_mode.hide() + self.share_mode.show() else: self.share_mode_button.setStyleSheet(self.common.css['mode_switcher_unselected_style']) self.receive_mode_button.setStyleSheet(self.common.css['mode_switcher_selected_style']) diff --git a/onionshare_gui/receive_mode/uploads.py b/onionshare_gui/receive_mode/uploads.py deleted file mode 100644 index 48574cc7..00000000 --- a/onionshare_gui/receive_mode/uploads.py +++ /dev/null @@ -1,320 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" -import os -import subprocess -import textwrap -from datetime import datetime -from PyQt5 import QtCore, QtWidgets, QtGui - -from onionshare import strings -from ..widgets import Alert - - -class File(QtWidgets.QWidget): - def __init__(self, common, filename): - super(File, self).__init__() - self.common = common - - self.common.log('File', '__init__', 'filename: {}'.format(filename)) - - self.filename = filename - self.started = datetime.now() - - # Filename label - self.filename_label = QtWidgets.QLabel(self.filename) - self.filename_label_width = self.filename_label.width() - - # File size label - self.filesize_label = QtWidgets.QLabel() - self.filesize_label.setStyleSheet(self.common.css['receive_file_size']) - self.filesize_label.hide() - - # Folder button - folder_pixmap = QtGui.QPixmap.fromImage(QtGui.QImage(self.common.get_resource_path('images/open_folder.png'))) - folder_icon = QtGui.QIcon(folder_pixmap) - self.folder_button = QtWidgets.QPushButton() - self.folder_button.clicked.connect(self.open_folder) - self.folder_button.setIcon(folder_icon) - self.folder_button.setIconSize(folder_pixmap.rect().size()) - self.folder_button.setFlat(True) - self.folder_button.hide() - - # Layouts - layout = QtWidgets.QHBoxLayout() - layout.addWidget(self.filename_label) - layout.addWidget(self.filesize_label) - layout.addStretch() - layout.addWidget(self.folder_button) - self.setLayout(layout) - - def update(self, uploaded_bytes, complete): - self.filesize_label.setText(self.common.human_readable_filesize(uploaded_bytes)) - self.filesize_label.show() - - if complete: - self.folder_button.show() - - def rename(self, new_filename): - self.filename = new_filename - self.filename_label.setText(self.filename) - - def open_folder(self): - """ - Open the downloads folder, with the file selected, in a cross-platform manner - """ - self.common.log('File', 'open_folder') - - abs_filename = os.path.join(self.common.settings.get('downloads_dir'), self.filename) - - # Linux - if self.common.platform == 'Linux' or self.common.platform == 'BSD': - try: - # If nautilus is available, open it - subprocess.Popen(['nautilus', abs_filename]) - except: - Alert(self.common, strings._('gui_open_folder_error_nautilus').format(abs_filename)) - - # macOS - elif self.common.platform == 'Darwin': - # TODO: Implement opening folder with file selected in macOS - # This seems helpful: https://stackoverflow.com/questions/3520493/python-show-in-finder - self.common.log('File', 'open_folder', 'not implemented for Darwin yet') - - # Windows - elif self.common.platform == 'Windows': - # TODO: Implement opening folder with file selected in Windows - # This seems helpful: https://stackoverflow.com/questions/6631299/python-opening-a-folder-in-explorer-nautilus-mac-thingie - self.common.log('File', 'open_folder', 'not implemented for Windows yet') - - -class Upload(QtWidgets.QWidget): - def __init__(self, common, upload_id, content_length): - super(Upload, self).__init__() - self.common = common - self.upload_id = upload_id - self.content_length = content_length - self.started = datetime.now() - - # Label - self.label = QtWidgets.QLabel(strings._('gui_upload_in_progress', True).format(self.started.strftime("%b %d, %I:%M%p"))) - - # Progress bar - self.progress_bar = QtWidgets.QProgressBar() - self.progress_bar.setTextVisible(True) - self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) - self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) - self.progress_bar.setMinimum(0) - self.progress_bar.setValue(0) - self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) - - # This layout contains file widgets - self.files_layout = QtWidgets.QVBoxLayout() - self.files_layout.setContentsMargins(0, 0, 0, 0) - files_widget = QtWidgets.QWidget() - files_widget.setStyleSheet(self.common.css['receive_file']) - files_widget.setLayout(self.files_layout) - - # Layout - layout = QtWidgets.QVBoxLayout() - layout.addWidget(self.label) - layout.addWidget(self.progress_bar) - layout.addWidget(files_widget) - layout.addStretch() - self.setLayout(layout) - - # We're also making a dictionary of file widgets, to make them easier to access - self.files = {} - - def update(self, progress): - """ - Using the progress from Web, update the progress bar and file size labels - for each file - """ - total_uploaded_bytes = 0 - for filename in progress: - total_uploaded_bytes += progress[filename]['uploaded_bytes'] - - # Update the progress bar - self.progress_bar.setMaximum(self.content_length) - self.progress_bar.setValue(total_uploaded_bytes) - - elapsed = datetime.now() - self.started - if elapsed.seconds < 10: - pb_fmt = strings._('gui_download_upload_progress_starting').format( - self.common.human_readable_filesize(total_uploaded_bytes)) - else: - estimated_time_remaining = self.common.estimated_time_remaining( - total_uploaded_bytes, - self.content_length, - self.started.timestamp()) - pb_fmt = strings._('gui_download_upload_progress_eta').format( - self.common.human_readable_filesize(total_uploaded_bytes), - estimated_time_remaining) - - # Using list(progress) to avoid "RuntimeError: dictionary changed size during iteration" - for filename in list(progress): - # Add a new file if needed - if filename not in self.files: - self.files[filename] = File(self.common, filename) - self.files_layout.addWidget(self.files[filename]) - - # Update the file - self.files[filename].update(progress[filename]['uploaded_bytes'], progress[filename]['complete']) - - def rename(self, old_filename, new_filename): - self.files[old_filename].rename(new_filename) - self.files[new_filename] = self.files.pop(old_filename) - - def finished(self): - # Hide the progress bar - self.progress_bar.hide() - - # Change the label - self.ended = self.started = datetime.now() - if self.started.year == self.ended.year and self.started.month == self.ended.month and self.started.day == self.ended.day: - if self.started.hour == self.ended.hour and self.started.minute == self.ended.minute: - text = strings._('gui_upload_finished', True).format( - self.started.strftime("%b %d, %I:%M%p") - ) - else: - text = strings._('gui_upload_finished_range', True).format( - self.started.strftime("%b %d, %I:%M%p"), - self.ended.strftime("%I:%M%p") - ) - else: - text = strings._('gui_upload_finished_range', True).format( - self.started.strftime("%b %d, %I:%M%p"), - self.ended.strftime("%b %d, %I:%M%p") - ) - self.label.setText(text) - - -class Uploads(QtWidgets.QScrollArea): - """ - The uploads chunk of the GUI. This lists all of the active upload - progress bars, as well as information about each upload. - """ - def __init__(self, common): - super(Uploads, self).__init__() - self.common = common - self.common.log('Uploads', '__init__') - - self.resizeEvent = None - - self.uploads = {} - - self.setWindowTitle(strings._('gui_uploads', True)) - self.setWidgetResizable(True) - self.setMinimumHeight(150) - self.setMinimumWidth(350) - self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) - self.setWindowFlags(QtCore.Qt.Sheet | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.CustomizeWindowHint) - self.vbar = self.verticalScrollBar() - self.vbar.rangeChanged.connect(self.resizeScroll) - - uploads_label = QtWidgets.QLabel(strings._('gui_uploads', True)) - uploads_label.setStyleSheet(self.common.css['downloads_uploads_label']) - self.no_uploads_label = QtWidgets.QLabel(strings._('gui_no_uploads', True)) - self.clear_history_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) - self.clear_history_button.clicked.connect(self.reset) - self.clear_history_button.hide() - - - self.uploads_layout = QtWidgets.QVBoxLayout() - - widget = QtWidgets.QWidget() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(uploads_label) - layout.addWidget(self.no_uploads_label) - layout.addWidget(self.clear_history_button) - layout.addLayout(self.uploads_layout) - layout.addStretch() - widget.setLayout(layout) - self.setWidget(widget) - - def resizeScroll(self, minimum, maximum): - """ - Scroll to the bottom of the window when the range changes. - """ - self.vbar.setValue(maximum) - - def add(self, upload_id, content_length): - """ - Add a new upload. - """ - self.common.log('Uploads', 'add', 'upload_id: {}, content_length: {}'.format(upload_id, content_length)) - # Hide the no_uploads_label - self.no_uploads_label.hide() - # Show the clear_history_button - self.clear_history_button.show() - - # Add it to the list - upload = Upload(self.common, upload_id, content_length) - self.uploads[upload_id] = upload - self.uploads_layout.addWidget(upload) - - def update(self, upload_id, progress): - """ - Update the progress of an upload. - """ - self.uploads[upload_id].update(progress) - - def rename(self, upload_id, old_filename, new_filename): - """ - Rename a file, which happens if the filename already exists in downloads_dir. - """ - self.uploads[upload_id].rename(old_filename, new_filename) - - def finished(self, upload_id): - """ - An upload has finished. - """ - self.uploads[upload_id].finished() - - def cancel(self, upload_id): - """ - Update an upload progress bar to show that it has been canceled. - """ - self.common.log('Uploads', 'cancel', 'upload_id: {}'.format(upload_id)) - self.uploads[upload_id].cancel() - - def reset(self): - """ - Reset the uploads back to zero - """ - self.common.log('Uploads', 'reset') - for upload in self.uploads.values(): - upload.close() - self.uploads_layout.removeWidget(upload) - self.uploads = {} - - self.no_uploads_label.show() - self.clear_history_button.hide() - self.resize(self.sizeHint()) - - def resizeEvent(self, event): - width = self.frameGeometry().width() - try: - for upload in self.uploads.values(): - for item in upload.files.values(): - item.filename_label.setText(textwrap.fill(item.filename, 30)) - item.adjustSize() - except: - pass diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py index 32135ca4..0267d826 100644 --- a/onionshare_gui/server_status.py +++ b/onionshare_gui/server_status.py @@ -90,20 +90,20 @@ class ServerStatus(QtWidgets.QWidget): self.server_button.clicked.connect(self.server_button_clicked) # URL layout - url_font = QtGui.QFont() + url_font = QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont) self.url_description = QtWidgets.QLabel() self.url_description.setWordWrap(True) self.url_description.setMinimumHeight(50) self.url = QtWidgets.QLabel() self.url.setFont(url_font) self.url.setWordWrap(True) - self.url.setMinimumHeight(65) self.url.setMinimumSize(self.url.sizeHint()) self.url.setStyleSheet(self.common.css['server_status_url']) self.copy_url_button = QtWidgets.QPushButton(strings._('gui_copy_url', True)) self.copy_url_button.setFlat(True) self.copy_url_button.setStyleSheet(self.common.css['server_status_url_buttons']) + self.copy_url_button.setMinimumHeight(65) self.copy_url_button.clicked.connect(self.copy_url) self.copy_hidservauth_button = QtWidgets.QPushButton(strings._('gui_copy_hidservauth', True)) self.copy_hidservauth_button.setFlat(True) @@ -142,12 +142,12 @@ class ServerStatus(QtWidgets.QWidget): When the widget is resized, try and adjust the display of a v3 onion URL. """ try: - self.get_url() + # Wrap the URL label url_length=len(self.get_url()) if url_length > 60: width = self.frameGeometry().width() if width < 530: - wrapped_onion_url = textwrap.fill(self.get_url(), 50) + wrapped_onion_url = textwrap.fill(self.get_url(), 46) self.url.setText(wrapped_onion_url) else: self.url.setText(self.get_url()) diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 3cd25d31..39f08128 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -883,8 +883,12 @@ class SettingsDialog(QtWidgets.QDialog): Help button clicked. """ self.common.log('SettingsDialog', 'help_clicked') - help_site = 'https://github.com/micahflee/onionshare/wiki' - QtGui.QDesktopServices.openUrl(QtCore.QUrl(help_site)) + SettingsDialog.open_help() + + @staticmethod + def open_help(): + help_url = 'https://github.com/micahflee/onionshare/wiki' + QtGui.QDesktopServices.openUrl(QtCore.QUrl(help_url)) def settings_from_fields(self): """ diff --git a/onionshare_gui/share_mode/downloads.py b/onionshare_gui/share_mode/downloads.py deleted file mode 100644 index a34796f1..00000000 --- a/onionshare_gui/share_mode/downloads.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" -import time -from PyQt5 import QtCore, QtWidgets, QtGui - -from onionshare import strings - - -class Download(object): - def __init__(self, common, download_id, total_bytes): - self.common = common - - self.download_id = download_id - self.started = time.time() - self.total_bytes = total_bytes - self.downloaded_bytes = 0 - - # Progress bar - self.progress_bar = QtWidgets.QProgressBar() - self.progress_bar.setTextVisible(True) - self.progress_bar.setAttribute(QtCore.Qt.WA_DeleteOnClose) - self.progress_bar.setAlignment(QtCore.Qt.AlignHCenter) - self.progress_bar.setMinimum(0) - self.progress_bar.setMaximum(total_bytes) - self.progress_bar.setValue(0) - self.progress_bar.setStyleSheet(self.common.css['downloads_uploads_progress_bar']) - self.progress_bar.total_bytes = total_bytes - - # Start at 0 - self.update(0) - - def update(self, downloaded_bytes): - self.downloaded_bytes = downloaded_bytes - - self.progress_bar.setValue(downloaded_bytes) - if downloaded_bytes == self.progress_bar.total_bytes: - pb_fmt = strings._('gui_download_upload_progress_complete').format( - self.common.format_seconds(time.time() - self.started)) - else: - elapsed = time.time() - self.started - if elapsed < 10: - # Wait a couple of seconds for the download rate to stabilize. - # This prevents a "Windows copy dialog"-esque experience at - # the beginning of the download. - pb_fmt = strings._('gui_download_upload_progress_starting').format( - self.common.human_readable_filesize(downloaded_bytes)) - else: - pb_fmt = strings._('gui_download_upload_progress_eta').format( - self.common.human_readable_filesize(downloaded_bytes), - self.estimated_time_remaining) - - self.progress_bar.setFormat(pb_fmt) - - def cancel(self): - self.progress_bar.setFormat(strings._('gui_canceled')) - - @property - def estimated_time_remaining(self): - return self.common.estimated_time_remaining(self.downloaded_bytes, - self.total_bytes, - self.started) - - -class Downloads(QtWidgets.QScrollArea): - """ - The downloads chunk of the GUI. This lists all of the active download - progress bars. - """ - def __init__(self, common): - super(Downloads, self).__init__() - self.common = common - - self.downloads = {} - - self.setWindowTitle(strings._('gui_downloads', True)) - self.setWidgetResizable(True) - self.setMinimumHeight(150) - self.setMinimumWidth(350) - self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png'))) - self.setWindowFlags(QtCore.Qt.Sheet | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.CustomizeWindowHint) - self.vbar = self.verticalScrollBar() - self.vbar.rangeChanged.connect(self.resizeScroll) - - downloads_label = QtWidgets.QLabel(strings._('gui_downloads', True)) - downloads_label.setStyleSheet(self.common.css['downloads_uploads_label']) - self.no_downloads_label = QtWidgets.QLabel(strings._('gui_no_downloads', True)) - self.clear_history_button = QtWidgets.QPushButton(strings._('gui_clear_history', True)) - self.clear_history_button.clicked.connect(self.reset) - self.clear_history_button.hide() - - self.downloads_layout = QtWidgets.QVBoxLayout() - - widget = QtWidgets.QWidget() - layout = QtWidgets.QVBoxLayout() - layout.addWidget(downloads_label) - layout.addWidget(self.no_downloads_label) - layout.addWidget(self.clear_history_button) - layout.addLayout(self.downloads_layout) - layout.addStretch() - widget.setLayout(layout) - self.setWidget(widget) - - def resizeScroll(self, minimum, maximum): - """ - Scroll to the bottom of the window when the range changes. - """ - self.vbar.setValue(maximum) - - def add(self, download_id, total_bytes): - """ - Add a new download progress bar. - """ - # Hide the no_downloads_label - self.no_downloads_label.hide() - # Show the clear_history_button - self.clear_history_button.show() - - # Add it to the list - download = Download(self.common, download_id, total_bytes) - self.downloads[download_id] = download - self.downloads_layout.addWidget(download.progress_bar) - - def update(self, download_id, downloaded_bytes): - """ - Update the progress of a download progress bar. - """ - self.downloads[download_id].update(downloaded_bytes) - - def cancel(self, download_id): - """ - Update a download progress bar to show that it has been canceled. - """ - self.downloads[download_id].cancel() - - def reset(self): - """ - Reset the downloads back to zero - """ - for download in self.downloads.values(): - self.downloads_layout.removeWidget(download.progress_bar) - download.progress_bar.close() - self.downloads = {} - - self.no_downloads_label.show() - self.clear_history_button.hide() - self.resize(self.sizeHint()) diff --git a/setup.py b/setup.py index 94213f7c..86b71f82 100644 --- a/setup.py +++ b/setup.py @@ -69,8 +69,9 @@ setup( 'onionshare', 'onionshare.web', 'onionshare_gui', - 'onionshare_gui.share_mode', - 'onionshare_gui.receive_mode' + 'onionshare_gui.mode', + 'onionshare_gui.mode.share_mode', + 'onionshare_gui.mode.receive_mode' ], include_package_data=True, scripts=['install/scripts/onionshare', 'install/scripts/onionshare-gui'], diff --git a/share/images/downloads.png b/share/images/downloads.png new file mode 100644 index 00000000..ad879b6e Binary files /dev/null and b/share/images/downloads.png differ diff --git a/share/images/downloads_toggle.png b/share/images/downloads_toggle.png new file mode 100644 index 00000000..846ececb Binary files /dev/null and b/share/images/downloads_toggle.png differ diff --git a/share/images/downloads_toggle_selected.png b/share/images/downloads_toggle_selected.png new file mode 100644 index 00000000..127ce208 Binary files /dev/null and b/share/images/downloads_toggle_selected.png differ diff --git a/share/images/downloads_transparent.png b/share/images/downloads_transparent.png new file mode 100644 index 00000000..99207097 Binary files /dev/null and b/share/images/downloads_transparent.png differ diff --git a/share/images/uploads.png b/share/images/uploads.png new file mode 100644 index 00000000..cd9bd98e Binary files /dev/null and b/share/images/uploads.png differ diff --git a/share/images/uploads_toggle.png b/share/images/uploads_toggle.png new file mode 100644 index 00000000..87303c9f Binary files /dev/null and b/share/images/uploads_toggle.png differ diff --git a/share/images/uploads_toggle_selected.png b/share/images/uploads_toggle_selected.png new file mode 100644 index 00000000..0ba52cff Binary files /dev/null and b/share/images/uploads_toggle_selected.png differ diff --git a/share/images/uploads_transparent.png b/share/images/uploads_transparent.png new file mode 100644 index 00000000..3648c3fb Binary files /dev/null and b/share/images/uploads_transparent.png differ diff --git a/share/locale/en.json b/share/locale/en.json index 0f0f0cf4..e5d9a3be 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -46,7 +46,7 @@ "gui_copy_url": "Copy Address", "gui_copy_hidservauth": "Copy HidServAuth", "gui_downloads": "Download History", - "gui_no_downloads": "No downloads yet.", + "gui_no_downloads": "No Downloads Yet", "gui_canceled": "Canceled", "gui_copied_url_title": "Copied OnionShare Address", "gui_copied_url": "OnionShare address copied to clipboard", @@ -151,8 +151,8 @@ "gui_status_indicator_receive_started": "Receiving", "gui_file_info": "{} files, {}", "gui_file_info_single": "{} file, {}", - "info_in_progress_downloads_tooltip": "{} download(s) in progress", - "info_completed_downloads_tooltip": "{} download(s) completed", + "history_in_progress_tooltip": "{} in progress", + "history_completed_tooltip": "{} completed", "info_in_progress_uploads_tooltip": "{} upload(s) in progress", "info_completed_uploads_tooltip": "{} upload(s) completed", "error_cannot_create_downloads_dir": "Could not create receive mode folder: {}", @@ -175,10 +175,11 @@ "systray_download_page_loaded_message": "A user loaded the download page", "systray_upload_page_loaded_message": "A user loaded the upload page", "gui_uploads": "Upload History", - "gui_no_uploads": "No uploads yet.", - "gui_clear_history": "Clear history", + "gui_no_uploads": "No Uploads Yet", + "gui_clear_history": "Clear All", "gui_upload_in_progress": "Upload Started {}", "gui_upload_finished_range": "Uploaded {} to {}", "gui_upload_finished": "Uploaded {}", + "gui_download_in_progress": "Download Started {}", "gui_open_folder_error_nautilus": "Cannot open folder because nautilus is not available. The file is here: {}" } diff --git a/tests_gui_local/__init__.py b/tests_gui_local/__init__.py index e69de29b..bb2b2182 100644 --- a/tests_gui_local/__init__.py +++ b/tests_gui_local/__init__.py @@ -0,0 +1 @@ +from .commontests import CommonTests diff --git a/tests_gui_local/commontests.py b/tests_gui_local/commontests.py index e67a91f2..39011b4a 100644 --- a/tests_gui_local/commontests.py +++ b/tests_gui_local/commontests.py @@ -6,6 +6,9 @@ import zipfile from PyQt5 import QtCore, QtTest from onionshare import strings +from onionshare_gui.mode.receive_mode import ReceiveMode +from onionshare_gui.mode.share_mode import ShareMode + class CommonTests(object): def test_gui_loaded(self): @@ -24,54 +27,75 @@ class CommonTests(object): '''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': + if type(mode) == ReceiveMode: QtTest.QTest.mouseClick(self.gui.receive_mode_button, QtCore.Qt.LeftButton) self.assertTrue(self.gui.mode, self.gui.MODE_RECEIVE) - if mode == 'share': + if type(mode) == ShareMode: QtTest.QTest.mouseClick(self.gui.share_mode_button, QtCore.Qt.LeftButton) self.assertTrue(self.gui.mode, self.gui.MODE_SHARE) + def test_click_toggle_history(self, mode): + '''Test that we can toggle Download or Upload history by clicking the toggle button''' + currently_visible = mode.history.isVisible() + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertEqual(mode.history.isVisible(), not currently_visible) + + def test_history_indicator(self, mode, public_mode): + '''Test that we can make sure the history is toggled off, do an action, and the indiciator works''' + # Make sure history is toggled off + if mode.history.isVisible(): + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.history.isVisible()) + + # Indicator should not be visible yet + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) + + if type(mode) == ReceiveMode: + # Upload a file + files = {'file[]': open('/tmp/test.txt', 'rb')} + if not public_mode: + path = 'http://127.0.0.1:{}/{}/upload'.format(self.gui.app.port, 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) + + if type(mode) == ShareMode: + # Download files + if public_mode: + url = "http://127.0.0.1:{}/download".format(self.gui.app.port) + else: + url = "http://127.0.0.1:{}/{}/download".format(self.gui.app.port, self.gui.share_mode.web.slug) + r = requests.get(url) + QtTest.QTest.qWait(2000) + + # Indicator should be visible, have a value of "1" + self.assertTrue(mode.toggle_history.indicator_label.isVisible()) + self.assertEqual(mode.toggle_history.indicator_label.text(), "1") + + # Toggle history back on, indicator should be hidden again + QtTest.QTest.mouseClick(mode.toggle_history, QtCore.Qt.LeftButton) + self.assertFalse(mode.toggle_history.indicator_label.isVisible()) + + def test_history_is_not_visible(self, mode): + '''Test that the History section is not visible''' + self.assertFalse(mode.history.isVisible()) + 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()) + '''Test that the History section is visible''' + self.assertTrue(mode.history.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) + QtTest.QTest.mouseClick(mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEqual(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.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) - if mode == 'share': - self.assertEqual(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) + self.assertEquals(mode.server_status_label.text(), strings._('gui_status_indicator_share_working')) def test_settings_button_is_hidden(self): '''Test that the settings button is hidden when the server starts''' @@ -81,10 +105,7 @@ class CommonTests(object): '''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) + self.assertEqual(mode.server_status.status, 2) def test_a_web_server_is_running(self): '''Test that the web server has started''' @@ -94,38 +115,26 @@ class CommonTests(object): 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+)') + if not public_mode: + self.assertRegex(mode.server_status.web.slug, r'(\w+)-(\w+)') + else: + self.assertIsNone(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()) + self.assertTrue(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()) + self.assertTrue(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.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_started', True)) - if mode == 'share': - self.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_started', True)) + if type(mode) == ReceiveMode: + self.assertEquals(mode.server_status_label.text(), strings._('gui_status_indicator_receive_started')) + if type(mode) == ShareMode: + self.assertEquals(mode.server_status_label.text(), strings._('gui_status_indicator_share_started')) def test_web_page(self, mode, string, public_mode): '''Test that the web page contains a string''' @@ -134,10 +143,7 @@ class CommonTests(object): 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) + path = '/{}'.format(mode.server_status.web.slug) else: path = '/' @@ -160,29 +166,18 @@ class CommonTests(object): 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()) + self.assertFalse(mode.history.empty.isVisible()) + self.assertTrue(mode.history.not_empty.isVisible()) def test_counter_incremented(self, mode, count): '''Test that the counter has incremented''' - if mode == 'receive': - self.assertEqual(self.gui.receive_mode.uploads_completed, count) - if mode == 'share': - self.assertEqual(self.gui.share_mode.downloads_completed, count) + self.assertEquals(mode.history.completed_count, 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.assertEqual(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.assertEqual(self.gui.share_mode.server_status.status, 0) + if type(mode) == ReceiveMode or (type(mode) == ShareMode and stay_open): + QtTest.QTest.mouseClick(mode.server_status.server_button, QtCore.Qt.LeftButton) + self.assertEquals(mode.server_status.status, 0) def test_web_service_is_stopped(self): '''Test that the web server also stopped''' @@ -194,9 +189,9 @@ class CommonTests(object): def test_server_status_indicator_says_closed(self, mode, stay_open): '''Test that the Server Status indicator shows we closed''' - if mode == 'receive': - self.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped', True)) - if mode == 'share': + if type(mode) == ReceiveMode: + self.assertEquals(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped', True)) + if type(mode) == ShareMode: if stay_open: self.assertEqual(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_stopped', True)) else: @@ -206,28 +201,18 @@ class CommonTests(object): 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) + mode.server_status.shutdown_timeout.setDateTime(timer) + self.assertTrue(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()) + self.assertFalse(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) + self.assertEqual(mode.server_status.status, 0) # Receive-specific tests def test_upload_file(self, public_mode, expected_file): @@ -304,4 +289,3 @@ class CommonTests(object): 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/onionshare_receive_mode_upload_test.py b/tests_gui_local/onionshare_receive_mode_upload_test.py index 2aa2ed94..1ce91ba2 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test.py @@ -94,25 +94,29 @@ class OnionShareGuiTest(unittest.TestCase): 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') + CommonTests.test_click_mode(self, self.gui.receive_mode) + + @pytest.mark.run(order=6) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, self.gui.receive_mode) @pytest.mark.run(order=7) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, self.gui.receive_mode) + + @pytest.mark.run(order=8) def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'receive') + CommonTests.test_history_is_visible(self, self.gui.receive_mode) @pytest.mark.run(order=8) def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.receive_mode) @pytest.mark.run(order=9) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'receive') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.receive_mode) @pytest.mark.run(order=10) def test_settings_button_is_hidden(self): @@ -120,7 +124,7 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=11) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'receive') + CommonTests.test_a_server_is_started(self, self.gui.receive_mode) @pytest.mark.run(order=12) def test_a_web_server_is_running(self): @@ -128,23 +132,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=14) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'receive', False) + CommonTests.test_have_a_slug(self, self.gui.receive_mode, False) @pytest.mark.run(order=15) def test_url_description_shown(self): - CommonTests.test_url_description_shown(self, 'receive') + CommonTests.test_url_description_shown(self, self.gui.receive_mode) @pytest.mark.run(order=16) def test_have_copy_url_button(self): - CommonTests.test_have_copy_url_button(self, 'receive') + CommonTests.test_have_copy_url_button(self, self.gui.receive_mode) @pytest.mark.run(order=17) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'receive') + CommonTests.test_server_status_indicator_says_started(self, self.gui.receive_mode) @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) + CommonTests.test_web_page(self, self.gui.receive_mode, 'Select the files you want to send, then click', False) @pytest.mark.run(order=19) def test_upload_file(self): @@ -152,11 +156,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=20) def test_history_widgets_present(self): - CommonTests.test_history_widgets_present(self, 'receive') + CommonTests.test_history_widgets_present(self, self.gui.receive_mode) @pytest.mark.run(order=21) def test_counter_incremented(self): - CommonTests.test_counter_incremented(self, 'receive', 1) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 1) @pytest.mark.run(order=22) def test_upload_same_file_is_renamed(self): @@ -164,19 +168,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=23) def test_upload_count_incremented_again(self): - CommonTests.test_counter_incremented(self, 'receive', 2) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 2) @pytest.mark.run(order=24) - def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'receive', False) + def test_history_indicator(self): + CommonTests.test_history_indicator(self, self.gui.receive_mode, False) @pytest.mark.run(order=25) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, self.gui.receive_mode, False) + + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=27) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.receive_mode, 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 index 30a290e7..cd02e012 100644 --- a/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py +++ b/tests_gui_local/onionshare_receive_mode_upload_test_public_mode.py @@ -74,9 +74,12 @@ class OnionShareGuiTest(unittest.TestCase): @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') + try: + os.remove('/tmp/test.txt') + os.remove('/tmp/OnionShare/test.txt') + os.remove('/tmp/OnionShare/test-2.txt') + except: + pass @pytest.mark.run(order=1) def test_gui_loaded(self): @@ -95,56 +98,60 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_click_mode(self): + CommonTests.test_click_mode(self, self.gui.receive_mode) @pytest.mark.run(order=6) - def test_click_mode(self): - CommonTests.test_click_mode(self, 'receive') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, self.gui.receive_mode) @pytest.mark.run(order=7) - def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'receive') + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, self.gui.receive_mode) @pytest.mark.run(order=8) - def test_server_working_on_start_button_pressed(self): - CommonTests.test_server_working_on_start_button_pressed(self, 'receive') + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, self.gui.receive_mode) @pytest.mark.run(order=9) - def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'receive') + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.receive_mode) @pytest.mark.run(order=10) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, self.gui.receive_mode) + + @pytest.mark.run(order=11) 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_server_is_started(self): + CommonTests.test_a_server_is_started(self, self.gui.receive_mode) + + @pytest.mark.run(order=13) 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) + CommonTests.test_have_a_slug(self, self.gui.receive_mode, True) @pytest.mark.run(order=15) def test_url_description_shown(self): - CommonTests.test_url_description_shown(self, 'receive') + CommonTests.test_url_description_shown(self, self.gui.receive_mode) @pytest.mark.run(order=16) def test_have_copy_url_button(self): - CommonTests.test_have_copy_url_button(self, 'receive') + CommonTests.test_have_copy_url_button(self, self.gui.receive_mode) @pytest.mark.run(order=17) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'receive') + CommonTests.test_server_status_indicator_says_started(self, self.gui.receive_mode) @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) + CommonTests.test_web_page(self, self.gui.receive_mode, 'Select the files you want to send, then click', True) @pytest.mark.run(order=19) def test_upload_file(self): @@ -152,11 +159,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=20) def test_history_widgets_present(self): - CommonTests.test_history_widgets_present(self, 'receive') + CommonTests.test_history_widgets_present(self, self.gui.receive_mode) @pytest.mark.run(order=21) def test_counter_incremented(self): - CommonTests.test_counter_incremented(self, 'receive', 1) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 1) @pytest.mark.run(order=22) def test_upload_same_file_is_renamed(self): @@ -164,19 +171,23 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=23) def test_upload_count_incremented_again(self): - CommonTests.test_counter_incremented(self, 'receive', 2) + CommonTests.test_counter_incremented(self, self.gui.receive_mode, 2) @pytest.mark.run(order=24) - def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'receive', False) + def test_history_indicator(self): + CommonTests.test_history_indicator(self, self.gui.receive_mode, True) @pytest.mark.run(order=25) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, self.gui.receive_mode, False) + + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=27) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.receive_mode, 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 index c546fb61..6842f1a6 100644 --- a/tests_gui_local/onionshare_share_mode_download_test.py +++ b/tests_gui_local/onionshare_share_mode_download_test.py @@ -96,94 +96,104 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, self.gui.share_mode) + + @pytest.mark.run(order=9) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, self.gui.share_mode) + + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) 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_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + + @pytest.mark.run(order=14) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) + + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) 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') + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, self.gui.share_mode, False) @pytest.mark.run(order=20) - def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, self.gui.share_mode) @pytest.mark.run(order=21) - def test_web_page(self): - CommonTests.test_web_page(self, 'share', 'Total size', False) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, self.gui.share_mode) @pytest.mark.run(order=22) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) + + @pytest.mark.run(order=23) + def test_web_page(self): + CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', False) + + @pytest.mark.run(order=24) 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_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, self.gui.share_mode) + + @pytest.mark.run(order=26) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, self.gui.share_mode, False) + + @pytest.mark.run(order=27) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, False) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) + @pytest.mark.run(order=30) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, False) + 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 index 764b5885..82f1989c 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_public_mode.py +++ b/tests_gui_local/onionshare_share_mode_download_test_public_mode.py @@ -96,94 +96,104 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, self.gui.share_mode) + + @pytest.mark.run(order=9) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, self.gui.share_mode) + + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) 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_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + + @pytest.mark.run(order=14) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) + + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) 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') + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, self.gui.share_mode, True) @pytest.mark.run(order=20) - def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, self.gui.share_mode) @pytest.mark.run(order=21) - def test_web_page(self): - CommonTests.test_web_page(self, 'share', 'Total size', True) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, self.gui.share_mode) @pytest.mark.run(order=22) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) + + @pytest.mark.run(order=23) + def test_web_page(self): + CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', True) + + @pytest.mark.run(order=24) 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_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, self.gui.share_mode) + + @pytest.mark.run(order=26) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, self.gui.share_mode, False) + + @pytest.mark.run(order=27) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', False) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, False) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) + @pytest.mark.run(order=30) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, True) + 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 index b92ff097..df9bc857 100644 --- a/tests_gui_local/onionshare_share_mode_download_test_stay_open.py +++ b/tests_gui_local/onionshare_share_mode_download_test_stay_open.py @@ -96,106 +96,116 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, self.gui.share_mode) + + @pytest.mark.run(order=9) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, self.gui.share_mode) + + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) 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_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + + @pytest.mark.run(order=14) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) + + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) 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') + def test_have_a_slug(self): + CommonTests.test_have_a_slug(self, self.gui.share_mode, True) @pytest.mark.run(order=20) - def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + def test_url_description_shown(self): + CommonTests.test_url_description_shown(self, self.gui.share_mode) @pytest.mark.run(order=21) - def test_web_page(self): - CommonTests.test_web_page(self, 'share', 'Total size', True) + def test_have_copy_url_button(self): + CommonTests.test_have_copy_url_button(self, self.gui.share_mode) @pytest.mark.run(order=22) + def test_server_status_indicator_says_started(self): + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) + + @pytest.mark.run(order=23) + def test_web_page(self): + CommonTests.test_web_page(self, self.gui.share_mode, 'Total size', True) + + @pytest.mark.run(order=24) 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_history_widgets_present(self): + CommonTests.test_history_widgets_present(self, self.gui.share_mode) + + @pytest.mark.run(order=26) + def test_counter_incremented(self): + CommonTests.test_counter_incremented(self, self.gui.share_mode, 1) + + @pytest.mark.run(order=27) 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_counter_incremented_again(self): + CommonTests.test_counter_incremented(self, self.gui.share_mode, 2) + + @pytest.mark.run(order=29) + def test_server_is_stopped(self): + CommonTests.test_server_is_stopped(self, self.gui.share_mode, True) + + @pytest.mark.run(order=30) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=29) + @pytest.mark.run(order=31) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, True) - @pytest.mark.run(order=30) + @pytest.mark.run(order=32) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) + @pytest.mark.run(order=33) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, True) + 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 index 1e5614dc..5b825dad 100644 --- a/tests_gui_local/onionshare_slug_persistent_test.py +++ b/tests_gui_local/onionshare_slug_persistent_test.py @@ -94,72 +94,82 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) - def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'share') + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, self.gui.share_mode) @pytest.mark.run(order=9) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, self.gui.share_mode) + + @pytest.mark.run(order=10) + def test_server_working_on_start_button_pressed(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + + @pytest.mark.run(order=11) + def test_server_status_indicator_says_starting(self): + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) + + @pytest.mark.run(order=12) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=13) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) - @pytest.mark.run(order=11) + @pytest.mark.run(order=14) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=12) + @pytest.mark.run(order=15) def test_have_a_slug(self): - CommonTests.test_have_a_slug(self, 'share', False) + CommonTests.test_have_a_slug(self, self.gui.share_mode, False) global slug slug = self.gui.share_mode.server_status.web.slug - @pytest.mark.run(order=13) + @pytest.mark.run(order=16) def test_server_status_indicator_says_started(self): - CommonTests.test_server_status_indicator_says_started(self, 'share') + CommonTests.test_server_status_indicator_says_started(self, self.gui.share_mode) - @pytest.mark.run(order=14) + @pytest.mark.run(order=17) def test_server_is_stopped(self): - CommonTests.test_server_is_stopped(self, 'share', True) + CommonTests.test_server_is_stopped(self, self.gui.share_mode, True) - @pytest.mark.run(order=15) + @pytest.mark.run(order=18) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=16) + @pytest.mark.run(order=19) def test_server_status_indicator_says_closed(self): - CommonTests.test_server_status_indicator_says_closed(self, 'share', True) + CommonTests.test_server_status_indicator_says_closed(self, self.gui.share_mode, True) - @pytest.mark.run(order=17) + @pytest.mark.run(order=20) 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') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) - @pytest.mark.run(order=18) + @pytest.mark.run(order=21) 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) + @pytest.mark.run(order=22) def test_server_is_stopped_again(self): - CommonTests.test_server_is_stopped(self, 'share', True) + CommonTests.test_server_is_stopped(self, self.gui.share_mode, True) CommonTests.test_web_service_is_stopped(self) + @pytest.mark.run(order=23) + def test_history_indicator(self): + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) + CommonTests.test_a_server_is_started(self, self.gui.share_mode) + CommonTests.test_history_indicator(self, self.gui.share_mode, False) + if __name__ == "__main__": unittest.main() diff --git a/tests_gui_local/onionshare_timer_test.py b/tests_gui_local/onionshare_timer_test.py index 1a5134e2..4aaaf364 100644 --- a/tests_gui_local/onionshare_timer_test.py +++ b/tests_gui_local/onionshare_timer_test.py @@ -96,29 +96,25 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, self.gui.share_mode) @pytest.mark.run(order=8) def test_set_timeout(self): - CommonTests.test_set_timeout(self, 'share', 5) + CommonTests.test_set_timeout(self, self.gui.share_mode, 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') + CommonTests.test_server_working_on_start_button_pressed(self, self.gui.share_mode) @pytest.mark.run(order=10) def test_server_status_indicator_says_starting(self): - CommonTests.test_server_status_indicator_says_starting(self, 'share') + CommonTests.test_server_status_indicator_says_starting(self, self.gui.share_mode) @pytest.mark.run(order=11) def test_a_server_is_started(self): - CommonTests.test_a_server_is_started(self, 'share') + CommonTests.test_a_server_is_started(self, self.gui.share_mode) @pytest.mark.run(order=12) def test_a_web_server_is_running(self): @@ -126,11 +122,11 @@ class OnionShareGuiTest(unittest.TestCase): @pytest.mark.run(order=13) def test_timeout_widget_hidden(self): - CommonTests.test_timeout_widget_hidden(self, 'share') + CommonTests.test_timeout_widget_hidden(self, self.gui.share_mode) @pytest.mark.run(order=14) def test_timeout(self): - CommonTests.test_server_timed_out(self, 'share', 10000) + CommonTests.test_server_timed_out(self, self.gui.share_mode, 10000) @pytest.mark.run(order=15) def test_web_service_is_stopped(self): diff --git a/tests_gui_tor/commontests.py b/tests_gui_tor/commontests.py index f58f0504..a1e420fd 100644 --- a/tests_gui_tor/commontests.py +++ b/tests_gui_tor/commontests.py @@ -7,78 +7,11 @@ 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.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_share_working', True)) - if mode == 'share': - self.assertEqual(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()) +from tests_gui_local import CommonTests as LocalCommonTests +class CommonTests(LocalCommonTests): def test_a_server_is_started(self, mode): - '''Test that the server has started''' + '''Test that the server has started (overriding from local tests to wait for longer)''' QtTest.QTest.qWait(45000) # Should now be in SERVER_STARTED state if mode == 'receive': @@ -86,128 +19,10 @@ class CommonTests(object): 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.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_started', True)) - if mode == 'share': - self.assertEqual(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.assertEqual(self.gui.receive_mode.uploads_completed, count) - if mode == 'share': - self.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(self.gui.receive_mode.server_status_label.text(), strings._('gui_status_indicator_receive_stopped', True)) - if mode == 'share': - if stay_open: - self.assertEqual(self.gui.share_mode.server_status_label.text(), strings._('gui_status_indicator_share_stopped', True)) - else: - self.assertEqual(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': @@ -222,119 +37,6 @@ class CommonTests(object): 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.assertEqual(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.assertEqual('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''' diff --git a/tests_gui_tor/onionshare_receive_mode_upload_test.py b/tests_gui_tor/onionshare_receive_mode_upload_test.py index 5be400e2..7c340037 100644 --- a/tests_gui_tor/onionshare_receive_mode_upload_test.py +++ b/tests_gui_tor/onionshare_receive_mode_upload_test.py @@ -94,15 +94,19 @@ class OnionShareGuiTest(unittest.TestCase): 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=6) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'receive') + @pytest.mark.run(order=7) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'receive') + + @pytest.mark.run(order=8) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'receive') @@ -134,51 +138,51 @@ class OnionShareGuiTest(unittest.TestCase): def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=16) + @pytest.mark.run(order=20) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'receive') - @pytest.mark.run(order=17) + @pytest.mark.run(order=21) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'receive') - @pytest.mark.run(order=18) + @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'receive') - @pytest.mark.run(order=19) + @pytest.mark.run(order=23) 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) + @pytest.mark.run(order=24) def test_upload_file(self): CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test.txt') - @pytest.mark.run(order=21) + @pytest.mark.run(order=25) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'receive') - @pytest.mark.run(order=22) + @pytest.mark.run(order=26) def test_counter_incremented(self): CommonTests.test_counter_incremented(self, 'receive', 1) - @pytest.mark.run(order=23) + @pytest.mark.run(order=27) def test_upload_same_file_is_renamed(self): CommonTests.test_upload_file(self, False, '/tmp/OnionShare/test-2.txt') - @pytest.mark.run(order=24) + @pytest.mark.run(order=28) def test_upload_count_incremented_again(self): CommonTests.test_counter_incremented(self, 'receive', 2) - @pytest.mark.run(order=25) + @pytest.mark.run(order=29) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'receive', False) - @pytest.mark.run(order=26) + @pytest.mark.run(order=30) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=27) + @pytest.mark.run(order=31) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) 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 index 9c9553a4..65bf5c89 100644 --- a/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py +++ b/tests_gui_tor/onionshare_receive_mode_upload_test_public_mode.py @@ -95,34 +95,38 @@ class OnionShareGuiTest(unittest.TestCase): 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=6) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'receive') + @pytest.mark.run(order=7) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'receive') + + @pytest.mark.run(order=8) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'receive') - @pytest.mark.run(order=8) + @pytest.mark.run(order=9) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'receive') - @pytest.mark.run(order=9) + @pytest.mark.run(order=10) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'receive') - @pytest.mark.run(order=10) + @pytest.mark.run(order=11) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=12) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'receive') - @pytest.mark.run(order=12) + @pytest.mark.run(order=13) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) @@ -134,51 +138,51 @@ class OnionShareGuiTest(unittest.TestCase): def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=16) + @pytest.mark.run(order=20) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'receive') - @pytest.mark.run(order=17) + @pytest.mark.run(order=21) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'receive') - @pytest.mark.run(order=18) + @pytest.mark.run(order=22) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'receive') - @pytest.mark.run(order=19) + @pytest.mark.run(order=23) 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) + @pytest.mark.run(order=24) def test_upload_file(self): CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test.txt') - @pytest.mark.run(order=21) + @pytest.mark.run(order=25) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'receive') - @pytest.mark.run(order=22) + @pytest.mark.run(order=26) def test_counter_incremented(self): CommonTests.test_counter_incremented(self, 'receive', 1) - @pytest.mark.run(order=23) + @pytest.mark.run(order=27) def test_upload_same_file_is_renamed(self): CommonTests.test_upload_file(self, True, '/tmp/OnionShare/test-2.txt') - @pytest.mark.run(order=24) + @pytest.mark.run(order=28) def test_upload_count_incremented_again(self): CommonTests.test_counter_incremented(self, 'receive', 2) - @pytest.mark.run(order=25) + @pytest.mark.run(order=29) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'receive', False) - @pytest.mark.run(order=26) + @pytest.mark.run(order=30) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=27) + @pytest.mark.run(order=31) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'receive', False) diff --git a/tests_gui_tor/onionshare_share_mode_cancel_share_test.py b/tests_gui_tor/onionshare_share_mode_cancel_share_test.py index 466109d7..cdab8f85 100644 --- a/tests_gui_tor/onionshare_share_mode_cancel_share_test.py +++ b/tests_gui_tor/onionshare_share_mode_cancel_share_test.py @@ -96,14 +96,6 @@ class OnionShareGuiTest(unittest.TestCase): 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) diff --git a/tests_gui_tor/onionshare_share_mode_download_test.py b/tests_gui_tor/onionshare_share_mode_download_test.py index 1c8e1b6c..2bf26690 100644 --- a/tests_gui_tor/onionshare_share_mode_download_test.py +++ b/tests_gui_tor/onionshare_share_mode_download_test.py @@ -97,20 +97,20 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) - def test_history_is_visible(self): - CommonTests.test_history_is_visible(self, 'share') + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_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) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') @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) + def test_history_is_visible(self): + CommonTests.test_history_is_visible(self, 'share') @pytest.mark.run(order=10) def test_file_selection_widget_readd_files(self): 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 index c292e729..4792994d 100644 --- a/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py +++ b/tests_gui_tor/onionshare_share_mode_download_test_public_mode.py @@ -97,94 +97,102 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_web_page(self): CommonTests.test_web_page(self, 'share', 'Total size', True) - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_download_share(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'share') - @pytest.mark.run(order=25) + @pytest.mark.run(order=27) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', False) - @pytest.mark.run(order=28) + @pytest.mark.run(order=30) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) 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 index 7838316f..92d52169 100644 --- a/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py +++ b/tests_gui_tor/onionshare_share_mode_download_test_stay_open.py @@ -97,106 +97,114 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_web_page(self): CommonTests.test_web_page(self, 'share', 'Total size', True) - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_download_share(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_history_widgets_present(self): CommonTests.test_history_widgets_present(self, 'share') - @pytest.mark.run(order=25) + @pytest.mark.run(order=27) def test_counter_incremented(self): CommonTests.test_counter_incremented(self, 'share', 1) - @pytest.mark.run(order=26) + @pytest.mark.run(order=28) def test_download_share_again(self): CommonTests.test_download_share(self, True) - @pytest.mark.run(order=27) + @pytest.mark.run(order=29) def test_counter_incremented_again(self): CommonTests.test_counter_incremented(self, 'share', 2) - @pytest.mark.run(order=28) + @pytest.mark.run(order=30) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', True) - @pytest.mark.run(order=29) + @pytest.mark.run(order=31) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=30) + @pytest.mark.run(order=32) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', True) - @pytest.mark.run(order=31) + @pytest.mark.run(order=33) def test_add_button_visible(self): CommonTests.test_add_button_visible(self) diff --git a/tests_gui_tor/onionshare_share_mode_persistent_test.py b/tests_gui_tor/onionshare_share_mode_persistent_test.py index 3cffaab6..6b9fbe16 100644 --- a/tests_gui_tor/onionshare_share_mode_persistent_test.py +++ b/tests_gui_tor/onionshare_share_mode_persistent_test.py @@ -95,79 +95,87 @@ class OnionShareGuiTest(unittest.TestCase): 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_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') + + @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=7) + @pytest.mark.run(order=10) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=11) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=9) + @pytest.mark.run(order=12) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=10) + @pytest.mark.run(order=13) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=11) + @pytest.mark.run(order=14) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=12) + @pytest.mark.run(order=15) 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) + @pytest.mark.run(order=16) 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) + @pytest.mark.run(order=17) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=15) + @pytest.mark.run(order=18) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', True) - @pytest.mark.run(order=16) + @pytest.mark.run(order=19) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=20) def test_server_status_indicator_says_closed(self): CommonTests.test_server_status_indicator_says_closed(self, 'share', True) - @pytest.mark.run(order=18) + @pytest.mark.run(order=21) 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) + @pytest.mark.run(order=22) 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) + @pytest.mark.run(order=23) 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) + @pytest.mark.run(order=24) def test_server_is_stopped_again(self): CommonTests.test_server_is_stopped(self, 'share', True) CommonTests.test_web_service_is_stopped(self) diff --git a/tests_gui_tor/onionshare_share_mode_stealth_test.py b/tests_gui_tor/onionshare_share_mode_stealth_test.py index aaf6fbc6..876efde2 100644 --- a/tests_gui_tor/onionshare_share_mode_stealth_test.py +++ b/tests_gui_tor/onionshare_share_mode_stealth_test.py @@ -97,74 +97,82 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_copy_have_hidserv_auth_button(self): CommonTests.test_copy_have_hidserv_auth_button(self, 'share') - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_hidserv_auth_string(self): CommonTests.test_hidserv_auth_string(self) 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 index 861b7ccc..37abc825 100644 --- a/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py +++ b/tests_gui_tor/onionshare_share_mode_tor_connection_killed_test.py @@ -97,78 +97,86 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_tor_killed_statusbar_message_shown(self): CommonTests.test_tor_killed_statusbar_message_shown(self, 'share') - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) diff --git a/tests_gui_tor/onionshare_timer_test.py b/tests_gui_tor/onionshare_timer_test.py index b76106d9..2b64b998 100644 --- a/tests_gui_tor/onionshare_timer_test.py +++ b/tests_gui_tor/onionshare_timer_test.py @@ -97,42 +97,50 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_set_timeout(self): CommonTests.test_set_timeout(self, 'share', 120) - @pytest.mark.run(order=9) + @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=10) + @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=11) + @pytest.mark.run(order=13) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_timeout_widget_hidden(self): CommonTests.test_timeout_widget_hidden(self, 'share') - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_timeout(self): CommonTests.test_server_timed_out(self, 'share', 125000) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self) diff --git a/tests_gui_tor/onionshare_tor_connection_killed_test.py b/tests_gui_tor/onionshare_tor_connection_killed_test.py index 861b7ccc..37abc825 100644 --- a/tests_gui_tor/onionshare_tor_connection_killed_test.py +++ b/tests_gui_tor/onionshare_tor_connection_killed_test.py @@ -97,78 +97,86 @@ class OnionShareGuiTest(unittest.TestCase): 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') + def test_info_widget_shows_less(self): + CommonTests.test_info_widget_shows_less(self, 'share') @pytest.mark.run(order=7) + def test_history_is_not_visible(self): + CommonTests.test_history_is_not_visible(self, 'share') + + @pytest.mark.run(order=8) + def test_click_toggle_history(self): + CommonTests.test_click_toggle_history(self, 'share') + + @pytest.mark.run(order=9) def test_history_is_visible(self): CommonTests.test_history_is_visible(self, 'share') - @pytest.mark.run(order=8) + @pytest.mark.run(order=10) def test_deleting_only_file_hides_delete_button(self): CommonTests.test_deleting_only_file_hides_delete_button(self) - @pytest.mark.run(order=9) + @pytest.mark.run(order=11) 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) + @pytest.mark.run(order=12) def test_file_selection_widget_readd_files(self): CommonTests.test_file_selection_widget_readd_files(self) - @pytest.mark.run(order=11) + @pytest.mark.run(order=13) def test_server_working_on_start_button_pressed(self): CommonTests.test_server_working_on_start_button_pressed(self, 'share') - @pytest.mark.run(order=12) + @pytest.mark.run(order=14) def test_server_status_indicator_says_starting(self): CommonTests.test_server_status_indicator_says_starting(self, 'share') - @pytest.mark.run(order=13) + @pytest.mark.run(order=15) def test_add_delete_buttons_hidden(self): CommonTests.test_add_delete_buttons_hidden(self) - @pytest.mark.run(order=14) + @pytest.mark.run(order=16) def test_settings_button_is_hidden(self): CommonTests.test_settings_button_is_hidden(self) - @pytest.mark.run(order=15) + @pytest.mark.run(order=17) def test_a_server_is_started(self): CommonTests.test_a_server_is_started(self, 'share') - @pytest.mark.run(order=16) + @pytest.mark.run(order=18) def test_a_web_server_is_running(self): CommonTests.test_a_web_server_is_running(self) - @pytest.mark.run(order=17) + @pytest.mark.run(order=19) def test_have_a_slug(self): CommonTests.test_have_a_slug(self, 'share', False) - @pytest.mark.run(order=18) + @pytest.mark.run(order=20) def test_have_an_onion(self): CommonTests.test_have_an_onion_service(self) - @pytest.mark.run(order=19) + @pytest.mark.run(order=21) def test_url_description_shown(self): CommonTests.test_url_description_shown(self, 'share') - @pytest.mark.run(order=20) + @pytest.mark.run(order=22) def test_have_copy_url_button(self): CommonTests.test_have_copy_url_button(self, 'share') - @pytest.mark.run(order=21) + @pytest.mark.run(order=23) def test_server_status_indicator_says_started(self): CommonTests.test_server_status_indicator_says_started(self, 'share') - @pytest.mark.run(order=22) + @pytest.mark.run(order=24) def test_tor_killed_statusbar_message_shown(self): CommonTests.test_tor_killed_statusbar_message_shown(self, 'share') - @pytest.mark.run(order=23) + @pytest.mark.run(order=25) def test_server_is_stopped(self): CommonTests.test_server_is_stopped(self, 'share', False) - @pytest.mark.run(order=24) + @pytest.mark.run(order=26) def test_web_service_is_stopped(self): CommonTests.test_web_service_is_stopped(self)