You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LightWork3D/tests/python/freecad_exchange_template_a...

210 lines
6.7 KiB
Python

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:
def __init__(self, axis=None, angle=None):
self.Axis = axis
self.Angle = angle
class Placement:
def __init__(self, base=None, rotation=None):
self.Base = base
self.Rotation = 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
fake_freecadgui = types.ModuleType("FreeCADGui")
fake_freecadgui.addCommand = lambda *args, **kwargs: None
fake_freecadgui.Selection = types.SimpleNamespace(getSelectionEx=lambda: [])
sys.modules["FreeCADGui"] = fake_freecadgui
def _install_fake_freecad_without_gui_commands():
_install_fake_freecad()
sys.modules["FreeCADGui"] = types.ModuleType("FreeCADGui")
class FakeViewObject:
def __init__(self):
self.Visibility = True
self.ShapeColor = None
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.Placement = None
def isDerivedFrom(self, type_name):
if self.TypeId == type_name:
return True
if type_name == "App::DocumentObjectGroup":
return self.TypeId == "App::DocumentObjectGroup"
if type_name == "App::LocalCoordinateSystem":
return self.TypeId in {
"Part::LocalCoordinateSystem",
"PartDesign::CoordinateSystem",
}
return False
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)
class FakeDocument:
def __init__(self):
self.Name = "TemplateDoc"
self.Objects = []
self.recomputed = False
self.saved_path = ""
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 recompute(self):
self.recomputed = True
def saveAs(self, path):
self.saved_path = path
def _reload_modules():
for name in ["TerminalObjects", "TemplateAuthoring"]:
sys.modules.pop(name, None)
return importlib.import_module("TemplateAuthoring")
class TemplateAuthoringTest(unittest.TestCase):
def test_template_authoring_command_titles_are_chinese(self):
_install_fake_freecad()
template_authoring = _reload_modules()
self.assertEqual(
"添加模板端子",
template_authoring.CommandAddTemplateTerminal().GetResources()["MenuText"],
)
self.assertEqual(
"校验模板端子",
template_authoring.CommandValidateTemplateTerminals().GetResources()["MenuText"],
)
self.assertEqual(
"保存模板为 FCStd",
template_authoring.CommandSaveTemplateAsFCStd().GetResources()["MenuText"],
)
def test_import_skips_command_registration_when_gui_has_no_add_command(self):
_install_fake_freecad_without_gui_commands()
template_authoring = _reload_modules()
self.assertTrue(hasattr(template_authoring, "save_template_as_fcstd"))
def test_create_template_terminal_writes_lcs_semantics(self):
_install_fake_freecad()
template_authoring = _reload_modules()
app = sys.modules["FreeCAD"]
doc = FakeDocument()
terminal = template_authoring.create_template_terminal(
doc,
"P1",
app.Vector(10, 20, 30),
terminal_type="primary",
)
self.assertEqual("Terminal_P1", terminal.Name)
self.assertEqual("P1", terminal.Label)
self.assertEqual("Terminal", terminal.Role)
self.assertTrue(terminal.CanWire)
self.assertEqual("P1", terminal.QetTemplateSlotName)
self.assertEqual("P1", terminal.QetTerminalLabel)
self.assertEqual("primary", terminal.QetTerminalType)
self.assertEqual(10.0, terminal.Placement.Base.x)
self.assertEqual(20.0, terminal.Placement.Base.y)
self.assertEqual(30.0, terminal.Placement.Base.z)
self.assertTrue(doc.recomputed)
def test_validate_template_terminals_reports_missing_slot_name(self):
_install_fake_freecad()
template_authoring = _reload_modules()
doc = FakeDocument()
terminal = doc.addObject("Part::LocalCoordinateSystem", "BrokenTerminal")
terminal.addProperty("App::PropertyString", "Role", "QET Template", "role")
terminal.Role = "Terminal"
terminal.addProperty(
"App::PropertyBool",
"CanWire",
"QET Template",
"can wire",
)
terminal.CanWire = True
report = template_authoring.validate_template_terminals(doc)
self.assertEqual(1, report["total_terminals"])
self.assertEqual(0, report["valid_terminals"])
self.assertEqual(1, len(report["warnings"]))
self.assertIn("QetTemplateSlotName", report["warnings"][0])
def test_save_template_as_fcstd_adds_extension_and_saves_valid_template(self):
_install_fake_freecad()
template_authoring = _reload_modules()
app = sys.modules["FreeCAD"]
doc = FakeDocument()
template_authoring.create_template_terminal(doc, "P1", app.Vector(1, 2, 3))
report = template_authoring.save_template_as_fcstd(doc, "D:/tmp/current-transformer")
self.assertEqual("D:/tmp/current-transformer.FCStd", doc.saved_path)
self.assertEqual("D:/tmp/current-transformer.FCStd", report["path"])
self.assertEqual(1, report["valid_terminals"])
if __name__ == "__main__":
unittest.main()