113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SRC = ROOT / "src"
|
|
if str(SRC) not in sys.path:
|
|
sys.path.insert(0, str(SRC))
|
|
|
|
from desktop_x11 import X11Adapter
|
|
|
|
|
|
class DesktopX11Tests(unittest.TestCase):
|
|
def _adapter(self) -> X11Adapter:
|
|
return object.__new__(X11Adapter)
|
|
|
|
@patch("desktop_x11.display.Display")
|
|
def test_paste_clipboard_closes_display_on_success(self, display_cls):
|
|
adapter = self._adapter()
|
|
display_obj = MagicMock()
|
|
display_cls.return_value = display_obj
|
|
adapter._send_combo = MagicMock()
|
|
|
|
adapter._paste_clipboard()
|
|
|
|
adapter._send_combo.assert_called_once_with(display_obj, ["Control_L", "Shift_L", "v"])
|
|
display_obj.close.assert_called_once_with()
|
|
|
|
@patch("desktop_x11.display.Display")
|
|
def test_paste_clipboard_closes_display_on_send_error(self, display_cls):
|
|
adapter = self._adapter()
|
|
display_obj = MagicMock()
|
|
display_cls.return_value = display_obj
|
|
adapter._send_combo = MagicMock(side_effect=RuntimeError("boom"))
|
|
|
|
with self.assertRaisesRegex(RuntimeError, "boom"):
|
|
adapter._paste_clipboard()
|
|
|
|
display_obj.close.assert_called_once_with()
|
|
|
|
@patch("desktop_x11.display.Display")
|
|
def test_type_text_closes_display_on_success(self, display_cls):
|
|
adapter = self._adapter()
|
|
display_obj = MagicMock()
|
|
display_cls.return_value = display_obj
|
|
adapter._send_combo = MagicMock()
|
|
adapter._keysym_for_char = MagicMock(return_value=(42, False))
|
|
|
|
adapter._type_text("a")
|
|
|
|
adapter._send_combo.assert_called_once_with(display_obj, [42], already_keysym=True)
|
|
display_obj.close.assert_called_once_with()
|
|
|
|
@patch("desktop_x11.display.Display")
|
|
def test_type_text_closes_display_on_send_error(self, display_cls):
|
|
adapter = self._adapter()
|
|
display_obj = MagicMock()
|
|
display_cls.return_value = display_obj
|
|
adapter._send_combo = MagicMock(side_effect=RuntimeError("boom"))
|
|
adapter._keysym_for_char = MagicMock(return_value=(42, False))
|
|
|
|
with self.assertRaisesRegex(RuntimeError, "boom"):
|
|
adapter._type_text("a")
|
|
|
|
display_obj.close.assert_called_once_with()
|
|
|
|
@patch("desktop_x11.xtest.fake_input")
|
|
def test_send_combo_releases_keys_and_syncs(self, fake_input):
|
|
adapter = self._adapter()
|
|
dpy = MagicMock()
|
|
dpy.keysym_to_keycode.side_effect = [10, 20, 30]
|
|
|
|
adapter._send_combo(dpy, ["Control_L", "Shift_L", "v"])
|
|
|
|
expected_calls = [
|
|
((dpy, 2, 10),),
|
|
((dpy, 2, 20),),
|
|
((dpy, 2, 30),),
|
|
((dpy, 3, 30),),
|
|
((dpy, 3, 20),),
|
|
((dpy, 3, 10),),
|
|
]
|
|
self.assertEqual(fake_input.call_args_list, expected_calls)
|
|
dpy.sync.assert_called_once_with()
|
|
|
|
@patch("desktop_x11.xtest.fake_input")
|
|
def test_send_combo_releases_pressed_keys_when_press_fails(self, fake_input):
|
|
adapter = self._adapter()
|
|
dpy = MagicMock()
|
|
dpy.keysym_to_keycode.side_effect = [10, 20]
|
|
|
|
def _fake_input(_dpy, event_type, code):
|
|
if event_type == 2 and code == 20:
|
|
raise RuntimeError("press failed")
|
|
return None
|
|
|
|
fake_input.side_effect = _fake_input
|
|
|
|
with self.assertRaisesRegex(RuntimeError, "press failed"):
|
|
adapter._send_combo(dpy, ["Control_L", "v"])
|
|
|
|
expected_calls = [
|
|
((dpy, 2, 10),),
|
|
((dpy, 2, 20),),
|
|
((dpy, 3, 10),),
|
|
]
|
|
self.assertEqual(fake_input.call_args_list, expected_calls)
|
|
dpy.sync.assert_called_once_with()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|