""" Integration tests for the Arduino MCP Server (cleaned version) These tests verify server architecture and component integration without requiring full MCP protocol simulation. """ import tempfile from pathlib import Path import pytest from src.mcp_arduino_server.server_refactored import create_server from src.mcp_arduino_server.config import ArduinoServerConfig class TestServerIntegration: """Test suite for server architecture integration""" @pytest.fixture def test_config(self, tmp_path): """Create test configuration with temporary directories""" return ArduinoServerConfig( arduino_cli_path="/usr/bin/arduino-cli", sketches_base_dir=tmp_path / "sketches", build_temp_dir=tmp_path / "build", wireviz_path="/usr/bin/wireviz", command_timeout=30, enable_client_sampling=True ) @pytest.fixture def mcp_server(self, test_config): """Create a test MCP server instance""" return create_server(test_config) def test_server_creation(self, test_config): """Test that server creates successfully with all components""" server = create_server(test_config) assert server is not None assert server.name == "Arduino Development Server" # Verify directories were created assert test_config.sketches_base_dir.exists() assert test_config.build_temp_dir.exists() @pytest.mark.asyncio async def test_server_tools_registration(self, mcp_server): """Test that all expected tools are registered""" # Get all registered tools tools = await mcp_server.get_tools() tool_names = list(tools.keys()) # Verify sketch tools sketch_tools = [name for name in tool_names if name.startswith('arduino_') and 'sketch' in name] assert len(sketch_tools) >= 5 # create, list, read, write, compile, upload # Verify library tools library_tools = [name for name in tool_names if 'librar' in name] assert len(library_tools) >= 3 # search, install, list examples # Verify board tools board_tools = [name for name in tool_names if 'board' in name or 'core' in name] assert len(board_tools) >= 4 # list boards, search boards, install core, list cores # Verify debug tools debug_tools = [name for name in tool_names if 'debug' in name] assert len(debug_tools) >= 5 # start, interactive, break, run, print, etc. # Verify WireViz tools wireviz_tools = [name for name in tool_names if 'wireviz' in name] assert len(wireviz_tools) >= 2 # generate from yaml, generate from description @pytest.mark.asyncio async def test_server_resources_registration(self, mcp_server): """Test that all expected resources are registered""" # Get all registered resources resources = await mcp_server.get_resources() resource_uris = list(resources.keys()) expected_resources = [ "arduino://sketches", "arduino://libraries", "arduino://boards", "arduino://debug/sessions", "wireviz://instructions", "server://info" ] for expected_uri in expected_resources: assert expected_uri in resource_uris, f"Resource {expected_uri} not found in {resource_uris}" @pytest.mark.asyncio async def test_server_info_resource(self, mcp_server): """Test the server info resource provides correct information""" # Get the server info resource info_resource = await mcp_server.get_resource("server://info") info_content = await info_resource.read() assert "Arduino Development Server" in info_content assert "Configuration:" in info_content assert "Components:" in info_content assert "Available Tool Categories:" in info_content assert "Sketch Tools:" in info_content assert "Library Tools:" in info_content assert "Board Tools:" in info_content assert "Debug Tools:" in info_content assert "WireViz Tools:" in info_content def test_component_isolation(self, test_config): """Test that components can be created independently""" from src.mcp_arduino_server.components import ( ArduinoSketch, ArduinoLibrary, ArduinoBoard, ArduinoDebug, WireViz ) # Each component should initialize without errors sketch = ArduinoSketch(test_config) library = ArduinoLibrary(test_config) board = ArduinoBoard(test_config) debug = ArduinoDebug(test_config) wireviz = WireViz(test_config) # Components should have expected attributes assert hasattr(sketch, 'config') assert hasattr(library, 'config') assert hasattr(board, 'config') assert hasattr(debug, 'config') assert hasattr(wireviz, 'config') def test_configuration_flexibility(self, tmp_path): """Test that server handles various configuration scenarios""" # Test minimal configuration minimal_config = ArduinoServerConfig( sketches_base_dir=tmp_path / "minimal" ) server1 = create_server(minimal_config) assert server1 is not None # Test custom configuration custom_config = ArduinoServerConfig( arduino_cli_path="/custom/arduino-cli", wireviz_path="/custom/wireviz", sketches_base_dir=tmp_path / "custom", command_timeout=60, enable_client_sampling=False ) server2 = create_server(custom_config) assert server2 is not None # Test that different configs create distinct servers assert server1 is not server2 @pytest.mark.asyncio async def test_tool_naming_consistency(self, mcp_server): """Test that tools follow consistent naming patterns""" tools = await mcp_server.get_tools() tool_names = list(tools.keys()) arduino_tools = [name for name in tool_names if name.startswith('arduino_')] wireviz_tools = [name for name in tool_names if name.startswith('wireviz_')] # Should have both Arduino and WireViz tools assert len(arduino_tools) > 0, "No Arduino tools found" assert len(wireviz_tools) > 0, "No WireViz tools found" # Arduino tools should follow patterns for tool_name in arduino_tools: # Should have component_action pattern parts = tool_name.split('_') assert len(parts) >= 2, f"Arduino tool {tool_name} doesn't follow naming pattern" assert parts[0] == 'arduino' # WireViz tools should follow patterns for tool_name in wireviz_tools: parts = tool_name.split('_') assert len(parts) >= 2, f"WireViz tool {tool_name} doesn't follow naming pattern" assert parts[0] == 'wireviz' @pytest.mark.asyncio async def test_resource_uri_patterns(self, mcp_server): """Test that resource URIs follow expected patterns""" resources = await mcp_server.get_resources() # Group by scheme schemes = {} for uri in resources.keys(): scheme = str(uri).split('://')[0] if scheme not in schemes: schemes[scheme] = [] schemes[scheme].append(uri) # Should have expected schemes assert 'arduino' in schemes, "No arduino:// resources found" assert 'wireviz' in schemes, "No wireviz:// resources found" assert 'server' in schemes, "No server:// resources found" # Each scheme should have reasonable number of resources assert len(schemes['arduino']) >= 3, "Too few arduino:// resources" assert len(schemes['wireviz']) >= 1, "Too few wireviz:// resources" assert len(schemes['server']) >= 1, "Too few server:// resources"