AddonManager: Refactor uninstaller GUI
Offload uninstaller GUI into its own class, add tests for that class, and do some additional minor cleanup of AddonManager.py.
This commit is contained in:
@@ -25,15 +25,25 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import FreeCAD
|
||||
|
||||
|
||||
class MockAddon:
|
||||
"""Minimal Addon class"""
|
||||
|
||||
def __init__(self):
|
||||
self.name = "TestAddon"
|
||||
self.url = "https://github.com/FreeCAD/FreeCAD-addons"
|
||||
self.branch = "master"
|
||||
test_dir = os.path.join(
|
||||
FreeCAD.getHomePath(), "Mod", "AddonManager", "AddonManagerTest", "data"
|
||||
)
|
||||
self.name = "MockAddon"
|
||||
self.display_name = "Mock Addon"
|
||||
self.url = os.path.join(test_dir, "test_simple_repo.zip")
|
||||
self.branch = "main"
|
||||
self.macro = None
|
||||
self.status = None
|
||||
|
||||
def set_status(self, status):
|
||||
self.status = status
|
||||
|
||||
|
||||
class MockMacro:
|
||||
|
||||
@@ -33,7 +33,7 @@ from addonmanager_dependency_installer import DependencyInstaller
|
||||
class CompleteProcessMock(subprocess.CompletedProcess):
|
||||
def __init__(self):
|
||||
super().__init__(["fake_arg"], 0)
|
||||
self.stdout = "Mock suprocess call stdout result"
|
||||
self.stdout = "Mock subprocess call stdout result"
|
||||
|
||||
|
||||
class SubprocessMock:
|
||||
|
||||
@@ -115,7 +115,7 @@ class TestAddonInstaller(unittest.TestCase):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
installer.installation_path = temp_dir
|
||||
installer._update_metadata()
|
||||
addon_dir = os.path.join(temp_dir, self.mock_addon.name)
|
||||
addon_dir = os.path.join(temp_dir, self.real_addon.name)
|
||||
os.mkdir(addon_dir)
|
||||
shutil.copy(
|
||||
os.path.join(self.test_data_dir, "good_package.xml"),
|
||||
@@ -125,7 +125,7 @@ class TestAddonInstaller(unittest.TestCase):
|
||||
installer._update_metadata()
|
||||
self.assertEqual(self.real_addon.installed_version, good_metadata.Version)
|
||||
|
||||
def test_finalize_zip_installation(self):
|
||||
def test_finalize_zip_installation_non_github(self):
|
||||
"""Ensure that zipfiles are correctly extracted."""
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
test_simple_repo = os.path.join(self.test_data_dir, "test_simple_repo.zip")
|
||||
@@ -140,12 +140,15 @@ class TestAddonInstaller(unittest.TestCase):
|
||||
os.path.isfile(expected_location), "Non-GitHub zip extraction failed"
|
||||
)
|
||||
|
||||
def test_finalize_zip_installation_github(self):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
test_github_style_repo = os.path.join(
|
||||
self.test_data_dir, "test_github_style_repo.zip"
|
||||
)
|
||||
installer = AddonInstaller(self.mock_addon, [])
|
||||
installer.installation_path = temp_dir
|
||||
self.mock_addon.url = test_github_style_repo
|
||||
self.mock_addon.branch = "master"
|
||||
installer._finalize_zip_installation(test_github_style_repo)
|
||||
expected_location = os.path.join(temp_dir, self.mock_addon.name, "README")
|
||||
self.assertTrue(
|
||||
|
||||
@@ -184,19 +184,22 @@ static char * blarg_xpm[] = {
|
||||
return m
|
||||
|
||||
def test_fetch_raw_code_no_data(self):
|
||||
|
||||
class MockNetworkManagerNoData():
|
||||
class MockNetworkManagerNoData:
|
||||
def __init__(self):
|
||||
self.fetched_url = None
|
||||
|
||||
def blocking_get(self, url):
|
||||
self.fetched_url = url
|
||||
return None
|
||||
|
||||
nmNoData = MockNetworkManagerNoData()
|
||||
m = Macro("Unit Test Macro")
|
||||
Macro.network_manager = nmNoData
|
||||
returned_data = m._fetch_raw_code("rawcodeurl <a href=\"https://fake_url.com\">Totally fake</a>")
|
||||
returned_data = m._fetch_raw_code(
|
||||
'rawcodeurl <a href="https://fake_url.com">Totally fake</a>'
|
||||
)
|
||||
self.assertIsNone(returned_data)
|
||||
self.assertEqual(nmNoData.fetched_url,"https://fake_url.com")
|
||||
self.assertEqual(nmNoData.fetched_url, "https://fake_url.com")
|
||||
|
||||
nmNoData.fetched_url = None
|
||||
returned_data = m._fetch_raw_code("Fake pagedata with no URL at all.")
|
||||
@@ -206,13 +209,14 @@ static char * blarg_xpm[] = {
|
||||
Macro.network_manager = None
|
||||
|
||||
def test_fetch_raw_code_with_data(self):
|
||||
|
||||
class MockNetworkManagerWithData():
|
||||
class MockNetworkManagerWithData:
|
||||
class MockQByteArray:
|
||||
def data(self):
|
||||
return "Data returned to _fetch_raw_code".encode("utf-8")
|
||||
|
||||
def __init__(self):
|
||||
self.fetched_url = None
|
||||
|
||||
def blocking_get(self, url):
|
||||
self.fetched_url = url
|
||||
return MockNetworkManagerWithData.MockQByteArray()
|
||||
@@ -220,7 +224,9 @@ static char * blarg_xpm[] = {
|
||||
nmWithData = MockNetworkManagerWithData()
|
||||
m = Macro("Unit Test Macro")
|
||||
Macro.network_manager = nmWithData
|
||||
returned_data = m._fetch_raw_code("rawcodeurl <a href=\"https://fake_url.com\">Totally fake</a>")
|
||||
self.assertEqual(returned_data,"Data returned to _fetch_raw_code")
|
||||
returned_data = m._fetch_raw_code(
|
||||
'rawcodeurl <a href="https://fake_url.com">Totally fake</a>'
|
||||
)
|
||||
self.assertEqual(returned_data, "Data returned to _fetch_raw_code")
|
||||
|
||||
Macro.network_manager = None
|
||||
|
||||
@@ -449,10 +449,15 @@ class TestMacroUninstaller(unittest.TestCase):
|
||||
self.assertTrue(os.path.exists(f))
|
||||
os.chmod(f, S_IREAD | S_IRGRP | S_IROTH)
|
||||
self.test_object.run()
|
||||
os.chmod(f, S_IWUSR | S_IREAD)
|
||||
|
||||
self.assertIn("failure", self.signals_caught)
|
||||
self.assertNotIn("success", self.signals_caught)
|
||||
if os.path.exists(f):
|
||||
os.chmod(f, S_IWUSR | S_IREAD)
|
||||
self.assertNotIn("success", self.signals_caught)
|
||||
self.assertIn("failure", self.signals_caught)
|
||||
else:
|
||||
# In some cases we managed to delete it anyway:
|
||||
self.assertIn("success", self.signals_caught)
|
||||
self.assertNotIn("failure", self.signals_caught)
|
||||
self.assertIn("finished", self.signals_caught)
|
||||
|
||||
def test_cleanup_directories_multiple_empty(self):
|
||||
|
||||
Reference in New Issue
Block a user