import importlib.util import sys import tempfile import unittest from pathlib import Path import types def _install_pyside6_stubs(): if "PySide6" in sys.modules: return pyside6_module = types.ModuleType("PySide6") qtcore_module = types.ModuleType("PySide6.QtCore") qtgui_module = types.ModuleType("PySide6.QtGui") qtwidgets_module = types.ModuleType("PySide6.QtWidgets") class _Signal: def __init__(self, *args, **kwargs): pass def connect(self, *args, **kwargs): pass class _QObject: pass class _QThread: def __init__(self, *args, **kwargs): pass class _QTimer: @staticmethod def singleShot(*args, **kwargs): pass class _QUrl: @staticmethod def fromLocalFile(path): return path class _QDesktopServices: @staticmethod def openUrl(*args, **kwargs): return True class _Widget: def __init__(self, *args, **kwargs): pass qtcore_module.QObject = _QObject qtcore_module.Qt = type("Qt", (), {}) qtcore_module.QThread = _QThread qtcore_module.Signal = _Signal qtcore_module.QTimer = _QTimer qtcore_module.QUrl = _QUrl qtgui_module.QDesktopServices = _QDesktopServices qtwidgets_module.QApplication = _Widget qtwidgets_module.QLabel = _Widget qtwidgets_module.QProgressBar = _Widget qtwidgets_module.QVBoxLayout = _Widget qtwidgets_module.QWidget = _Widget qtwidgets_module.QPushButton = _Widget qtwidgets_module.QHBoxLayout = _Widget sys.modules["PySide6"] = pyside6_module sys.modules["PySide6.QtCore"] = qtcore_module sys.modules["PySide6.QtGui"] = qtgui_module sys.modules["PySide6.QtWidgets"] = qtwidgets_module MODULE_PATH = Path("updater_gui.py") _install_pyside6_stubs() SPEC = importlib.util.spec_from_file_location("updater_gui_under_test", MODULE_PATH) updater_gui = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(updater_gui) class UpdaterGuiTests(unittest.TestCase): def test_read_version_marker(self): with tempfile.TemporaryDirectory() as tmp_dir: marker = Path(tmp_dir) / "version.txt" marker.write_text("2.0.1\n", encoding="utf-8") value = updater_gui._read_version_marker(tmp_dir) self.assertEqual(value, "2.0.1") def test_mirror_tree_skips_selected_file(self): with tempfile.TemporaryDirectory() as src_tmp, tempfile.TemporaryDirectory() as dst_tmp: src = Path(src_tmp) dst = Path(dst_tmp) (src / "keep.txt").write_text("ok", encoding="utf-8") (src / "skip.bin").write_text("x", encoding="utf-8") (src / "sub").mkdir() (src / "sub" / "nested.txt").write_text("nested", encoding="utf-8") updater_gui._mirror_tree(str(src), str(dst), skip_names={"skip.bin"}) self.assertTrue((dst / "keep.txt").exists()) self.assertTrue((dst / "sub" / "nested.txt").exists()) self.assertFalse((dst / "skip.bin").exists()) if __name__ == "__main__": unittest.main()