Add keyboard event tests
This commit is contained in:
parent
82a68b0fe5
commit
50279f88fb
@ -15,12 +15,6 @@ class State:
|
||||
SENDING = const(2)
|
||||
|
||||
|
||||
class DictionaryEntry:
|
||||
def __init__(self, key: str, value: str):
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
|
||||
class Character:
|
||||
'''Helper class for making a left-shifted key identical to a right-shifted key'''
|
||||
|
||||
@ -30,7 +24,7 @@ class Character:
|
||||
self.is_shifted = is_shifted
|
||||
self.key_code = KC.LSHIFT(key_code) if is_shifted else key_code
|
||||
|
||||
def __eq__(self, other: any) -> bool:
|
||||
def __eq__(self, other: any) -> bool: # type: ignore
|
||||
try:
|
||||
return (
|
||||
self.key_code.code == other.key_code.code
|
||||
@ -104,8 +98,7 @@ class TextReplacement(Module):
|
||||
dictionary: dict,
|
||||
):
|
||||
for entry in dictionary:
|
||||
entry = DictionaryEntry(entry, dictionary[entry])
|
||||
self._rules.append(Rule(Phrase(entry.key), Phrase(entry.value)))
|
||||
self._rules.append(Rule(Phrase(entry), Phrase(dictionary[entry])))
|
||||
|
||||
def process_key(self, keyboard, key, is_pressed, int_coord):
|
||||
if not self._state == State.LISTENING:
|
||||
@ -115,8 +108,9 @@ class TextReplacement(Module):
|
||||
self._shifted = True
|
||||
else:
|
||||
self._shifted = False
|
||||
elif is_pressed:
|
||||
if is_pressed:
|
||||
character = Character(key, self._shifted)
|
||||
|
||||
# run through the dictionary to check for a possible match on each new keypress
|
||||
for rule in self._rules:
|
||||
if rule.to_substitute.character_is_at_current_index(character):
|
||||
@ -163,7 +157,7 @@ class TextReplacement(Module):
|
||||
|
||||
if self._state == State.DELETING:
|
||||
# send backspace taps equivalent to the length of the phrase to be substituted
|
||||
to_substitute: Phrase = self._matched_rule.to_substitute
|
||||
to_substitute: Phrase = self._matched_rule.to_substitute # type: ignore
|
||||
to_substitute.next_character()
|
||||
if not to_substitute.index_at_end():
|
||||
keyboard.tap_key(KC.BSPC)
|
||||
@ -185,7 +179,7 @@ class TextReplacement(Module):
|
||||
keyboard.remove_key(key)
|
||||
|
||||
if self._state == State.SENDING:
|
||||
substitution = self._matched_rule.substitution
|
||||
substitution = self._matched_rule.substitution # type: ignore
|
||||
if not substitution.index_at_end():
|
||||
keyboard.tap_key(substitution.get_character_at_current_index().key_code)
|
||||
substitution.next_character()
|
||||
|
@ -2,14 +2,76 @@ import unittest
|
||||
|
||||
from kmk.keys import ALL_ALPHAS, ALL_NUMBERS, KC
|
||||
from kmk.modules.text_replacement import Character, Phrase, Rule, TextReplacement
|
||||
from tests.keyboard_test import KeyboardTest
|
||||
|
||||
|
||||
class TestTextReplacement(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.symbols = '`-=[]\\;\',./~!@#$%^&*()_+{}|:\"<>?'
|
||||
self.everything = ALL_NUMBERS + ALL_ALPHAS + ALL_ALPHAS.lower() + self.symbols
|
||||
self.test_dictionary = {'aa': 'b', 'b': 'aa', '!': '@', 'dccc': 'dcbb'}
|
||||
self.text_replacement = TextReplacement(self.test_dictionary)
|
||||
self.keyboard = KeyboardTest(
|
||||
[self.text_replacement],
|
||||
[
|
||||
[KC.A, KC.B, KC.N1, KC.LSHIFT, KC.LCTRL, KC.C, KC.D],
|
||||
],
|
||||
debug_enabled=True,
|
||||
)
|
||||
|
||||
return super().setUp()
|
||||
|
||||
def test_keyboard_events_are_correct(self):
|
||||
# backspace doesn't have to fire for the final key pressed
|
||||
# that results in a corresponding match, as that key is never sent
|
||||
# the matching key also never sends a keyup event
|
||||
self.keyboard.test(
|
||||
'multi-character key, single-character value',
|
||||
[(0, True), (0, False), (0, True), (0, False)],
|
||||
[{KC.A}, {}, {KC.BACKSPACE}, {}, {KC.B}, {}],
|
||||
)
|
||||
# note: the pressed key is never sent here, as the event is
|
||||
# intercepted and the replacement is sent instead
|
||||
self.keyboard.test(
|
||||
'multi-character value, single-character key',
|
||||
[(1, True), (1, False)],
|
||||
[{KC.A}, {}, {KC.A}, {}],
|
||||
)
|
||||
# modifiers are force-released if there's a match,
|
||||
# so the keyup event for them isn't sent
|
||||
self.keyboard.test(
|
||||
'shifted alphanumeric or symbol in key and/or value',
|
||||
[(3, True), (2, True), (2, False), (3, False)],
|
||||
[{KC.LSHIFT}, {KC.LSHIFT, KC.N2}, {}],
|
||||
)
|
||||
self.keyboard.test(
|
||||
'backspace is only tapped as many times as necessary to delete the difference between the key and value',
|
||||
[
|
||||
(6, True),
|
||||
(6, False),
|
||||
(5, True),
|
||||
(5, False),
|
||||
(5, True),
|
||||
(5, False),
|
||||
(5, True),
|
||||
(5, False),
|
||||
],
|
||||
[
|
||||
{KC.D},
|
||||
{},
|
||||
{KC.C},
|
||||
{},
|
||||
{KC.C},
|
||||
{},
|
||||
{KC.BACKSPACE},
|
||||
{},
|
||||
{KC.B},
|
||||
{},
|
||||
{KC.B},
|
||||
{},
|
||||
],
|
||||
)
|
||||
|
||||
def test_invalid_character_in_dictionary_throws_error(self):
|
||||
dict = {
|
||||
'illegal_character_in_key': {'é': 'a'},
|
||||
@ -114,7 +176,7 @@ class TestTextReplacement(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_sanity_check(self):
|
||||
'''Tests character/phrase construction with every letter, number, and symbol, shifted and unshifted'''
|
||||
'''Test character/phrase construction with every letter, number, and symbol, shifted and unshifted'''
|
||||
phrase = Phrase(self.everything)
|
||||
for i, character in enumerate(self.everything):
|
||||
self.assertEqual(
|
||||
|
Loading…
Reference in New Issue
Block a user