Addon Manager: Fix test language dependency

Fixes #8065
This commit is contained in:
Chris Hennes
2022-12-20 10:07:14 -06:00
parent fd35950ec8
commit 4db688771a
3 changed files with 103 additions and 40 deletions

View File

@@ -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):

View File

@@ -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

View File

@@ -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(