# SPDX-License-Identifier: LGPL-2.1-or-later # *************************************************************************** # * Copyright (c) 2024 FreeCAD Team * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * # * the License, or (at your option) any later version. * # * for detail see the LICENSE text file. * # * * # * This program is distributed in the hope that it will be useful, * # * but WITHOUT ANY WARRANTY; without even the implied warranty of * # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * # * GNU Library General Public License for more details. * # * * # * You should have received a copy of the GNU Library General Public * # * License along with this program; if not, write to the Free Software * # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * # * USA * # * * # *************************************************************************** """Unit tests for the Property Editor Widgets.""" import unittest import FreeCAD from Path.Tool.docobject import DetachedDocumentObject from Path.Tool.docobject.ui.property import ( BasePropertyEditorWidget, QuantityPropertyEditorWidget, BoolPropertyEditorWidget, IntPropertyEditorWidget, EnumPropertyEditorWidget, LabelPropertyEditorWidget, ) class TestPropertyEditorFactory(unittest.TestCase): """Tests the BasePropertyEditorWidget.for_property factory method.""" def setUp(self): # Use the real DetachedDocumentObject self.obj = DetachedDocumentObject() # Add properties using the DetachedDocumentObject API with correct signature self.obj.addProperty("App::PropertyLength", "Length", "Base", "Length property") self.obj.Length = FreeCAD.Units.Quantity(10.0) # Set value separately self.obj.addProperty("App::PropertyBool", "IsEnabled", "Base", "Boolean property") self.obj.IsEnabled = True # Set value separately self.obj.addProperty("App::PropertyInt", "Count", "Base", "Integer property") self.obj.Count = 5 # Set value separately self.obj.addProperty("App::PropertyEnumeration", "Mode", "Base", "Enumeration property") # Set enums and initial value separately self.obj.Mode = ["Auto", "Manual"] self.obj.addProperty("App::PropertyString", "Comment", "Base", "String property") self.obj.Comment = "Test" # Set value separately def test_quantity_creation(self): widget = BasePropertyEditorWidget.for_property(self.obj, "Length") self.assertIsInstance(widget, QuantityPropertyEditorWidget) def test_bool_creation(self): widget = BasePropertyEditorWidget.for_property(self.obj, "IsEnabled") self.assertIsInstance(widget, BoolPropertyEditorWidget) def test_int_creation(self): widget = BasePropertyEditorWidget.for_property(self.obj, "Count") self.assertIsInstance(widget, IntPropertyEditorWidget) def test_enum_creation(self): widget = BasePropertyEditorWidget.for_property(self.obj, "Mode") self.assertIsInstance(widget, EnumPropertyEditorWidget) def test_label_creation_for_string(self): widget = BasePropertyEditorWidget.for_property(self.obj, "Comment") self.assertIsInstance(widget, LabelPropertyEditorWidget) def test_label_creation_for_invalid_prop(self): widget = BasePropertyEditorWidget.for_property(self.obj, "NonExistent") self.assertIsInstance(widget, LabelPropertyEditorWidget) class TestQuantityPropertyEditorWidget(unittest.TestCase): """Tests for QuantityPropertyEditorWidget.""" def setUp(self): self.obj = DetachedDocumentObject() self.obj.addProperty("App::PropertyLength", "Length", "Base", "Length property") self.obj.Length = FreeCAD.Units.Quantity("10.0 mm") self.widget = QuantityPropertyEditorWidget(self.obj, "Length") # Access the real editor widget self.editor = self.widget._editor_widget self.widget.updateWidget() def test_update_property(self): # Check if the real widget's value is updated self.assertEqual(self.editor.property("rawValue"), 10.0) # Check if the real widget's value and unit are updated self.assertEqual(self.editor.property("value").UserString, "10.00 mm") # Simulate changing the raw value and check if the object's value updates self.editor.lineEdit().setText("12.0") self.widget.updateProperty() self.assertEqual(self.obj.Length.Value, 12.0) self.assertEqual(self.obj.Length.UserString, "12.00 mm") # Try assignment with unit. self.editor.lineEdit().setText("15.5 in") self.widget.updateProperty() updated_value = self.obj.getPropertyByName("Length") self.assertIsInstance(updated_value, FreeCAD.Units.Quantity) self.assertEqual(updated_value, FreeCAD.Units.Quantity("15.5 in")) class TestBoolPropertyEditorWidget(unittest.TestCase): """Tests for BoolPropertyEditorWidget.""" def setUp(self): self.obj = DetachedDocumentObject() self.obj.addProperty("App::PropertyBool", "IsEnabled", "Base", "Boolean property") self.obj.IsEnabled = True self.widget = BoolPropertyEditorWidget(self.obj, "IsEnabled") # Access the real editor widget self.editor = self.widget._editor_widget def test_update_widget(self): self.widget.updateWidget() # Check if the real widget's value is updated self.assertEqual(self.editor.currentIndex(), 1) # True is index 1 self.obj.setPropertyByName("IsEnabled", False) self.widget.updateWidget() self.assertEqual(self.editor.currentIndex(), 0) # False is index 0 def test_update_property(self): # Simulate user changing value in the combobox self.editor.setCurrentIndex(0) # Select False self.widget._on_index_changed(0) self.assertEqual(self.obj.getPropertyByName("IsEnabled"), False) self.editor.setCurrentIndex(1) # Select True self.widget._on_index_changed(1) self.assertEqual(self.obj.getPropertyByName("IsEnabled"), True) class TestIntPropertyEditorWidget(unittest.TestCase): """Tests for IntPropertyEditorWidget.""" def setUp(self): self.obj = DetachedDocumentObject() self.obj.addProperty("App::PropertyInt", "Count", "Base", "Integer property") self.obj.Count = 5 self.widget = IntPropertyEditorWidget(self.obj, "Count") # Access the real editor widget self.editor = self.widget._editor_widget def test_update_widget(self): self.widget.updateWidget() # Check if the real widget's value is updated self.assertEqual(self.editor.value(), 5) self.obj.setPropertyByName("Count", 100) self.widget.updateWidget() self.assertEqual(self.editor.value(), 100) def test_update_property(self): # Simulate user changing value in the spinbox self.editor.setValue(42) self.widget.updateProperty() self.assertEqual(self.obj.getPropertyByName("Count"), 42) class TestEnumPropertyEditorWidget(unittest.TestCase): """Tests for EnumPropertyEditorWidget.""" def setUp(self): self.obj = DetachedDocumentObject() self.obj.addProperty("App::PropertyEnumeration", "Mode", "Base", "Enumeration property") self.obj.Mode = ["Auto", "Manual", "Semi"] # Set enums and initial value self.widget = EnumPropertyEditorWidget(self.obj, "Mode") # Access the real editor widget self.editor = self.widget._editor_widget def test_populate_enum(self): # Check if the real widget is populated self.assertEqual(self.editor.count(), 3) self.assertEqual(self.editor.itemText(0), "Auto") self.assertEqual(self.editor.itemText(1), "Manual") self.assertEqual(self.editor.itemText(2), "Semi") def test_update_widget(self): self.widget.updateWidget() # Check if the real widget's value is updated self.assertEqual(self.editor.currentText(), "Auto") self.obj.setPropertyByName("Mode", "Manual") self.widget.updateWidget() self.assertEqual(self.editor.currentText(), "Manual") def test_update_property(self): # Simulate user changing value in the combobox self.editor.setCurrentIndex(1) # Select Manual self.widget._on_index_changed(1) self.assertEqual(self.obj.getPropertyByName("Mode"), "Manual") self.editor.setCurrentIndex(2) # Select Semi self.widget._on_index_changed(2) self.assertEqual(self.obj.getPropertyByName("Mode"), "Semi") class TestLabelPropertyEditorWidget(unittest.TestCase): """Tests for LabelPropertyEditorWidget.""" def setUp(self): self.obj = DetachedDocumentObject() self.obj.addProperty("App::PropertyString", "Comment", "Base", "String property") self.obj.Comment = "Test Comment" self.widget = LabelPropertyEditorWidget(self.obj, "Comment") # Access the real editor widget self.editor = self.widget._editor_widget def test_update_widget(self): self.widget.updateWidget() # Check if the real widget's value is updated self.assertEqual(self.editor.text(), "Test Comment") self.obj.setPropertyByName("Comment", "New Comment") self.widget.updateWidget() self.assertEqual(self.editor.text(), "New Comment") def test_update_property_is_noop(self): # updateProperty should do nothing for a read-only label self.widget.updateProperty() # No assertions needed, just ensure it doesn't raise errors if __name__ == "__main__": unittest.main()