Skip to content

Commit 19ac438

Browse files
Add test_graphical_keyboard_emoji_font.py
1 parent af34394 commit 19ac438

4 files changed

Lines changed: 98 additions & 28 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Future release (next version)
44
Put unreleased changes here!
55

66

7+
0.11.0
8+
======
9+
710
Builtin Apps:
811
- Bundle as compiled bytecode .mpy files to reduce build size by 60KiB and improve performance
912
- About: show system uptime
@@ -14,13 +17,14 @@ Frameworks:
1417
- AppManager: require explicit import lvgl for clarity
1518
- FontManager: new framework that provides font listing, TTF support, emoji support
1619
- InputManager: mark emulate_focus_obj(group,o) as deprecated in favor of lv.group_focus_obj(o)
20+
- MposKeyboard: add support for typing a few basic emojis
1721
- SharedPreferences: avoid writing default-only configs at boot and prune empty config dirs/files
1822

1923
OS:
2024
- Add os.path functionality like in CPython
2125
- c_mpos/quirc: fix compilation warnings
22-
- Simplify focusgroup handling
2326
- Disable unused OS facilities (FreeRTOS internals, tracing, INFO logging, broken GIF, Pinyin IME, LVGL window, BMP) to reduce build size by 109KiB
27+
- Simplify focusgroup handling
2428
- Re-enable UART REPL again BUT add esp.uart_repl(False) functionality to disable/enable it at runtime
2529

2630
0.10.0

internal_filesystem/lib/mpos/ui/testing.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,34 +1648,36 @@ def click_keyboard_button(keyboard, button_text, use_direct=True):
16481648
return False
16491649

16501650
if use_direct and is_mpos_keyboard:
1651-
# For MposKeyboard, directly manipulate the textarea
1652-
# This is the most reliable approach for testing
1653-
textarea = keyboard._textarea
1654-
if textarea is None:
1655-
print(f"click_keyboard_button: No textarea connected to keyboard")
1656-
return False
1657-
1658-
current_text = textarea.get_text()
1659-
1660-
# Handle special keys (matching keyboard.py logic)
1661-
if button_text == lv.SYMBOL.BACKSPACE:
1662-
new_text = current_text[:-1]
1663-
elif button_text == " " or button_text == keyboard.LABEL_SPACE:
1664-
new_text = current_text + " "
1665-
elif button_text in [lv.SYMBOL.UP, lv.SYMBOL.DOWN, keyboard.LABEL_LETTERS,
1666-
keyboard.LABEL_NUMBERS_SPECIALS, keyboard.LABEL_SPECIALS,
1667-
lv.SYMBOL.OK]:
1668-
# Mode switching or OK - don't modify text
1669-
print(f"click_keyboard_button: '{button_text}' is a control key, not adding to textarea")
1670-
wait_for_render(10)
1671-
return True
1672-
else:
1673-
# Regular character
1674-
new_text = current_text + button_text
1675-
1676-
textarea.set_text(new_text)
1651+
# For MposKeyboard, run through its event handler logic so behavior
1652+
# matches real typing (including mode switching and emoji font updates).
1653+
class _SyntheticKeyboardTarget:
1654+
def __init__(self, idx, text):
1655+
self._idx = idx
1656+
self._text = text
1657+
1658+
def get_selected_button(self):
1659+
return self._idx
1660+
1661+
def get_button_text(self, idx):
1662+
if idx == self._idx:
1663+
return self._text
1664+
return None
1665+
1666+
class _SyntheticKeyboardEvent:
1667+
def __init__(self, target):
1668+
self._target = target
1669+
1670+
def get_code(self):
1671+
return lv.EVENT.VALUE_CHANGED
1672+
1673+
def get_target_obj(self):
1674+
return self._target
1675+
1676+
target = _SyntheticKeyboardTarget(button_idx, button_text)
1677+
event = _SyntheticKeyboardEvent(target)
1678+
keyboard._handle_events(event)
16771679
wait_for_render(10)
1678-
print(f"click_keyboard_button: Clicked '{button_text}' at index {button_idx} using direct textarea manipulation")
1680+
print(f"click_keyboard_button: Clicked '{button_text}' at index {button_idx} using direct handler simulation")
16791681
else:
16801682
# Use coordinate-based clicking
16811683
coords = get_keyboard_button_coords(keyboard, button_text)
39.3 KB
Binary file not shown.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
Graphical tests for emoji input on MposKeyboard.
3+
4+
Checks that:
5+
- Emoji keys exist on the specials keyboard layout
6+
- Typing an emoji inserts it into the textarea
7+
- Textarea font is switched to an emoji-capable composed font
8+
9+
Usage:
10+
Desktop: ./tests/unittest.sh tests/test_graphical_keyboard_emoji_font.py
11+
Device: ./tests/unittest.sh tests/test_graphical_keyboard_emoji_font.py --ondevice
12+
"""
13+
14+
import unittest
15+
import lvgl as lv
16+
17+
from mpos import FontManager
18+
from mpos.ui.testing import KeyboardTestCase
19+
20+
21+
class TestGraphicalKeyboardEmojiFont(KeyboardTestCase):
22+
def test_typing_emoji_switches_textarea_font(self):
23+
keyboard, textarea = self.create_keyboard_scene(initial_text="")
24+
25+
base_font = FontManager.getFont(size=16, family="Montserrat", emoji=False)
26+
textarea.set_style_text_font(base_font, lv.PART.MAIN)
27+
self.wait_for_render()
28+
29+
before_font = textarea.get_style_text_font(lv.PART.MAIN)
30+
self.assertEqual(before_font.get_line_height(), base_font.get_line_height())
31+
32+
keyboard.set_mode(keyboard.MODE_SPECIALS)
33+
self.wait_for_render()
34+
35+
emoji_key = "🙂"
36+
emoji_found = False
37+
emoji_button_idx = None
38+
for i in range(100):
39+
text = keyboard.get_button_text(i)
40+
if text is None:
41+
break
42+
if text == emoji_key:
43+
emoji_found = True
44+
emoji_button_idx = i
45+
break
46+
self.assertTrue(emoji_found, "Expected emoji key not present in specials layout")
47+
48+
clicked = self.click_keyboard_button(emoji_key)
49+
self.assertTrue(clicked, "Could not click emoji button")
50+
self.wait_for_render(20)
51+
52+
self.assertTextareaText(emoji_key)
53+
self.assertTrue(keyboard._textarea_emoji_font_applied)
54+
55+
after_font = textarea.get_style_text_font(lv.PART.MAIN)
56+
self.assertTrue(after_font.get_line_height() >= base_font.get_line_height())
57+
58+
fallback_font = None
59+
try:
60+
fallback_font = after_font.fallback
61+
except Exception:
62+
fallback_font = None
63+
64+
self.assertIsNotNone(fallback_font)

0 commit comments

Comments
 (0)