barcode-server/tests/key_event_reader_test.py
2022-06-24 12:14:10 -07:00

168 lines
5.2 KiB
Python

from typing import List
from unittest.mock import Mock
from evdev import InputEvent, ecodes, KeyEvent
from barcode_server.keyevent_reader import KeyEventReader
from tests import TestBase
class KeyEventReaderTest(TestBase):
@staticmethod
def fake_input_loop(input: List[InputEvent]):
input_events = input
def read_loop():
for event in input_events:
yield event
return read_loop
@staticmethod
def mock_input_event(keycode, keystate) -> InputEvent:
input_event = Mock(spec=InputEvent)
input_event.type = 1
input_event.keystate = keystate # 0: UP, 1: Down, 2: Hold
input_event.keycode = keycode
# inverse lookup of the event code in the target structure
code = next(key for key, value in ecodes.keys.items() if value == keycode)
input_event.code = code
return input_event
def generate_input_event_sequence(self, expected: str, finish_line: bool = True) -> List[InputEvent]:
events = []
keycodes = list(map(lambda x: self.character_to_keycode(x), expected))
for item in keycodes:
for keystate in [KeyEvent.key_down, KeyEvent.key_up]:
event = self.mock_input_event(keycode=item, keystate=keystate)
events.append(event)
if finish_line:
for keystate in [KeyEvent.key_down, KeyEvent.key_up]:
event = self.mock_input_event(keycode="KEY_ENTER", keystate=keystate)
events.append(event)
return events
@staticmethod
def character_to_keycode(character: str) -> str:
char_to_keycode_map = {
'0': "KEY_KP0",
'1': "KEY_KP1",
'2': "KEY_KP2",
'3': "KEY_KP3",
'4': "KEY_KP4",
'5': "KEY_KP5",
'6': "KEY_KP6",
'7': "KEY_KP7",
'8': "KEY_KP8",
'9': "KEY_KP9",
'*': "KEY_KPASTERISK",
'/': "KEY_SLASH",
'-': "KEY_KPMINUS",
'+': "KEY_KPPLUS",
'.': "KEY_DOT",
',': "KEY_COMMA",
'?': "KEY_QUESTION",
'\n': "KEY_ENTER",
}
return char_to_keycode_map[character]
def test_mock_gen(self):
# GIVEN
expected = [
self.mock_input_event(keycode="KEY_KPMINUS", keystate=KeyEvent.key_down),
self.mock_input_event(keycode="KEY_KPMINUS", keystate=KeyEvent.key_up),
self.mock_input_event(keycode="KEY_DOT", keystate=KeyEvent.key_down),
self.mock_input_event(keycode="KEY_DOT", keystate=KeyEvent.key_up),
self.mock_input_event(keycode="KEY_KPMINUS", keystate=KeyEvent.key_down),
self.mock_input_event(keycode="KEY_KPMINUS", keystate=KeyEvent.key_up),
self.mock_input_event(keycode="KEY_ENTER", keystate=KeyEvent.key_down),
self.mock_input_event(keycode="KEY_ENTER", keystate=KeyEvent.key_up),
]
text = "-.-"
# WHEN
input_events = self.generate_input_event_sequence(text)
# THEN
self.assertEqual(len(expected), len(input_events))
for i in range(0, len(expected)):
self.assertEqual(expected[i].keycode, input_events[i].keycode)
async def test_numbers(self):
# GIVEN
under_test = KeyEventReader()
expected = "0123456789"
input_events = self.generate_input_event_sequence(expected)
input_device = Mock()
input_device.read_loop = self.fake_input_loop(input_events)
# WHEN
line = under_test.read_line(input_device)
# THEN
self.assertEqual(expected, line)
async def test_special_characters(self):
# GIVEN
under_test = KeyEventReader()
expected = "+.,*/-?"
input_events = self.generate_input_event_sequence(expected)
input_device = Mock()
input_device.read_loop = self.fake_input_loop(input_events)
# WHEN
line = under_test.read_line(input_device)
# THEN
self.assertEqual(expected, line)
async def test_none_event(self):
# GIVEN
under_test = KeyEventReader()
unexpected = "0"
expected = "1"
input_events = self.generate_input_event_sequence(unexpected + expected)
input_events[0] = None
input_events[1] = None
input_device = Mock()
input_device.read_loop = self.fake_input_loop(input_events)
# WHEN
line = under_test.read_line(input_device)
# THEN
self.assertEqual(expected, line)
async def test_event_without_keystate_attribute(self):
# GIVEN
under_test = KeyEventReader()
unexpected = "0"
input_events_without_keystate = self.generate_input_event_sequence(unexpected)
for event in input_events_without_keystate:
delattr(event, "keystate")
expected = "1"
input_events = self.generate_input_event_sequence(expected)
input_events = input_events + input_events_without_keystate
input_device = Mock()
input_device.read_loop = self.fake_input_loop(input_events)
# WHEN
line = under_test.read_line(input_device)
# THEN
self.assertEqual(expected, line)