import importlib import sys import types import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] MODULE_DIR = REPO_ROOT / "src" / "Mod" / "FreeCADExchange" if str(MODULE_DIR) not in sys.path: sys.path.insert(0, str(MODULE_DIR)) def _install_fake_freecad(): class Vector: def __init__(self, x=0.0, y=0.0, z=0.0): self.x = float(x) self.y = float(y) self.z = float(z) class Rotation: pass class Placement: def __init__(self, base=None, rotation=None): self.Base = base or Vector() self.Rotation = rotation or Rotation() fake_freecad = types.ModuleType("FreeCAD") fake_freecad.Vector = Vector fake_freecad.Rotation = Rotation fake_freecad.Placement = Placement fake_freecad.ActiveDocument = None fake_freecad.Console = types.SimpleNamespace( PrintMessage=lambda *args, **kwargs: None, PrintWarning=lambda *args, **kwargs: None, PrintError=lambda *args, **kwargs: None, ) sys.modules["FreeCAD"] = fake_freecad class FakeViewObject: def __init__(self): self.Visibility = True class FakeObject: def __init__(self, name, type_id): self.Name = name self.Label = name self.TypeId = type_id self.PropertiesList = [] self.Group = [] self.ViewObject = FakeViewObject() self.InList = [] def isDerivedFrom(self, type_name): return self.TypeId == type_name def addProperty(self, prop_type, prop_name, group_name, description): if prop_name not in self.PropertiesList: self.PropertiesList.append(prop_name) def addObject(self, child): if child not in self.Group: self.Group.append(child) if self not in child.InList: child.InList.append(self) class FakeDocument: def __init__(self): self.Objects = [] self.Name = "FakeDoc" def addObject(self, type_name, name): obj = FakeObject(name, type_name) self.Objects.append(obj) return obj def getObject(self, name): for obj in self.Objects: if obj.Name == name: return obj return None def _reload_modules(): for name in ["TerminalObjects", "WiringObjects", "WiringImport"]: sys.modules.pop(name, None) terminal_objects = importlib.import_module("TerminalObjects") wiring_objects = importlib.import_module("WiringObjects") wiring_import = importlib.import_module("WiringImport") return terminal_objects, wiring_objects, wiring_import class WiringImportTest(unittest.TestCase): def test_import_wire_tasks_creates_and_updates_qet_tasks(self): _install_fake_freecad() terminal_objects, _wiring_objects, wiring_import = _reload_modules() doc = FakeDocument() terminal_objects.ensure_root_group(doc, "project-1") payload = { "project_uuid": "project-1", "devices": [ {"element_uuid": "device-a", "display_tag": "TAa"}, {"element_uuid": "device-b", "display_tag": "PEN001"}, ], "wires": [ { "wire_id": "wire-1", "net_uuid": "net-1", "group_uuid": "group-1", "wire_mark": "W001", "wire_mark_is_manual": True, "start_element_uuid": "device-a", "start_terminal_uuid": "terminal-a", "end_element_uuid": "device-b", "end_terminal_uuid": "terminal-b", "start_terminal_display": "A1", "end_terminal_display": "B1", "conductor_uuids": ["conductor-1"], } ], } report = wiring_import.import_wire_tasks_from_payload(payload, doc) task_group = doc.getObject("QETWiring_01_Tasks") self.assertIsNotNone(task_group) self.assertEqual(1, report["imported_tasks"]) self.assertEqual(0, report["updated_tasks"]) self.assertEqual(1, len(task_group.Group)) task = task_group.Group[0] self.assertEqual("wire-1", task.QetWireUuid) self.assertEqual("net-1", task.QetNetUuid) self.assertEqual("group-1", task.QetGroupUuid) self.assertEqual("W001", task.QetWireMark) self.assertTrue(task.QetWireMarkIsManual) self.assertEqual("terminal-a", task.QetStartTerminalUuid) self.assertEqual("terminal-b", task.QetEndTerminalUuid) self.assertEqual("device-a", task.QetStartElementUuid) self.assertEqual("device-b", task.QetEndElementUuid) self.assertEqual("A1", task.QetStartTerminalDisplay) self.assertEqual("B1", task.QetEndTerminalDisplay) self.assertEqual("TAa:A1 -> PEN001:B1", task.QetEndpointLabel) self.assertIn("TAa:A1 -> PEN001:B1", task.Label) self.assertIn("conductor-1", task.QetConductorUuidsJson) self.assertEqual("Task", task.RouteType) self.assertEqual("Task", task.RouteStatus) payload["wires"][0]["wire_mark"] = "W001-updated" task.RouteStatus = "Routed" second_report = wiring_import.import_wire_tasks_from_payload(payload, doc) self.assertEqual(0, second_report["imported_tasks"]) self.assertEqual(1, second_report["updated_tasks"]) self.assertEqual(1, len(task_group.Group)) self.assertEqual("W001-updated", task_group.Group[0].QetWireMark) self.assertEqual("Routed", task_group.Group[0].RouteStatus) if __name__ == "__main__": unittest.main()