Files
MicroPythonOS/tests/test_graphical_keyboard_rapid_mode_switch.py
2026-01-13 00:38:17 +01:00

152 lines
5.2 KiB
Python

"""
Test for rapid mode switching bug (clicking ?123/abc rapidly).
This test reproduces:
1. Comma being added when clicking "abc" button
2. Intermittent crashes when rapidly clicking mode switch buttons
Usage:
Desktop: ./tests/unittest.sh tests/test_graphical_keyboard_rapid_mode_switch.py
"""
import unittest
import lvgl as lv
from mpos import MposKeyboard, wait_for_render
class TestRapidModeSwitching(unittest.TestCase):
"""Test rapid mode switching between lowercase and numbers."""
def setUp(self):
"""Set up test fixtures."""
self.screen = lv.obj()
self.screen.set_size(320, 240)
# Create textarea
self.textarea = lv.textarea(self.screen)
self.textarea.set_size(280, 40)
self.textarea.align(lv.ALIGN.TOP_MID, 0, 10)
self.textarea.set_one_line(True)
# Load screen
lv.screen_load(self.screen)
wait_for_render(5)
def tearDown(self):
"""Clean up."""
lv.screen_load(lv.obj())
wait_for_render(5)
def test_rapid_clicking_abc_button(self):
"""
Rapidly click the "Abc" button to reproduce the comma bug and crash.
Expected: Clicking "Abc" should NOT add comma to textarea
Bug: Comma is being added, suggesting button index confusion
"""
print("\n=== Testing rapid clicking of Abc button ===")
keyboard = MposKeyboard(self.screen)
keyboard.set_textarea(self.textarea)
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
wait_for_render(10)
# Start in lowercase, switch to numbers
print("Step 1: Switch to numbers mode")
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
wait_for_render(10) # Give time to settle
# Clear textarea
self.textarea.set_text("")
# Now find the "abc" button
abc_button_index = None
for i in range(100):
try:
text = keyboard.get_button_text(i)
if text == "Abc":
abc_button_index = i
print(f" Found 'Abc' button at index {i}")
break
except:
pass
self.assertIsNotNone(abc_button_index, "Should find 'Abc' button in numbers mode")
# Simulate rapid clicking by alternating modes
print("\nStep 2: Rapidly switch modes by simulating Abc/?123 clicks")
for i in range(10):
# Get current mode
current_mode = keyboard._keyboard.get_mode()
# Clear text before click
textarea_before = self.textarea.get_text()
print(f" Click {i+1}: mode={current_mode}, textarea='{textarea_before}'")
if current_mode == MposKeyboard.MODE_NUMBERS or current_mode == lv.keyboard.MODE.NUMBER:
# Click "Abc" to go to lowercase
keyboard.set_mode(MposKeyboard.MODE_LOWERCASE)
else:
# Click "?123" to go to numbers
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
wait_for_render(2)
# Check if text changed (BUG: should not change!)
textarea_after = self.textarea.get_text()
if textarea_after != textarea_before:
print(f" ERROR: Text changed from '{textarea_before}' to '{textarea_after}'")
self.fail(f"BUG: Clicking mode switch button added '{textarea_after}' to textarea")
# Verify textarea is still empty
final_text = self.textarea.get_text()
print(f"\nFinal textarea text: '{final_text}'")
self.assertEqual(final_text, "",
f"Textarea should be empty after mode switches, but contains: '{final_text}'")
print("SUCCESS: No spurious characters added during rapid mode switching")
def test_button_indices_after_mode_switch(self):
"""
Test that button indices remain consistent after mode switches.
This helps identify if the comma bug is due to button index confusion.
"""
print("\n=== Testing button indices after mode switch ===")
keyboard = MposKeyboard(self.screen)
keyboard.set_textarea(self.textarea)
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
wait_for_render(10)
# Map button indices in lowercase mode
print("\nButton indices in LOWERCASE mode:")
keyboard.set_mode(MposKeyboard.MODE_LOWERCASE)
wait_for_render(10)
lowercase_buttons = {}
for i in range(40):
try:
text = keyboard.get_button_text(i)
if text in ["?123", ",", "Abc", lv.SYMBOL.UP]:
lowercase_buttons[text] = i
print(f" '{text}' at index {i}")
except:
pass
# Map button indices in numbers mode
print("\nButton indices in NUMBERS mode:")
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
wait_for_render(10)
numbers_buttons = {}
for i in range(40):
try:
text = keyboard.get_button_text(i)
if text in ["?123", ",", "Abc", "=\\<"]:
numbers_buttons[text] = i
print(f" '{text}' at index {i}")
except:
pass