forked from MicroPythonOS/MicroPythonOS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_graphical_custom_keyboard.py
More file actions
311 lines (237 loc) · 10.5 KB
/
test_graphical_custom_keyboard.py
File metadata and controls
311 lines (237 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
"""
Graphical tests for MposKeyboard.
Tests keyboard visual appearance, text input via simulated button presses,
and mode switching. Captures screenshots for regression testing.
Usage:
Desktop: ./tests/unittest.sh tests/test_graphical_custom_keyboard.py
Device: ./tests/unittest.sh tests/test_graphical_custom_keyboard.py --ondevice
"""
import unittest
import lvgl as lv
import sys
import os
from mpos import MposKeyboard, wait_for_render, capture_screenshot, AppearanceManager
class TestGraphicalMposKeyboard(unittest.TestCase):
"""Test suite for MposKeyboard graphical verification."""
def setUp(self):
"""Set up test fixtures before each test method."""
# Determine screenshot directory
if sys.platform == "esp32":
self.screenshot_dir = "tests/screenshots"
else:
self.screenshot_dir = "../tests/screenshots"
# Ensure screenshots directory exists
try:
os.mkdir(self.screenshot_dir)
except OSError:
pass # Directory already exists
print(f"\n=== Graphical Keyboard Test Setup ===")
print(f"Platform: {sys.platform}")
def tearDown(self):
"""Clean up after each test method."""
lv.screen_load(lv.obj())
wait_for_render(5)
print("=== Test Cleanup Complete ===\n")
def _create_test_keyboard_scene(self):
"""
Create a test scene with textarea and keyboard.
Returns:
tuple: (screen, keyboard, textarea)
"""
# Create screen
screen = lv.obj()
screen.set_size(320, 240)
# Create textarea
textarea = lv.textarea(screen)
textarea.set_size(280, 40)
textarea.align(lv.ALIGN.TOP_MID, 0, 10)
textarea.set_placeholder_text("Type here...")
textarea.set_one_line(True)
# Create custom keyboard
keyboard = MposKeyboard(screen)
keyboard.set_textarea(textarea)
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
# Load and render
lv.screen_load(screen)
wait_for_render(iterations=20)
return screen, keyboard, textarea
def _simulate_button_press(self, keyboard, button_index):
"""
Simulate pressing a keyboard button.
Args:
keyboard: CustomKeyboard instance
button_index: Index of button to press
Returns:
str: Text of the pressed button
"""
# Get button text before pressing
button_text = keyboard.get_button_text(button_index)
# Simulate button press by setting it as selected and sending event
# Note: This is a bit of a hack since we can't directly click in tests
# We'll trigger the VALUE_CHANGED event which is what happens on click
# The keyboard has an internal handler that responds to VALUE_CHANGED
# We need to manually trigger it
keyboard.send_event(lv.EVENT.VALUE_CHANGED, None)
wait_for_render(5)
return button_text
def test_keyboard_lowercase_appearance(self):
"""
Test keyboard appearance in lowercase mode.
Verifies that the keyboard renders correctly and captures screenshot.
"""
print("\n=== Testing lowercase keyboard appearance ===")
screen, keyboard, textarea = self._create_test_keyboard_scene()
# Ensure lowercase mode
keyboard.set_mode(MposKeyboard.MODE_LOWERCASE)
wait_for_render(10)
# Capture screenshot
screenshot_path = f"{self.screenshot_dir}/custom_keyboard_lowercase.raw"
print(f"Capturing screenshot: {screenshot_path}")
capture_screenshot(screenshot_path, width=320, height=240)
# Verify screenshot was created
stat = os.stat(screenshot_path)
self.assertTrue(stat[6] > 0, "Screenshot file is empty")
print(f"Screenshot captured: {stat[6]} bytes")
print("=== Lowercase appearance test PASSED ===")
def test_keyboard_uppercase_appearance(self):
"""Test keyboard appearance in uppercase mode."""
print("\n=== Testing uppercase keyboard appearance ===")
screen, keyboard, textarea = self._create_test_keyboard_scene()
# Switch to uppercase mode
keyboard.set_mode(MposKeyboard.MODE_UPPERCASE)
wait_for_render(10)
# Capture screenshot
screenshot_path = f"{self.screenshot_dir}/custom_keyboard_uppercase.raw"
print(f"Capturing screenshot: {screenshot_path}")
capture_screenshot(screenshot_path, width=320, height=240)
# Verify screenshot was created
stat = os.stat(screenshot_path)
self.assertTrue(stat[6] > 0, "Screenshot file is empty")
print(f"Screenshot captured: {stat[6]} bytes")
print("=== Uppercase appearance test PASSED ===")
def test_keyboard_numbers_appearance(self):
"""Test keyboard appearance in numbers/specials mode."""
print("\n=== Testing numbers keyboard appearance ===")
screen, keyboard, textarea = self._create_test_keyboard_scene()
# Switch to numbers mode
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
wait_for_render(10)
# Capture screenshot
screenshot_path = f"{self.screenshot_dir}/custom_keyboard_numbers.raw"
print(f"Capturing screenshot: {screenshot_path}")
capture_screenshot(screenshot_path, width=320, height=240)
# Verify screenshot was created
stat = os.stat(screenshot_path)
self.assertTrue(stat[6] > 0, "Screenshot file is empty")
print(f"Screenshot captured: {stat[6]} bytes")
print("=== Numbers appearance test PASSED ===")
def test_keyboard_specials_appearance(self):
"""Test keyboard appearance in additional specials mode."""
print("\n=== Testing specials keyboard appearance ===")
screen, keyboard, textarea = self._create_test_keyboard_scene()
# Switch to specials mode
keyboard.set_mode(MposKeyboard.MODE_SPECIALS)
wait_for_render(10)
# Capture screenshot
screenshot_path = f"{self.screenshot_dir}/custom_keyboard_specials.raw"
print(f"Capturing screenshot: {screenshot_path}")
capture_screenshot(screenshot_path, width=320, height=240)
# Verify screenshot was created
stat = os.stat(screenshot_path)
self.assertTrue(stat[6] > 0, "Screenshot file is empty")
print(f"Screenshot captured: {stat[6]} bytes")
print("=== Specials appearance test PASSED ===")
def test_keyboard_visibility_light_mode(self):
"""
Test that custom keyboard buttons are visible in light mode.
This verifies that the theme fix is applied.
"""
print("\n=== Testing keyboard visibility in light mode ===")
# Set light mode (should already be default)
import mpos.config
prefs = mpos.config.SharedPreferences("theme_settings")
editor = prefs.edit()
editor.put_string("theme_light_dark", "light")
editor.commit()
AppearanceManager.set_theme(prefs)
wait_for_render(10)
# Create keyboard
screen, keyboard, textarea = self._create_test_keyboard_scene()
# Get button background color
bg_color = keyboard.get_style_bg_color(lv.PART.ITEMS)
# Extract RGB (similar to keyboard styling test)
try:
color_dict = {
'r': bg_color.red() if hasattr(bg_color, 'red') else 0,
'g': bg_color.green() if hasattr(bg_color, 'green') else 0,
'b': bg_color.blue() if hasattr(bg_color, 'blue') else 0,
}
except:
try:
color_int = bg_color.to_int() if hasattr(bg_color, 'to_int') else 0
color_dict = {
'r': (color_int >> 16) & 0xFF,
'g': (color_int >> 8) & 0xFF,
'b': color_int & 0xFF,
}
except:
color_dict = {'r': 0, 'g': 0, 'b': 0}
print(f"Button background: RGB({color_dict['r']}, {color_dict['g']}, {color_dict['b']})")
# Verify buttons are NOT pure white (which would be invisible)
if 'r' in color_dict:
is_white = (color_dict['r'] >= 250 and
color_dict['g'] >= 250 and
color_dict['b'] >= 250)
self.assertFalse(
is_white,
f"Mpos keyboard buttons are pure white in light mode (invisible)!"
)
print("=== Visibility test PASSED ===")
def test_keyboard_with_standard_comparison(self):
"""
Test custom keyboard alongside standard keyboard.
Creates both for visual comparison.
"""
print("\n=== Testing custom vs standard keyboard ===")
# Create screen with two textareas
screen = lv.obj()
screen.set_size(320, 240)
# Top textarea with standard keyboard
ta_standard = lv.textarea(screen)
ta_standard.set_size(280, 30)
ta_standard.set_pos(20, 5)
ta_standard.set_placeholder_text("Standard")
ta_standard.set_one_line(True)
# Create standard keyboard (hidden initially)
keyboard_standard = MposKeyboard(screen)
keyboard_standard.set_textarea(ta_standard)
keyboard_standard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
keyboard_standard.set_style_min_height(145, 0)
# Load and render
lv.screen_load(screen)
wait_for_render(20)
# Capture standard keyboard
screenshot_path = f"{self.screenshot_dir}/keyboard_standard_comparison.raw"
print(f"Capturing standard keyboard: {screenshot_path}")
capture_screenshot(screenshot_path, width=320, height=240)
# Clean up
lv.screen_load(lv.obj())
wait_for_render(5)
# Now create custom keyboard
screen2 = lv.obj()
screen2.set_size(320, 240)
ta_custom = lv.textarea(screen2)
ta_custom.set_size(280, 30)
ta_custom.set_pos(20, 5)
ta_custom.set_placeholder_text("Custom")
ta_custom.set_one_line(True)
keyboard_custom = MposKeyboard(screen2)
keyboard_custom.set_textarea(ta_custom)
keyboard_custom.align(lv.ALIGN.BOTTOM_MID, 0, 0)
lv.screen_load(screen2)
wait_for_render(20)
# Capture custom keyboard
screenshot_path = f"{self.screenshot_dir}/keyboard_custom_comparison.raw"
print(f"Capturing custom keyboard: {screenshot_path}")
capture_screenshot(screenshot_path, width=320, height=240)
print("=== Comparison test PASSED ===")