DroidMind

by hyperb1iss
Verified
# pylint: disable=duplicate-code """Tests for the DroidMind MCP tools and resources.""" from unittest.mock import AsyncMock, MagicMock, patch from mcp.server.fastmcp import Context, Image import pytest from droidmind.devices import Device from droidmind.tools import ( connect_device, device_properties, disconnect_device, list_devices, reboot_device, screenshot as capture_screenshot, shell_command, ) @pytest.fixture def mock_context(): """Create a mock MCP context.""" context = MagicMock(spec=Context) context.info = AsyncMock() context.error = AsyncMock() return context @pytest.fixture def mock_device(): """Create a mock device for testing.""" device = MagicMock(spec=Device) device.serial = "device1" # Set up properties class AsyncPropertyMock: def __init__(self, return_value): self.return_value = return_value def __await__(self): async def _async_return(): return self.return_value return _async_return().__await__() device.model = AsyncPropertyMock("Pixel 4") device.brand = AsyncPropertyMock("Google") device.android_version = AsyncPropertyMock("11") device.sdk_level = AsyncPropertyMock("30") device.build_number = AsyncPropertyMock("RQ3A.211001.001") # Set up methods device.get_properties = AsyncMock( return_value={ "ro.product.model": "Pixel 4", "ro.product.brand": "Google", "ro.build.version.release": "11", "ro.build.version.sdk": "30", "ro.build.id": "RQ3A.211001.001", } ) device.run_shell = AsyncMock(return_value="Command output") device.take_screenshot = AsyncMock(return_value=b"FAKE_SCREENSHOT_DATA") device.reboot = AsyncMock() return device @pytest.mark.asyncio @patch("droidmind.tools.device_management.get_device_manager") async def test_list_devices(mock_list_devices, mock_context, mock_device): """Test the devicelist tool.""" # Set up the mock device list class AsyncPropertyMock: def __init__(self, return_value): self.return_value = return_value def __await__(self): async def _async_return(): return self.return_value return _async_return().__await__() mock_device1 = MagicMock(spec=Device) mock_device1.serial = "device1" mock_device1.model = AsyncPropertyMock("Pixel 4") mock_device1.android_version = AsyncPropertyMock("11") mock_device2 = MagicMock(spec=Device) mock_device2.serial = "device2" mock_device2.model = AsyncPropertyMock("Pixel 5") mock_device2.android_version = AsyncPropertyMock("12") # Set up the mock device manager mock_manager = MagicMock() mock_manager.list_devices = AsyncMock(return_value=[mock_device1, mock_device2]) mock_list_devices.return_value = mock_manager # Call the tool result = await list_devices(ctx=mock_context) # Verify the result assert "Connected Android Devices (2)" in result assert "Device 1: Pixel 4" in result assert "Device 2: Pixel 5" in result @pytest.mark.asyncio @patch("droidmind.tools.device_management.get_device_manager") async def test_list_devices_empty(mock_list_devices, mock_context): """Test the devicelist tool with no devices.""" # Set up the mock device manager mock_manager = MagicMock() mock_manager.list_devices = AsyncMock(return_value=[]) mock_list_devices.return_value = mock_manager # Call the tool result = await list_devices(ctx=mock_context) # Verify the result assert "No devices connected" in result @pytest.mark.asyncio @patch("droidmind.tools.device_management.get_device_manager") async def test_device_properties(mock_get_device_manager, mock_context, mock_device): """Test the device_properties tool.""" # Setup mock get_device_manager to return a mock that has get_device method mock_manager = MagicMock() mock_manager.get_device = AsyncMock(return_value=mock_device) mock_get_device_manager.return_value = mock_manager # Call the tool with correct parameter order result = await device_properties(ctx=mock_context, serial="device1") # Verify the result assert "Device Properties for device1" in result assert "**Model**: Pixel 4" in result assert "**Brand**: Google" in result assert "**Android Version**: 11" in result assert "**SDK Level**: 30" in result assert "**Build Number**: RQ3A.211001.001" in result @pytest.mark.asyncio @patch("droidmind.tools.device_management.get_device_manager") async def test_device_properties_not_found(mock_get_device_manager, mock_context): """Test the device_properties tool with a non-existent device.""" # Setup mock get_device_manager to return a mock that has get_device method mock_manager = MagicMock() mock_manager.get_device = AsyncMock(return_value=None) mock_get_device_manager.return_value = mock_manager # Call the tool result = await device_properties(ctx=mock_context, serial="nonexistent") # Verify the result assert "Device nonexistent not found or not connected" in result @pytest.mark.asyncio @patch("droidmind.tools.device_management.get_device_manager") async def test_connect_device(mock_connect, mock_context, mock_device): """Test the connect_device tool.""" # Setup mock get_device_manager to return a mock that has connect method mock_manager = MagicMock() mock_manager.connect = AsyncMock(return_value=mock_device) mock_connect.return_value = mock_manager # Call the tool result = await connect_device(ctx=mock_context, ip_address="192.168.1.100", port=5555) # Verify the result assert "Device Connected Successfully" in result assert "Pixel 4" in result assert "192.168.1.100:5555" in result @pytest.mark.asyncio @patch("droidmind.tools.device_management.get_device_manager") async def test_disconnect_device(mock_disconnect, mock_context): """Test the disconnect_device tool.""" # Setup mock get_device_manager to return a mock that has disconnect method mock_manager = MagicMock() mock_manager.disconnect = AsyncMock(return_value=True) mock_disconnect.return_value = mock_manager # Call the tool result = await disconnect_device(ctx=mock_context, serial="device1") # Verify the result assert "Successfully disconnected from device device1" in result @pytest.mark.asyncio @patch("droidmind.tools.shell.get_device_manager") async def test_shell_command(mock_get_device_manager, mock_context, mock_device): """Test the shell_command tool.""" # Setup mock get_device_manager to return a mock that has get_device method mock_manager = MagicMock() mock_manager.get_device = AsyncMock(return_value=mock_device) mock_get_device_manager.return_value = mock_manager # Call the tool result = await shell_command(ctx=mock_context, serial="device1", command="ls -la") # Verify the result assert "Command Output from device1" in result assert "Command output" in result @pytest.mark.asyncio @patch("droidmind.tools.media.get_device_manager") async def test_capture_screenshot(mock_get_device, mock_context, mock_device): """Test the screenshot tool.""" # Setup mock get_device_manager to return a mock that has get_device method mock_manager = MagicMock() mock_manager.get_device = AsyncMock(return_value=mock_device) mock_get_device.return_value = mock_manager # Call the tool result = await capture_screenshot(ctx=mock_context, serial="device1") # Verify the result is an Image object with the expected data assert isinstance(result, Image) assert result.data == b"FAKE_SCREENSHOT_DATA" # Verify the context methods were called mock_context.info.assert_called() assert "Capturing screenshot" in mock_context.info.call_args_list[0][0][0] @pytest.mark.asyncio @patch("droidmind.tools.device_management.get_device_manager") async def test_reboot_device(mock_get_device_manager, mock_context, mock_device): """Test the reboot_device tool.""" # Setup mock get_device_manager to return a mock that has get_device method mock_manager = MagicMock() mock_manager.get_device = AsyncMock(return_value=mock_device) mock_get_device_manager.return_value = mock_manager # Call the tool result = await reboot_device(ctx=mock_context, serial="device1", mode="recovery") # Verify the result assert "Device device1 is rebooting in recovery mode" in result # Verify the device's reboot method was called with the correct mode mock_device.reboot.assert_called_once_with("recovery")
ID: p03zdsi6ol