|
16 | 16 | from unittest.mock import MagicMock, patch |
17 | 17 |
|
18 | 18 | import pytest |
| 19 | +from test_data_model_vehicle_components_common import REALISTIC_VEHICLE_DATA |
19 | 20 |
|
20 | 21 | from ardupilot_methodic_configurator.backend_filesystem import LocalFilesystem |
| 22 | +from ardupilot_methodic_configurator.backend_filesystem_vehicle_components import VehicleComponents |
21 | 23 | from ardupilot_methodic_configurator.data_model_vehicle_components import ComponentDataModel |
22 | 24 | from ardupilot_methodic_configurator.frontend_tkinter_component_editor_base import ( |
23 | 25 | VEICLE_IMAGE_WIDTH_PIX, |
|
30 | 32 | # pylint: disable=protected-access |
31 | 33 |
|
32 | 34 |
|
| 35 | +def setup_common_editor_mocks(editor) -> ComponentEditorWindowBase: |
| 36 | + """Set up common mock attributes and methods for editor fixtures.""" |
| 37 | + # Set up all required attributes manually |
| 38 | + editor.root = MagicMock() |
| 39 | + editor.main_frame = MagicMock() |
| 40 | + editor.scroll_frame = MagicMock() |
| 41 | + editor.scroll_frame.view_port = MagicMock() |
| 42 | + editor.version = "1.0.0" |
| 43 | + |
| 44 | + # Mock filesystem and methods with proper schema loading |
| 45 | + editor.local_filesystem = MagicMock(spec=LocalFilesystem) |
| 46 | + editor.local_filesystem.vehicle_dir = "dummy_vehicle_dir" |
| 47 | + editor.local_filesystem.get_component_property_description = MagicMock(return_value=("Test description", False)) |
| 48 | + editor.local_filesystem.vehicle_image_exists = MagicMock(return_value=False) |
| 49 | + editor.local_filesystem.vehicle_image_filepath = MagicMock(return_value="test.jpg") |
| 50 | + editor.local_filesystem.save_component_to_system_templates = MagicMock() |
| 51 | + |
| 52 | + # Mock the vehicle_components attribute |
| 53 | + mock_vehicle_components = MagicMock() |
| 54 | + # Make schema loading return a valid empty schema |
| 55 | + mock_vehicle_components.load_schema.return_value = {"properties": {}} |
| 56 | + mock_vehicle_components.get_component_property_description = MagicMock(return_value=("Test description", False)) |
| 57 | + editor.local_filesystem.vehicle_components = mock_vehicle_components |
| 58 | + |
| 59 | + # Setup test data and data model |
| 60 | + editor.entry_widgets = {} |
| 61 | + |
| 62 | + # Create data model with realistic test data |
| 63 | + vehicle_components = VehicleComponents() |
| 64 | + component_datatypes = vehicle_components.get_all_value_datatypes() |
| 65 | + editor.data_model = ComponentDataModel(REALISTIC_VEHICLE_DATA, component_datatypes) |
| 66 | + |
| 67 | + # Mock specific methods that are used in tests |
| 68 | + editor.data_model.set_component_value = MagicMock() |
| 69 | + editor.data_model.update_component = MagicMock() |
| 70 | + |
| 71 | + # Override methods that might cause UI interactions in tests |
| 72 | + # Mock _add_widget completely to avoid UI creation |
| 73 | + editor._add_widget = MagicMock() |
| 74 | + editor.put_image_in_label = MagicMock(return_value=MagicMock()) |
| 75 | + editor.add_entry_or_combobox = MagicMock(return_value=MagicMock()) |
| 76 | + |
| 77 | + return editor |
| 78 | + |
| 79 | + |
| 80 | +def add_editor_helper_methods(editor) -> None: |
| 81 | + """Add common helper methods for testing that bypass UI operations.""" |
| 82 | + |
| 83 | + # Use add_widget as a public proxy for _add_widget for easier testing |
| 84 | + def add_widget_proxy(parent, key, value, path) -> None: |
| 85 | + return editor._add_widget(parent, key, value, path) |
| 86 | + |
| 87 | + editor.add_widget = add_widget_proxy |
| 88 | + |
| 89 | + # Add helper methods for testing that bypass UI operations |
| 90 | + def test_populate_frames() -> None: |
| 91 | + # This is a test-friendly version that doesn't involve actual UI widgets |
| 92 | + components = editor.data_model.get_all_components() |
| 93 | + for key, value in components.items(): |
| 94 | + editor._add_widget(editor.scroll_frame.view_port, key, value, []) |
| 95 | + |
| 96 | + editor.populate_frames = test_populate_frames |
| 97 | + |
| 98 | + |
| 99 | +class SharedTestArgumentParser: |
| 100 | + """Shared test cases for the argument_parser function to avoid duplication.""" |
| 101 | + |
| 102 | + def test_argument_parser(self) -> None: |
| 103 | + """Test argument_parser function.""" |
| 104 | + with patch("sys.argv", ["test_script", "--vehicle-dir", "test_dir", "--vehicle-type", "ArduCopter"]): |
| 105 | + args = argument_parser() |
| 106 | + |
| 107 | + assert hasattr(args, "vehicle_dir") |
| 108 | + assert hasattr(args, "vehicle_type") |
| 109 | + assert hasattr(args, "skip_component_editor") |
| 110 | + |
| 111 | + def test_argument_parser_with_skip_component_editor(self) -> None: |
| 112 | + """Test argument_parser with skip-component-editor flag.""" |
| 113 | + with patch( |
| 114 | + "sys.argv", ["test_script", "--vehicle-dir", "test_dir", "--vehicle-type", "ArduCopter", "--skip-component-editor"] |
| 115 | + ): |
| 116 | + args = argument_parser() |
| 117 | + |
| 118 | + assert args.skip_component_editor is True |
| 119 | + |
| 120 | + |
| 121 | +@pytest.fixture |
| 122 | +def editor_with_mocked_root() -> ComponentEditorWindowBase: |
| 123 | + """Create a mock ComponentEditorWindowBase for testing.""" |
| 124 | + # Create the class without initialization |
| 125 | + with patch.object(ComponentEditorWindowBase, "__init__", return_value=None): |
| 126 | + editor = ComponentEditorWindowBase() # pylint: disable=no-value-for-parameter |
| 127 | + |
| 128 | + # Set up common mocks and helper methods |
| 129 | + setup_common_editor_mocks(editor) |
| 130 | + add_editor_helper_methods(editor) |
| 131 | + |
| 132 | + yield editor |
| 133 | + |
| 134 | + |
33 | 135 | class TestArgumentParserBehavior: |
34 | 136 | """Test argument parser behavior and functionality.""" |
35 | 137 |
|
|
0 commit comments