@@ -26,14 +26,23 @@ from PySide import QtCore, QtWidgets
|
||||
class DialogWatcher(QtCore.QObject):
|
||||
"""Examine the running GUI and look for a modal dialog with a given title, containing a button
|
||||
with a given label. Click that button, which is expected to close the dialog. Generally run on
|
||||
a one-shot QTimer to allow the dialog time to open up."""
|
||||
a one-shot QTimer to allow the dialog time to open up. If the specified dialog is found, but
|
||||
it does not contain the expected button, button_found will be false, and the dialog will be
|
||||
closed with a reject() slot."""
|
||||
|
||||
def __init__(self, dialog_to_watch_for, button):
|
||||
def __init__(self, dialog_to_watch_for, button=QtWidgets.QDialogButtonBox.NoButton):
|
||||
super().__init__()
|
||||
|
||||
# Status variables for tests to check:
|
||||
self.dialog_found = False
|
||||
self.has_run = False
|
||||
self.button_found = False
|
||||
|
||||
self.dialog_to_watch_for = dialog_to_watch_for
|
||||
self.button = button
|
||||
if button != QtWidgets.QDialogButtonBox.NoButton:
|
||||
self.button = button
|
||||
else:
|
||||
self.button = QtWidgets.QDialogButtonBox.Cancel
|
||||
|
||||
def run(self):
|
||||
widget = QtWidgets.QApplication.activeModalWidget()
|
||||
@@ -50,11 +59,16 @@ class DialogWatcher(QtCore.QObject):
|
||||
self.has_run = True
|
||||
|
||||
def click_button(self, widget):
|
||||
buttons = widget.findChildren(QtWidgets.QPushButton)
|
||||
for button in buttons:
|
||||
text = button.text().replace("&", "")
|
||||
if text == self.button:
|
||||
button.click()
|
||||
button_boxes = widget.findChildren(QtWidgets.QDialogButtonBox)
|
||||
if len(button_boxes) == 1: # There should be one, and only one
|
||||
button_to_click = button_boxes[0].button(self.button)
|
||||
if button_to_click:
|
||||
self.button_found = True
|
||||
button_to_click.click()
|
||||
else:
|
||||
widget.reject()
|
||||
else:
|
||||
widget.reject()
|
||||
|
||||
|
||||
class DialogInteractor(DialogWatcher):
|
||||
|
||||
@@ -50,19 +50,23 @@ class TestInstallerGui(unittest.TestCase):
|
||||
def test_success_dialog(self):
|
||||
# Pop the modal dialog and verify that it opens, and responds to an OK click
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Success"), translate("AddonsInstaller", "OK")
|
||||
translate("AddonsInstaller", "Success"),
|
||||
QtWidgets.QDialogButtonBox.Ok,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._installation_succeeded()
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_failure_dialog(self):
|
||||
# Pop the modal dialog and verify that it opens, and responds to a Cancel click
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Installation Failed"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._installation_failed(
|
||||
@@ -71,36 +75,45 @@ class TestInstallerGui(unittest.TestCase):
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_no_python_dialog(self):
|
||||
# Pop the modal dialog and verify that it opens, and responds to a No click
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Cannot execute Python"),
|
||||
translate("AddonsInstaller", "No"),
|
||||
QtWidgets.QDialogButtonBox.No,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._report_no_python_exe()
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_no_pip_dialog(self):
|
||||
# Pop the modal dialog and verify that it opens, and responds to a No click
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Cannot execute pip"),
|
||||
translate("AddonsInstaller", "No"),
|
||||
QtWidgets.QDialogButtonBox.No,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._report_no_pip("pip not actually run, this was a test")
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_dependency_failure_dialog(self):
|
||||
# Pop the modal dialog and verify that it opens, and responds to a No click
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Package installation failed"),
|
||||
translate("AddonsInstaller", "No"),
|
||||
QtWidgets.QDialogButtonBox.No,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._report_dependency_failure(
|
||||
@@ -109,6 +122,9 @@ class TestInstallerGui(unittest.TestCase):
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_install(self):
|
||||
# Run the installation code and make sure it puts the directory in place
|
||||
@@ -132,13 +148,16 @@ class TestInstallerGui(unittest.TestCase):
|
||||
disallowed_packages = ["disallowed_package_name"]
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Missing Requirement"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._handle_disallowed_python(disallowed_packages)
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_handle_disallowed_python_long_list(self):
|
||||
"""A separate test for when there are MANY packages, which takes a separate code path."""
|
||||
@@ -147,39 +166,48 @@ class TestInstallerGui(unittest.TestCase):
|
||||
disallowed_packages.append(f"disallowed_package_name_{i}")
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Missing Requirement"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._handle_disallowed_python(disallowed_packages)
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_report_missing_workbenches_single(self):
|
||||
"""Test only missing one workbench"""
|
||||
wbs = ["OneMissingWorkbench"]
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Missing Requirement"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._report_missing_workbenches(wbs)
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_report_missing_workbenches_multiple(self):
|
||||
"""Test only missing one workbench"""
|
||||
wbs = ["FirstMissingWorkbench", "SecondMissingWorkbench"]
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Missing Requirement"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._report_missing_workbenches(wbs)
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_resolve_dependencies_then_install(self):
|
||||
class MissingDependenciesMock:
|
||||
@@ -190,14 +218,17 @@ class TestInstallerGui(unittest.TestCase):
|
||||
|
||||
missing = MissingDependenciesMock()
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Resolve Dependencies"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
translate("DependencyResolutionDialog", "Resolve Dependencies"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer_gui._resolve_dependencies_then_install(missing)
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_check_python_version_bad(self):
|
||||
class MissingDependenciesMock:
|
||||
@@ -207,13 +238,16 @@ class TestInstallerGui(unittest.TestCase):
|
||||
missing = MissingDependenciesMock()
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Incompatible Python version"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
stop_installing = self.installer_gui._check_python_version(missing)
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
self.assertTrue(
|
||||
stop_installing, "Failed to halt installation on bad Python version"
|
||||
)
|
||||
@@ -427,8 +461,8 @@ class TestMacroInstallerGui(unittest.TestCase):
|
||||
# First test: the user cancels the dialog
|
||||
self.installer.addon_params.set("alwaysAskForToolbar", True)
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Select Toolbar"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
translate("select_toolbar_dialog", "Select Toolbar"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
result = self.installer._ask_for_toolbar([])
|
||||
@@ -440,17 +474,12 @@ class TestMacroInstallerGui(unittest.TestCase):
|
||||
# - The checkbox "Ask every time" is unchecked
|
||||
# - The selected toolbar option is "Create new toolbar", which triggers a search for
|
||||
# a new custom toolbar name by calling _create_new_custom_toolbar, which we mock.
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Select Toolbar"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
fake_custom_toolbar_group = TestMacroInstallerGui.MockParameter()
|
||||
fake_custom_toolbar_group.set("Name", "UnitTestCustomToolbar")
|
||||
self.installer._create_new_custom_toolbar = lambda: fake_custom_toolbar_group
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Select Toolbar"),
|
||||
translate("AddonsInstaller", "OK"),
|
||||
translate("select_toolbar_dialog", "Select Toolbar"),
|
||||
QtWidgets.QDialogButtonBox.Ok,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
result = self.installer._ask_for_toolbar([])
|
||||
@@ -460,13 +489,16 @@ class TestMacroInstallerGui(unittest.TestCase):
|
||||
self.assertEqual(name, "UnitTestCustomToolbar")
|
||||
self.assertIn("alwaysAskForToolbar", self.installer.addon_params.params)
|
||||
self.assertFalse(self.installer.addon_params.get("alwaysAskForToolbar", True))
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_ask_for_toolbar_with_dialog_selection(self):
|
||||
|
||||
# Third test: the user selects a custom toolbar in the dialog, and checks the box to always
|
||||
# ask.
|
||||
dialog_interactor = DialogInteractor(
|
||||
translate("AddonsInstaller", "Select Toolbar"),
|
||||
translate("select_toolbar_dialog", "Select Toolbar"),
|
||||
self.interactor_selection_option_and_checkbox,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_interactor.run)
|
||||
@@ -526,8 +558,8 @@ class TestMacroInstallerGui(unittest.TestCase):
|
||||
def test_ask_to_install_toolbar_button_enabled_no(self):
|
||||
self.installer.addon_params.SetBool("dontShowAddMacroButtonDialog", False)
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Add button?"),
|
||||
translate("AddonsInstaller", "No"),
|
||||
translate("toolbar_button", "Add button?"),
|
||||
QtWidgets.QDialogButtonBox.No,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.installer._ask_to_install_toolbar_button() # Blocks until killed by watcher
|
||||
|
||||
@@ -23,13 +23,12 @@
|
||||
import functools
|
||||
import unittest
|
||||
|
||||
from PySide import QtCore
|
||||
from PySide import QtCore, QtWidgets
|
||||
|
||||
import FreeCAD
|
||||
|
||||
from AddonManagerTest.gui.gui_mocks import (
|
||||
DialogWatcher,
|
||||
DialogInteractor,
|
||||
FakeWorker,
|
||||
MockThread,
|
||||
)
|
||||
@@ -59,25 +58,31 @@ class TestUninstallerGUI(unittest.TestCase):
|
||||
def test_confirmation_dialog_yes(self):
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Confirm remove"),
|
||||
translate("AddonsInstaller", "Yes"),
|
||||
QtWidgets.QDialogButtonBox.Yes,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
answer = self.uninstaller_gui._confirm_uninstallation()
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
self.assertTrue(answer, "Expected a 'Yes' click to return True, but got False")
|
||||
|
||||
def test_confirmation_dialog_cancel(self):
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Confirm remove"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
answer = self.uninstaller_gui._confirm_uninstallation()
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
self.assertFalse(
|
||||
answer, "Expected a 'Cancel' click to return False, but got True"
|
||||
)
|
||||
@@ -85,7 +90,7 @@ class TestUninstallerGUI(unittest.TestCase):
|
||||
def test_progress_dialog(self):
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Removing Addon"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.uninstaller_gui._show_progress_dialog()
|
||||
@@ -95,12 +100,15 @@ class TestUninstallerGUI(unittest.TestCase):
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_timer_launches_progress_dialog(self):
|
||||
worker = FakeWorker()
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Removing Addon"),
|
||||
translate("AddonsInstaller", "Cancel"),
|
||||
QtWidgets.QDialogButtonBox.Cancel,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
QtCore.QTimer.singleShot(20, worker.stop)
|
||||
@@ -114,22 +122,28 @@ class TestUninstallerGUI(unittest.TestCase):
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_success_dialog(self):
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Uninstall complete"),
|
||||
translate("AddonsInstaller", "OK"),
|
||||
QtWidgets.QDialogButtonBox.Ok,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.uninstaller_gui._succeeded(self.addon_to_remove)
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_failure_dialog(self):
|
||||
dialog_watcher = DialogWatcher(
|
||||
translate("AddonsInstaller", "Uninstall failed"),
|
||||
translate("AddonsInstaller", "OK"),
|
||||
QtWidgets.QDialogButtonBox.Ok,
|
||||
)
|
||||
QtCore.QTimer.singleShot(10, dialog_watcher.run)
|
||||
self.uninstaller_gui._failed(
|
||||
@@ -138,6 +152,9 @@ class TestUninstallerGUI(unittest.TestCase):
|
||||
self.assertTrue(
|
||||
dialog_watcher.dialog_found, "Failed to find the expected dialog box"
|
||||
)
|
||||
self.assertTrue(
|
||||
dialog_watcher.button_found, "Failed to find the expected button"
|
||||
)
|
||||
|
||||
def test_finalize(self):
|
||||
self.uninstaller_gui.finished.connect(
|
||||
|
||||
Reference in New Issue
Block a user