"""Tests for the Linux evdev/uinput backend.""" from unittest import mock import pytest from vibe_coded_mcp_desktop_control.linux_backend import LinuxEvdevBackend @pytest.fixture def mock_uinput() -> mock.MagicMock: """Patch evdev.UInput so tests do not require /dev/uinput access.""" with mock.patch("vibe_coded_mcp_desktop_control.linux_backend.UInput") as patched: yield patched def test_backend_initialization(mock_uinput: mock.MagicMock) -> None: """The backend should create a UInput device on initialization.""" backend = LinuxEvdevBackend(layout="us") assert backend.layout == "us" mock_uinput.assert_called_once() backend.close() def test_close_releases_device(mock_uinput: mock.MagicMock) -> None: """Closing the backend should close the underlying UInput device.""" backend = LinuxEvdevBackend(layout="us") device = backend.ui backend.close() device.close.assert_called_once() assert backend.ui is None def test_mouse_click(mock_uinput: mock.MagicMock) -> None: """A left mouse click should write press and release events.""" backend = LinuxEvdevBackend(layout="us") device = backend.ui backend.mouse_action("left", "click") assert device.write.call_count == 2 assert device.syn.call_count == 2 def test_keyboard_key_resolves_string(mock_uinput: mock.MagicMock) -> None: """A string key name should be resolved to an evdev keycode.""" backend = LinuxEvdevBackend(layout="us") device = backend.ui backend.keyboard_key("ENTER", "click") assert device.write.call_count == 2 assert device.syn.call_count == 2 def test_keyboard_action_unknown_logs_error( mock_uinput: mock.MagicMock, caplog: pytest.LogCaptureFixture ) -> None: """An unknown keyboard action should log an error and return.""" backend = LinuxEvdevBackend(layout="us") with caplog.at_level("ERROR"): backend.keyboard_action("unknown_action") assert "Unknown keyboard action" in caplog.text