""" Tests for the kicad_mcp.config module. """ import os import platform from unittest.mock import patch class TestConfigModule: """Test config module constants and platform-specific behavior.""" def test_system_detection(self): """Test that system is properly detected.""" from kicad_mcp.config import system assert system in ['Darwin', 'Windows', 'Linux'] or isinstance(system, str) assert system == platform.system() def test_macos_paths(self): """Test macOS-specific path configuration.""" with patch('platform.system', return_value='Darwin'): # Need to reload the config module after patching import importlib import kicad_mcp.config importlib.reload(kicad_mcp.config) from kicad_mcp.config import KICAD_APP_PATH, KICAD_PYTHON_BASE, KICAD_USER_DIR assert os.path.expanduser("~/Documents/KiCad") == KICAD_USER_DIR assert KICAD_APP_PATH == "/Applications/KiCad/KiCad.app" assert "Contents/Frameworks/Python.framework" in KICAD_PYTHON_BASE def test_windows_paths(self): """Test Windows-specific path configuration.""" with patch('platform.system', return_value='Windows'): import importlib import kicad_mcp.config importlib.reload(kicad_mcp.config) from kicad_mcp.config import KICAD_APP_PATH, KICAD_PYTHON_BASE, KICAD_USER_DIR assert os.path.expanduser("~/Documents/KiCad") == KICAD_USER_DIR assert KICAD_APP_PATH == r"C:\Program Files\KiCad" assert KICAD_PYTHON_BASE == "" def test_linux_paths(self): """Test Linux-specific path configuration.""" with patch('platform.system', return_value='Linux'): import importlib import kicad_mcp.config importlib.reload(kicad_mcp.config) from kicad_mcp.config import KICAD_APP_PATH, KICAD_PYTHON_BASE, KICAD_USER_DIR assert os.path.expanduser("~/KiCad") == KICAD_USER_DIR assert KICAD_APP_PATH == "/usr/share/kicad" assert KICAD_PYTHON_BASE == "" def test_unknown_system_defaults_to_macos(self): """Test that unknown systems default to macOS paths.""" with patch('platform.system', return_value='FreeBSD'): import importlib import kicad_mcp.config importlib.reload(kicad_mcp.config) from kicad_mcp.config import KICAD_APP_PATH, KICAD_USER_DIR assert os.path.expanduser("~/Documents/KiCad") == KICAD_USER_DIR assert KICAD_APP_PATH == "/Applications/KiCad/KiCad.app" def test_kicad_extensions(self): """Test KiCad file extension mappings.""" from kicad_mcp.config import KICAD_EXTENSIONS expected_keys = ["project", "pcb", "schematic", "design_rules", "worksheet", "footprint", "netlist", "kibot_config"] for key in expected_keys: assert key in KICAD_EXTENSIONS assert isinstance(KICAD_EXTENSIONS[key], str) assert KICAD_EXTENSIONS[key].startswith(('.', '_')) def test_data_extensions(self): """Test data file extensions list.""" from kicad_mcp.config import DATA_EXTENSIONS assert isinstance(DATA_EXTENSIONS, list) assert len(DATA_EXTENSIONS) > 0 expected_extensions = [".csv", ".pos", ".net", ".zip", ".drl"] for ext in expected_extensions: assert ext in DATA_EXTENSIONS def test_circuit_defaults(self): """Test circuit default parameters.""" from kicad_mcp.config import CIRCUIT_DEFAULTS required_keys = ["grid_spacing", "component_spacing", "wire_width", "text_size", "pin_length"] for key in required_keys: assert key in CIRCUIT_DEFAULTS # Test specific types assert isinstance(CIRCUIT_DEFAULTS["text_size"], list) assert len(CIRCUIT_DEFAULTS["text_size"]) == 2 assert all(isinstance(x, (int, float)) for x in CIRCUIT_DEFAULTS["text_size"]) def test_common_libraries_structure(self): """Test common libraries configuration structure.""" from kicad_mcp.config import COMMON_LIBRARIES expected_categories = ["basic", "power", "connectors"] for category in expected_categories: assert category in COMMON_LIBRARIES assert isinstance(COMMON_LIBRARIES[category], dict) for component, info in COMMON_LIBRARIES[category].items(): assert "library" in info assert "symbol" in info assert isinstance(info["library"], str) assert isinstance(info["symbol"], str) def test_default_footprints_structure(self): """Test default footprints configuration structure.""" from kicad_mcp.config import DEFAULT_FOOTPRINTS # Test that at least some common components are present common_components = ["R", "C", "LED", "D"] for component in common_components: assert component in DEFAULT_FOOTPRINTS assert isinstance(DEFAULT_FOOTPRINTS[component], list) assert len(DEFAULT_FOOTPRINTS[component]) > 0 # All footprints should be strings for footprint in DEFAULT_FOOTPRINTS[component]: assert isinstance(footprint, str) assert ":" in footprint # Should be in format "Library:Footprint" def test_timeout_constants(self): """Test timeout constants are reasonable values.""" from kicad_mcp.config import TIMEOUT_CONSTANTS required_keys = ["kicad_cli_version_check", "kicad_cli_export", "application_open", "subprocess_default"] for key in required_keys: assert key in TIMEOUT_CONSTANTS timeout = TIMEOUT_CONSTANTS[key] assert isinstance(timeout, (int, float)) assert 0 < timeout <= 300 # Reasonable timeout range def test_progress_constants(self): """Test progress constants are valid percentages.""" from kicad_mcp.config import PROGRESS_CONSTANTS required_keys = ["start", "detection", "setup", "processing", "finishing", "validation", "complete"] for key in required_keys: assert key in PROGRESS_CONSTANTS progress = PROGRESS_CONSTANTS[key] assert isinstance(progress, int) assert 0 <= progress <= 100 def test_display_constants(self): """Test display constants are reasonable values.""" from kicad_mcp.config import DISPLAY_CONSTANTS assert "bom_preview_limit" in DISPLAY_CONSTANTS limit = DISPLAY_CONSTANTS["bom_preview_limit"] assert isinstance(limit, int) assert limit > 0 def test_empty_search_paths_environment(self): """Test behavior with empty KICAD_SEARCH_PATHS.""" with patch.dict(os.environ, {"KICAD_SEARCH_PATHS": ""}): import importlib import kicad_mcp.config importlib.reload(kicad_mcp.config) # Should still have default locations if they exist from kicad_mcp.config import ADDITIONAL_SEARCH_PATHS assert isinstance(ADDITIONAL_SEARCH_PATHS, list) def test_nonexistent_search_paths_ignored(self): """Test that nonexistent search paths are ignored.""" with patch.dict(os.environ, {"KICAD_SEARCH_PATHS": "/nonexistent/path1,/nonexistent/path2"}), \ patch('os.path.exists', return_value=False): import importlib import kicad_mcp.config importlib.reload(kicad_mcp.config) from kicad_mcp.config import ADDITIONAL_SEARCH_PATHS # Should not contain the nonexistent paths assert "/nonexistent/path1" not in ADDITIONAL_SEARCH_PATHS assert "/nonexistent/path2" not in ADDITIONAL_SEARCH_PATHS def test_search_paths_expansion_and_trimming(self): """Test that search paths are expanded and trimmed.""" with patch.dict(os.environ, {"KICAD_SEARCH_PATHS": "~/test_path1, ~/test_path2 "}), \ patch('os.path.exists', return_value=True), \ patch('os.path.expanduser', side_effect=lambda x: x.replace("~", "/home/user")): import importlib import kicad_mcp.config importlib.reload(kicad_mcp.config) from kicad_mcp.config import ADDITIONAL_SEARCH_PATHS # Should contain expanded paths assert "/home/user/test_path1" in ADDITIONAL_SEARCH_PATHS assert "/home/user/test_path2" in ADDITIONAL_SEARCH_PATHS def test_default_project_locations_expanded(self): """Test that default project locations are properly expanded.""" from kicad_mcp.config import DEFAULT_PROJECT_LOCATIONS assert isinstance(DEFAULT_PROJECT_LOCATIONS, list) assert len(DEFAULT_PROJECT_LOCATIONS) > 0 # All should start with ~/ for location in DEFAULT_PROJECT_LOCATIONS: assert location.startswith("~/")