mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-04-28 09:52:37 +02:00

This new setting triggers the same user prompts, but the actual meaning of it differs, since users will now be accepting to upgrade the container image rather than just checking for new releases. Changing the name of the setting will trigger this prompt for all users, effectively ensuring they want their image to be automatically upgraded.
645 lines
22 KiB
Python
645 lines
22 KiB
Python
import os
|
|
import pathlib
|
|
import platform
|
|
import shutil
|
|
import time
|
|
from typing import List
|
|
|
|
from pytest import MonkeyPatch, fixture
|
|
from pytest_mock import MockerFixture
|
|
from pytestqt.qtbot import QtBot
|
|
|
|
from dangerzone import errors
|
|
from dangerzone.document import Document
|
|
from dangerzone.gui import MainWindow
|
|
from dangerzone.gui import main_window as main_window_module
|
|
from dangerzone.gui import updater as updater_module
|
|
from dangerzone.gui.logic import DangerzoneGui
|
|
|
|
# import Pyside related objects from here to avoid duplicating import logic.
|
|
from dangerzone.gui.main_window import (
|
|
ContentWidget,
|
|
InstallContainerThread,
|
|
QtCore,
|
|
QtGui,
|
|
WaitingWidgetContainer,
|
|
)
|
|
from dangerzone.gui.updater import UpdaterThread
|
|
from dangerzone.isolation_provider.container import Container
|
|
from dangerzone.isolation_provider.dummy import Dummy
|
|
from dangerzone.updater import releases
|
|
|
|
from .test_updater import assert_report_equal, default_updater_settings
|
|
|
|
##
|
|
# Widget Fixtures
|
|
##
|
|
|
|
|
|
@fixture
|
|
def content_widget(qtbot: QtBot, mocker: MockerFixture) -> ContentWidget:
|
|
# Setup
|
|
mock_app = mocker.MagicMock()
|
|
dummy = mocker.MagicMock()
|
|
dz = DangerzoneGui(mock_app, dummy)
|
|
w = ContentWidget(dz)
|
|
qtbot.addWidget(w)
|
|
return w
|
|
|
|
|
|
def drag_files_event(mocker: MockerFixture, files: List[str]) -> QtGui.QDropEvent:
|
|
ev = mocker.MagicMock(spec=QtGui.QDropEvent)
|
|
ev.accept.return_value = True
|
|
|
|
urls = [QtCore.QUrl.fromLocalFile(x) for x in files]
|
|
ev.mimeData.return_value.has_urls.return_value = True
|
|
ev.mimeData.return_value.urls.return_value = urls
|
|
return ev
|
|
|
|
|
|
@fixture
|
|
def drag_valid_files_event(
|
|
mocker: MockerFixture, sample_doc: str, sample_pdf: str
|
|
) -> QtGui.QDropEvent:
|
|
return drag_files_event(mocker, [sample_doc, sample_pdf])
|
|
|
|
|
|
@fixture
|
|
def drag_1_invalid_file_event(
|
|
mocker: MockerFixture, sample_doc: str, tmp_path: pathlib.Path
|
|
) -> QtGui.QDropEvent:
|
|
unsupported_file_path = tmp_path / "file.unsupported"
|
|
shutil.copy(sample_doc, unsupported_file_path)
|
|
return drag_files_event(mocker, [str(unsupported_file_path)])
|
|
|
|
|
|
@fixture
|
|
def drag_1_invalid_and_2_valid_files_event(
|
|
mocker: MockerFixture, tmp_path: pathlib.Path, sample_doc: str, sample_pdf: str
|
|
) -> QtGui.QDropEvent:
|
|
unsupported_file_path = tmp_path / "file.unsupported"
|
|
shutil.copy(sample_doc, unsupported_file_path)
|
|
return drag_files_event(
|
|
mocker, [sample_doc, sample_pdf, str(unsupported_file_path)]
|
|
)
|
|
|
|
|
|
@fixture
|
|
def drag_text_event(mocker: MockerFixture) -> QtGui.QDropEvent:
|
|
ev = mocker.MagicMock()
|
|
ev.accept.return_value = True
|
|
ev.mimeData.return_value.has_urls.return_value = False
|
|
return ev
|
|
|
|
|
|
def test_default_menu(
|
|
qtbot: QtBot,
|
|
updater: UpdaterThread,
|
|
) -> None:
|
|
"""Check that the default menu entries are in order."""
|
|
updater.dangerzone.settings.set("updater_check_all", True)
|
|
|
|
window = MainWindow(updater.dangerzone)
|
|
menu_actions = window.hamburger_button.menu().actions()
|
|
assert len(menu_actions) == 3
|
|
|
|
toggle_updates_action = menu_actions[0]
|
|
assert toggle_updates_action.text() == "Check for updates"
|
|
assert toggle_updates_action.isChecked()
|
|
|
|
separator = menu_actions[1]
|
|
assert separator.isSeparator()
|
|
|
|
exit_action = menu_actions[2]
|
|
assert exit_action.text() == "Exit"
|
|
|
|
toggle_updates_action.trigger()
|
|
assert not toggle_updates_action.isChecked()
|
|
assert updater.dangerzone.settings.get("updater_check_all") is False
|
|
|
|
|
|
def test_no_update(
|
|
qtbot: QtBot,
|
|
updater: UpdaterThread,
|
|
monkeypatch: MonkeyPatch,
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""Test that when no update has been detected, the user is not alerted."""
|
|
# Check that when no update is detected, e.g., due to update cooldown, an empty
|
|
# report is received that does not affect the menu entries.
|
|
curtime = int(time.time())
|
|
updater.dangerzone.settings.set("updater_check_all", True)
|
|
updater.dangerzone.settings.set("updater_errors", 9)
|
|
updater.dangerzone.settings.set("updater_last_check", curtime)
|
|
|
|
expected_settings = default_updater_settings()
|
|
expected_settings["updater_check_all"] = True
|
|
expected_settings["updater_errors"] = 0 # errors must be cleared
|
|
expected_settings["updater_last_check"] = curtime
|
|
|
|
window = MainWindow(updater.dangerzone)
|
|
window.register_update_handler(updater.finished)
|
|
handle_updates_spy = mocker.spy(window, "handle_updates")
|
|
|
|
menu_actions_before = window.hamburger_button.menu().actions()
|
|
|
|
with qtbot.waitSignal(updater.finished):
|
|
updater.start()
|
|
|
|
# Check that the callback function gets an empty report.
|
|
handle_updates_spy.assert_called_once()
|
|
assert_report_equal(handle_updates_spy.call_args.args[0], releases.UpdateReport())
|
|
|
|
# Check that the menu entries remain exactly the same.
|
|
menu_actions_after = window.hamburger_button.menu().actions()
|
|
assert menu_actions_before == menu_actions_after
|
|
|
|
# Check that any previous update errors are cleared.
|
|
assert updater.dangerzone.settings.get_updater_settings() == expected_settings
|
|
|
|
|
|
def test_update_detected(
|
|
qtbot: QtBot,
|
|
qt_updater: UpdaterThread,
|
|
monkeypatch: MonkeyPatch,
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""Test that a newly detected version leads to a notification to the user."""
|
|
|
|
qt_updater.dangerzone.settings.set("updater_check_all", True)
|
|
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
|
qt_updater.dangerzone.settings.set("updater_errors", 9)
|
|
|
|
# Make requests.get().json() return the following dictionary.
|
|
mock_upstream_info = {"tag_name": "99.9.9", "body": "changelog"}
|
|
mocker.patch("dangerzone.updater.releases.requests.get")
|
|
requests_mock = releases.requests.get
|
|
requests_mock().status_code = 200 # type: ignore [call-arg]
|
|
requests_mock().json.return_value = mock_upstream_info # type: ignore [attr-defined, call-arg]
|
|
|
|
window = MainWindow(qt_updater.dangerzone)
|
|
window.register_update_handler(qt_updater.finished)
|
|
handle_updates_spy = mocker.spy(window, "handle_updates")
|
|
load_svg_spy = mocker.spy(main_window_module, "load_svg_image")
|
|
|
|
menu_actions_before = window.hamburger_button.menu().actions()
|
|
|
|
with qtbot.waitSignal(qt_updater.finished):
|
|
qt_updater.start()
|
|
|
|
menu_actions_after = window.hamburger_button.menu().actions()
|
|
|
|
# Check that the callback function gets an update report.
|
|
handle_updates_spy.assert_called_once()
|
|
assert_report_equal(
|
|
handle_updates_spy.call_args.args[0],
|
|
releases.UpdateReport("99.9.9", "<p>changelog</p>"),
|
|
)
|
|
|
|
# Check that the settings have been updated properly.
|
|
expected_settings = default_updater_settings()
|
|
expected_settings["updater_check_all"] = True
|
|
expected_settings["updater_last_check"] = qt_updater.dangerzone.settings.get(
|
|
"updater_last_check"
|
|
)
|
|
expected_settings["updater_latest_version"] = "99.9.9"
|
|
expected_settings["updater_latest_changelog"] = "<p>changelog</p>"
|
|
expected_settings["updater_errors"] = 0
|
|
assert qt_updater.dangerzone.settings.get_updater_settings() == expected_settings
|
|
|
|
# Check that the hamburger icon has changed with the expected SVG image.
|
|
assert load_svg_spy.call_count == 2
|
|
assert load_svg_spy.call_args_list[0].args[0] == "hamburger_menu_update_success.svg"
|
|
assert (
|
|
load_svg_spy.call_args_list[1].args[0]
|
|
== "hamburger_menu_update_dot_available.svg"
|
|
)
|
|
|
|
# Check that new menu entries have been added.
|
|
menu_actions_after = window.hamburger_button.menu().actions()
|
|
assert len(menu_actions_after) == 5
|
|
assert menu_actions_after[2:] == menu_actions_before
|
|
|
|
success_action = menu_actions_after[0]
|
|
assert success_action.text() == "New version available"
|
|
|
|
separator = menu_actions_after[1]
|
|
assert separator.isSeparator()
|
|
|
|
# Check that clicking in the new menu entry, opens a dialog.
|
|
update_dialog_spy = mocker.spy(main_window_module, "UpdateDialog")
|
|
|
|
def check_dialog() -> None:
|
|
dialog = qt_updater.dangerzone.app.activeWindow()
|
|
|
|
update_dialog_spy.assert_called_once()
|
|
kwargs = update_dialog_spy.call_args.kwargs
|
|
assert "99.9.9" in kwargs["title"]
|
|
assert "dangerzone.rocks" in kwargs["intro_msg"]
|
|
assert not kwargs["middle_widget"].toggle_button.isChecked()
|
|
collapsible_box = kwargs["middle_widget"]
|
|
text_browser = (
|
|
collapsible_box.layout().itemAt(1).widget().layout().itemAt(0).widget()
|
|
)
|
|
assert collapsible_box.toggle_button.text() == "What's New?"
|
|
assert text_browser.toPlainText() == "changelog"
|
|
|
|
height_initial = dialog.sizeHint().height()
|
|
width_initial = dialog.sizeHint().width()
|
|
|
|
# Collapse the "What's New" section and ensure that the dialog's height
|
|
# increases.
|
|
with qtbot.waitSignal(collapsible_box.toggle_animation.finished):
|
|
collapsible_box.toggle_button.click()
|
|
|
|
assert dialog.sizeHint().height() > height_initial
|
|
assert dialog.sizeHint().width() == width_initial
|
|
|
|
# Uncollapse the "What's New" section, and ensure that the dialog's height gets
|
|
# back to the original value.
|
|
with qtbot.waitSignal(collapsible_box.toggle_animation.finished):
|
|
collapsible_box.toggle_button.click()
|
|
|
|
assert dialog.sizeHint().height() == height_initial
|
|
assert dialog.sizeHint().width() == width_initial
|
|
|
|
dialog.close()
|
|
|
|
QtCore.QTimer.singleShot(500, check_dialog)
|
|
success_action.trigger()
|
|
|
|
# FIXME: We should check the content of the dialog here.
|
|
|
|
|
|
def test_update_error(
|
|
qtbot: QtBot,
|
|
qt_updater: UpdaterThread,
|
|
monkeypatch: MonkeyPatch,
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""Test that an error during an update check leads to a notification to the user."""
|
|
# Test 1 - Check that the first error does not notify the user.
|
|
qt_updater.dangerzone.settings.set("updater_check_all", True)
|
|
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
|
qt_updater.dangerzone.settings.set("updater_errors", 0)
|
|
|
|
# Make requests.get() return an error
|
|
mocker.patch("dangerzone.updater.releases.requests.get")
|
|
requests_mock = releases.requests.get
|
|
requests_mock.side_effect = Exception("failed") # type: ignore [attr-defined]
|
|
|
|
window = MainWindow(qt_updater.dangerzone)
|
|
window.register_update_handler(qt_updater.finished)
|
|
handle_updates_spy = mocker.spy(window, "handle_updates")
|
|
load_svg_spy = mocker.spy(main_window_module, "load_svg_image")
|
|
|
|
menu_actions_before = window.hamburger_button.menu().actions()
|
|
|
|
with qtbot.waitSignal(qt_updater.finished):
|
|
qt_updater.start()
|
|
|
|
menu_actions_after = window.hamburger_button.menu().actions()
|
|
|
|
# Check that the callback function gets an update report.
|
|
handle_updates_spy.assert_called_once()
|
|
assert "failed" in handle_updates_spy.call_args.args[0].error
|
|
|
|
# Check that the settings have been updated properly.
|
|
expected_settings = default_updater_settings()
|
|
expected_settings["updater_check_all"] = True
|
|
expected_settings["updater_last_check"] = qt_updater.dangerzone.settings.get(
|
|
"updater_last_check"
|
|
)
|
|
expected_settings["updater_errors"] += 1
|
|
assert qt_updater.dangerzone.settings.get_updater_settings() == expected_settings
|
|
|
|
# Check that the hamburger icon has not changed.
|
|
assert load_svg_spy.call_count == 0
|
|
|
|
# Check that no menu entries have been added.
|
|
assert menu_actions_before == menu_actions_after
|
|
|
|
# Test 2 - Check that the second error does not notify the user either.
|
|
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
|
with qtbot.waitSignal(qt_updater.finished):
|
|
qt_updater.start()
|
|
|
|
assert load_svg_spy.call_count == 0
|
|
|
|
# Check that the settings have been updated properly.
|
|
expected_settings["updater_errors"] += 1
|
|
expected_settings["updater_last_check"] = qt_updater.dangerzone.settings.get(
|
|
"updater_last_check"
|
|
)
|
|
assert qt_updater.dangerzone.settings.get_updater_settings() == expected_settings
|
|
|
|
# Check that no menu entries have been added.
|
|
assert menu_actions_before == menu_actions_after
|
|
|
|
# Test 3 - Check that a third error shows a new menu entry.
|
|
qt_updater.dangerzone.settings.set("updater_last_check", 0)
|
|
with qtbot.waitSignal(qt_updater.finished):
|
|
qt_updater.start()
|
|
|
|
menu_actions_after = window.hamburger_button.menu().actions()
|
|
assert len(menu_actions_after) == 5
|
|
assert menu_actions_after[2:] == menu_actions_before
|
|
|
|
# Check that the hamburger icon has changed with the expected SVG image.
|
|
assert load_svg_spy.call_count == 2
|
|
assert load_svg_spy.call_args_list[0].args[0] == "hamburger_menu_update_error.svg"
|
|
assert (
|
|
load_svg_spy.call_args_list[1].args[0] == "hamburger_menu_update_dot_error.svg"
|
|
)
|
|
|
|
error_action = menu_actions_after[0]
|
|
assert error_action.text() == "Update error"
|
|
|
|
separator = menu_actions_after[1]
|
|
assert separator.isSeparator()
|
|
|
|
# Check that clicking in the new menu entry, opens a dialog.
|
|
update_dialog_spy = mocker.spy(main_window_module, "UpdateDialog")
|
|
|
|
def check_dialog() -> None:
|
|
dialog = qt_updater.dangerzone.app.activeWindow()
|
|
|
|
update_dialog_spy.assert_called_once()
|
|
kwargs = update_dialog_spy.call_args.kwargs
|
|
assert kwargs["title"] == "Update check error"
|
|
assert "Something went wrong" in kwargs["intro_msg"]
|
|
assert "dangerzone.rocks" in kwargs["intro_msg"]
|
|
assert not kwargs["middle_widget"].toggle_button.isChecked()
|
|
collapsible_box = kwargs["middle_widget"]
|
|
text_browser = (
|
|
collapsible_box.layout().itemAt(1).widget().layout().itemAt(0).widget()
|
|
)
|
|
assert collapsible_box.toggle_button.text() == "Error Details"
|
|
assert "Encountered an exception" in text_browser.toPlainText()
|
|
assert "failed" in text_browser.toPlainText()
|
|
|
|
dialog.close()
|
|
|
|
QtCore.QTimer.singleShot(500, check_dialog)
|
|
error_action.trigger()
|
|
|
|
|
|
##
|
|
# Document Selection tests
|
|
##
|
|
|
|
|
|
def test_change_document_button(
|
|
content_widget: ContentWidget,
|
|
qtbot: QtBot,
|
|
mocker: MockerFixture,
|
|
sample_pdf: str,
|
|
sample_doc: str,
|
|
tmp_path: pathlib.Path,
|
|
) -> None:
|
|
# Setup first doc selection
|
|
file_dialog_mock = mocker.MagicMock()
|
|
file_dialog_mock.selectedFiles.return_value = (sample_pdf,)
|
|
content_widget.doc_selection_widget.file_dialog = file_dialog_mock
|
|
|
|
# Select first file
|
|
with qtbot.waitSignal(content_widget.documents_added):
|
|
qtbot.mouseClick(
|
|
content_widget.doc_selection_widget.dangerous_doc_button,
|
|
QtCore.Qt.MouseButton.LeftButton,
|
|
)
|
|
file_dialog_mock.accept()
|
|
|
|
# Setup doc change
|
|
shutil.copy(sample_doc, tmp_path)
|
|
tmp_sample_doc = tmp_path / os.path.basename(sample_doc)
|
|
file_dialog_mock.selectedFiles.return_value = (tmp_sample_doc,)
|
|
|
|
# When clicking on "select docs" button
|
|
with qtbot.waitSignal(content_widget.documents_added):
|
|
qtbot.mouseClick(
|
|
content_widget.settings_widget.change_selection_button,
|
|
QtCore.Qt.MouseButton.LeftButton,
|
|
)
|
|
file_dialog_mock.accept()
|
|
|
|
# Then two dialogs should have been open
|
|
assert file_dialog_mock.exec.call_count == 2
|
|
assert file_dialog_mock.selectedFiles.call_count == 2
|
|
|
|
# Then the final document should be only the second one
|
|
docs = [
|
|
doc.input_filename
|
|
for doc in content_widget.dangerzone.get_unconverted_documents()
|
|
]
|
|
assert len(docs) == 1
|
|
assert docs[0] == str(tmp_sample_doc)
|
|
|
|
|
|
def test_drop_valid_documents(
|
|
content_widget: ContentWidget,
|
|
drag_valid_files_event: QtGui.QDropEvent,
|
|
qtbot: QtBot,
|
|
) -> None:
|
|
with qtbot.waitSignal(
|
|
content_widget.doc_selection_wrapper.documents_selected,
|
|
check_params_cb=lambda x: len(x) == 2 and isinstance(x[0], Document),
|
|
):
|
|
content_widget.doc_selection_wrapper.dropEvent(drag_valid_files_event)
|
|
|
|
|
|
def test_drop_text(
|
|
content_widget: ContentWidget,
|
|
drag_text_event: QtGui.QDropEvent,
|
|
qtbot: QtBot,
|
|
) -> None:
|
|
with qtbot.assertNotEmitted(
|
|
content_widget.doc_selection_wrapper.documents_selected
|
|
):
|
|
content_widget.doc_selection_wrapper.dropEvent(drag_text_event)
|
|
|
|
|
|
def test_drop_1_invalid_doc(
|
|
content_widget: ContentWidget,
|
|
drag_1_invalid_file_event: QtGui.QDropEvent,
|
|
qtbot: QtBot,
|
|
) -> None:
|
|
with qtbot.assertNotEmitted(
|
|
content_widget.doc_selection_wrapper.documents_selected
|
|
):
|
|
content_widget.doc_selection_wrapper.dropEvent(drag_1_invalid_file_event)
|
|
|
|
|
|
def test_drop_1_invalid_2_valid_documents(
|
|
content_widget: ContentWidget,
|
|
drag_1_invalid_and_2_valid_files_event: QtGui.QDropEvent,
|
|
qtbot: QtBot,
|
|
monkeypatch: MonkeyPatch,
|
|
) -> None:
|
|
# If we accept to continue
|
|
monkeypatch.setattr(
|
|
content_widget.doc_selection_wrapper, "prompt_continue_without", lambda x: True
|
|
)
|
|
|
|
# Then the 2 valid docs will be selected
|
|
with qtbot.waitSignal(
|
|
content_widget.doc_selection_wrapper.documents_selected,
|
|
check_params_cb=lambda x: len(x) == 2 and isinstance(x[0], Document),
|
|
):
|
|
content_widget.doc_selection_wrapper.dropEvent(
|
|
drag_1_invalid_and_2_valid_files_event
|
|
)
|
|
|
|
# If we refuse to continue
|
|
monkeypatch.setattr(
|
|
content_widget.doc_selection_wrapper, "prompt_continue_without", lambda x: False
|
|
)
|
|
|
|
# Then no docs will be selected
|
|
with qtbot.assertNotEmitted(
|
|
content_widget.doc_selection_wrapper.documents_selected,
|
|
):
|
|
content_widget.doc_selection_wrapper.dropEvent(
|
|
drag_1_invalid_and_2_valid_files_event
|
|
)
|
|
|
|
|
|
def test_not_available_container_tech_exception(
|
|
qtbot: QtBot, mocker: MockerFixture
|
|
) -> None:
|
|
# Setup
|
|
mock_app = mocker.MagicMock()
|
|
dummy = Dummy()
|
|
fn = mocker.patch.object(dummy, "is_available")
|
|
fn.side_effect = errors.NotAvailableContainerTechException(
|
|
"podman", "podman image ls logs"
|
|
)
|
|
|
|
dz = DangerzoneGui(mock_app, dummy)
|
|
widget = WaitingWidgetContainer(dz)
|
|
qtbot.addWidget(widget)
|
|
|
|
# Assert that the error is displayed in the GUI
|
|
if platform.system() in ["Darwin", "Windows"]:
|
|
assert "Dangerzone requires Docker Desktop" in widget.label.text()
|
|
else:
|
|
assert "Podman is installed but cannot run properly" in widget.label.text()
|
|
|
|
assert "podman image ls logs" in widget.traceback.toPlainText()
|
|
|
|
|
|
def test_no_container_tech_exception(qtbot: QtBot, mocker: MockerFixture) -> None:
|
|
# Setup
|
|
mock_app = mocker.MagicMock()
|
|
dummy = mocker.MagicMock()
|
|
|
|
# Raise
|
|
dummy.is_available.side_effect = errors.NoContainerTechException("podman")
|
|
|
|
dz = DangerzoneGui(mock_app, dummy)
|
|
widget = WaitingWidgetContainer(dz)
|
|
qtbot.addWidget(widget)
|
|
|
|
# Assert that the error is displayed in the GUI
|
|
if platform.system() in ["Darwin", "Windows"]:
|
|
assert "Dangerzone requires Docker Desktop" in widget.label.text()
|
|
else:
|
|
assert "Dangerzone requires Podman" in widget.label.text()
|
|
|
|
|
|
def test_installation_failure_exception(qtbot: QtBot, mocker: MockerFixture) -> None:
|
|
"""Ensures that if an exception is raised during image installation,
|
|
it is shown in the GUI.
|
|
"""
|
|
# Setup install to raise an exception
|
|
mock_app = mocker.MagicMock()
|
|
dummy = mocker.MagicMock(spec=Container)
|
|
dummy.install.side_effect = RuntimeError("Error during install")
|
|
|
|
dz = DangerzoneGui(mock_app, dummy)
|
|
|
|
# Mock the InstallContainerThread to call the original run method instead of
|
|
# starting a new thread
|
|
mocker.patch.object(InstallContainerThread, "start", InstallContainerThread.run)
|
|
widget = WaitingWidgetContainer(dz)
|
|
qtbot.addWidget(widget)
|
|
|
|
assert dummy.install.call_count == 1
|
|
|
|
assert "Error during install" in widget.traceback.toPlainText()
|
|
assert "RuntimeError" in widget.traceback.toPlainText()
|
|
|
|
|
|
def test_installation_failure_return_false(qtbot: QtBot, mocker: MockerFixture) -> None:
|
|
"""Ensures that if the installation returns False, the error is shown in the GUI."""
|
|
# Setup install to return False
|
|
mock_app = mocker.MagicMock()
|
|
dummy = mocker.MagicMock(spec=Container)
|
|
dummy.install.return_value = False
|
|
|
|
dz = DangerzoneGui(mock_app, dummy)
|
|
|
|
# Mock the InstallContainerThread to call the original run method instead of
|
|
# starting a new thread
|
|
mocker.patch.object(InstallContainerThread, "start", InstallContainerThread.run)
|
|
widget = WaitingWidgetContainer(dz)
|
|
qtbot.addWidget(widget)
|
|
|
|
assert dummy.install.call_count == 1
|
|
|
|
assert "the following error occured" in widget.label.text()
|
|
assert "The image cannot be found" in widget.traceback.toPlainText()
|
|
|
|
|
|
def test_up_to_date_docker_desktop_does_nothing(
|
|
qtbot: QtBot, mocker: MockerFixture
|
|
) -> None:
|
|
# Setup install to return False
|
|
mock_app = mocker.MagicMock()
|
|
dummy = mocker.MagicMock(spec=Container)
|
|
dummy.check_docker_desktop_version.return_value = (True, "1.0.0")
|
|
dz = DangerzoneGui(mock_app, dummy)
|
|
|
|
window = MainWindow(dz)
|
|
qtbot.addWidget(window)
|
|
|
|
menu_actions = window.hamburger_button.menu().actions()
|
|
assert "Docker Desktop should be upgraded" not in [
|
|
a.toolTip() for a in menu_actions
|
|
]
|
|
|
|
|
|
def test_outdated_docker_desktop_displays_warning(
|
|
qtbot: QtBot, mocker: MockerFixture
|
|
) -> None:
|
|
# Setup install to return False
|
|
mock_app = mocker.MagicMock()
|
|
dummy = mocker.MagicMock(spec=Container)
|
|
dummy.check_docker_desktop_version.return_value = (False, "1.0.0")
|
|
|
|
dz = DangerzoneGui(mock_app, dummy)
|
|
|
|
load_svg_spy = mocker.spy(main_window_module, "load_svg_image")
|
|
|
|
window = MainWindow(dz)
|
|
qtbot.addWidget(window)
|
|
|
|
menu_actions = window.hamburger_button.menu().actions()
|
|
assert menu_actions[0].toolTip() == "Docker Desktop should be upgraded"
|
|
|
|
# Check that the hamburger icon has changed with the expected SVG image.
|
|
assert load_svg_spy.call_count == 4
|
|
assert (
|
|
load_svg_spy.call_args_list[2].args[0] == "hamburger_menu_update_dot_error.svg"
|
|
)
|
|
|
|
alert_spy = mocker.spy(window.alert, "launch")
|
|
|
|
# Clicking the menu item should open a warning message
|
|
def _check_alert_displayed() -> None:
|
|
alert_spy.assert_any_call()
|
|
if window.alert:
|
|
window.alert.close()
|
|
|
|
QtCore.QTimer.singleShot(0, _check_alert_displayed)
|
|
menu_actions[0].trigger()
|