mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Trying to finish keyboard
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
Manual test for the "abc" button bug with DEBUG OUTPUT.
|
||||
|
||||
Run with: ./scripts/run_desktop.sh tests/manual_test_abc_button_debug.py
|
||||
|
||||
This will show debug output when you click the "abc" button.
|
||||
Watch the terminal to see what's happening!
|
||||
"""
|
||||
|
||||
import lvgl as lv
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
|
||||
# Get active screen
|
||||
screen = lv.screen_active()
|
||||
screen.clean()
|
||||
|
||||
# Create title
|
||||
title = lv.label(screen)
|
||||
title.set_text("ABC Button Debug Test")
|
||||
title.align(lv.ALIGN.TOP_MID, 0, 5)
|
||||
|
||||
# Create instructions
|
||||
instructions = lv.label(screen)
|
||||
instructions.set_text(
|
||||
"Watch the TERMINAL output!\n"
|
||||
"\n"
|
||||
"1. Click '?123' to go to numbers mode\n"
|
||||
"2. Click 'abc' to go back to lowercase\n"
|
||||
"3. Check terminal for debug output\n"
|
||||
"4. Check if comma appears in textarea"
|
||||
)
|
||||
instructions.set_style_text_align(lv.TEXT_ALIGN.LEFT, 0)
|
||||
instructions.align(lv.ALIGN.TOP_LEFT, 10, 30)
|
||||
|
||||
# Create textarea
|
||||
textarea = lv.textarea(screen)
|
||||
textarea.set_size(280, 30)
|
||||
textarea.set_one_line(True)
|
||||
textarea.align(lv.ALIGN.TOP_MID, 0, 120)
|
||||
textarea.set_placeholder_text("Type here...")
|
||||
|
||||
# Create keyboard
|
||||
keyboard = MposKeyboard(screen)
|
||||
keyboard.set_textarea(textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
|
||||
print("\n" + "="*70)
|
||||
print("ABC BUTTON DEBUG TEST")
|
||||
print("="*70)
|
||||
print("Instructions:")
|
||||
print("1. The keyboard starts in LOWERCASE mode")
|
||||
print("2. Click the '?123' button (bottom left) to switch to NUMBERS mode")
|
||||
print("3. Click the 'abc' button (bottom left) to switch back to LOWERCASE")
|
||||
print("4. Watch this terminal for [KEYBOARD DEBUG] messages")
|
||||
print("5. Check if a comma appears in the textarea")
|
||||
print("="*70)
|
||||
print("\nWaiting for button clicks...")
|
||||
print()
|
||||
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
Automated test that simulates clicking the abc button and shows debug output.
|
||||
|
||||
This will show us exactly what's happening when the abc button is clicked.
|
||||
|
||||
Usage:
|
||||
Desktop: ./tests/unittest.sh tests/test_graphical_abc_button_debug.py
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
from graphical_test_helper import wait_for_render
|
||||
|
||||
|
||||
class TestAbcButtonDebug(unittest.TestCase):
|
||||
"""Test that shows debug output when clicking abc button."""
|
||||
|
||||
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_simulate_abc_button_click(self):
|
||||
"""
|
||||
Simulate clicking the abc button and show what happens.
|
||||
"""
|
||||
print("\n" + "="*70)
|
||||
print("SIMULATING ABC BUTTON CLICK - WATCH FOR DEBUG OUTPUT")
|
||||
print("="*70)
|
||||
|
||||
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("\n>>> Switching to NUMBERS mode...")
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
wait_for_render(10)
|
||||
|
||||
# Wait for debounce period to expire (150ms + margin)
|
||||
import time
|
||||
print(">>> Waiting 200ms for debounce period to expire...")
|
||||
time.sleep(0.2)
|
||||
|
||||
# Clear textarea
|
||||
self.textarea.set_text("")
|
||||
print(f">>> Textarea cleared: '{self.textarea.get_text()}'")
|
||||
|
||||
# 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 {abc_button_index}")
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
# Now simulate what happens when user TOUCHES the button
|
||||
# When user touches a button, LVGL's button matrix:
|
||||
# 1. Sets the button as selected
|
||||
# 2. Triggers VALUE_CHANGED event
|
||||
print(f"\n>>> Simulating user clicking button {abc_button_index}...")
|
||||
print(f">>> Before click: textarea = '{self.textarea.get_text()}'")
|
||||
print("\n--- DEBUG OUTPUT SHOULD APPEAR BELOW ---\n")
|
||||
|
||||
# Trigger the VALUE_CHANGED event which our handler catches
|
||||
# This simulates a real button press
|
||||
keyboard._keyboard.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
wait_for_render(5)
|
||||
|
||||
print("\n--- END DEBUG OUTPUT ---\n")
|
||||
|
||||
textarea_after = self.textarea.get_text()
|
||||
print(f">>> After click: textarea = '{textarea_after}'")
|
||||
|
||||
if textarea_after != "":
|
||||
print(f"\n❌ BUG CONFIRMED!")
|
||||
print(f" Expected: '' (empty)")
|
||||
print(f" Got: '{textarea_after}'")
|
||||
else:
|
||||
print(f"\n✓ No text added (but check debug output above)")
|
||||
|
||||
print("="*70)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,162 @@
|
||||
"""
|
||||
Test for the abc button click bug - comma being added.
|
||||
|
||||
This test actually CLICKS the abc button to reproduce the comma bug.
|
||||
|
||||
Usage:
|
||||
Desktop: ./tests/unittest.sh tests/test_graphical_keyboard_abc_click_bug.py
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import lvgl as lv
|
||||
from mpos.ui.keyboard import MposKeyboard
|
||||
from graphical_test_helper import wait_for_render
|
||||
|
||||
|
||||
class TestAbcButtonClickBug(unittest.TestCase):
|
||||
"""Test that clicking abc button doesn't add comma."""
|
||||
|
||||
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_clicking_abc_button_should_not_add_comma(self):
|
||||
"""
|
||||
Test that actually CLICKING the abc button doesn't add comma.
|
||||
|
||||
This is the REAL test - simulating actual user clicks.
|
||||
"""
|
||||
print("\n=== Testing ACTUAL 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)
|
||||
|
||||
# Clear textarea
|
||||
self.textarea.set_text("")
|
||||
print(f" Textarea cleared: '{self.textarea.get_text()}'")
|
||||
|
||||
# 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")
|
||||
|
||||
# ACTUALLY CLICK THE BUTTON
|
||||
print(f"\nStep 2: ACTUALLY CLICK button index {abc_button_index}")
|
||||
print(f" Before click: textarea='{self.textarea.get_text()}'")
|
||||
|
||||
# Simulate button click by sending CLICKED event to the button matrix
|
||||
# Get the underlying button matrix object
|
||||
btnm = keyboard._keyboard
|
||||
|
||||
# Method 1: Try to programmatically click the button
|
||||
# This simulates what happens when user actually touches the button
|
||||
btnm.set_selected_button(abc_button_index)
|
||||
wait_for_render(2)
|
||||
|
||||
# Send the VALUE_CHANGED event
|
||||
btnm.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
wait_for_render(5)
|
||||
|
||||
textarea_after = self.textarea.get_text()
|
||||
print(f" After click: textarea='{textarea_after}'")
|
||||
|
||||
# Check if comma was added
|
||||
if "," in textarea_after:
|
||||
print(f"\n ❌ BUG CONFIRMED: Comma was added!")
|
||||
print(f" Textarea contains: '{textarea_after}'")
|
||||
self.fail(f"BUG: Clicking 'abc' button added comma! Textarea: '{textarea_after}'")
|
||||
|
||||
# Also check if anything else was added
|
||||
if textarea_after != "":
|
||||
print(f"\n ❌ BUG CONFIRMED: Something was added!")
|
||||
print(f" Expected: ''")
|
||||
print(f" Got: '{textarea_after}'")
|
||||
self.fail(f"BUG: Clicking 'abc' button added text! Textarea: '{textarea_after}'")
|
||||
|
||||
print(f"\n ✓ SUCCESS: No text added, textarea is still empty")
|
||||
|
||||
def test_clicking_abc_multiple_times(self):
|
||||
"""
|
||||
Test clicking abc button multiple times in a row.
|
||||
"""
|
||||
print("\n=== Testing MULTIPLE clicks of abc button ===")
|
||||
|
||||
keyboard = MposKeyboard(self.screen)
|
||||
keyboard.set_textarea(self.textarea)
|
||||
keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
|
||||
wait_for_render(10)
|
||||
|
||||
for attempt in range(5):
|
||||
print(f"\n--- Attempt {attempt + 1} ---")
|
||||
|
||||
# Go to numbers mode
|
||||
keyboard.set_mode(MposKeyboard.MODE_NUMBERS)
|
||||
wait_for_render(10)
|
||||
|
||||
# Clear textarea
|
||||
self.textarea.set_text("")
|
||||
|
||||
# Find 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
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
# Click it
|
||||
print(f"Clicking 'abc' at index {abc_button_index}")
|
||||
keyboard._keyboard.set_selected_button(abc_button_index)
|
||||
wait_for_render(2)
|
||||
keyboard._keyboard.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
wait_for_render(5)
|
||||
|
||||
textarea_text = self.textarea.get_text()
|
||||
print(f" Result: textarea='{textarea_text}'")
|
||||
|
||||
if textarea_text != "":
|
||||
print(f" ❌ FAIL on attempt {attempt + 1}: Got '{textarea_text}'")
|
||||
self.fail(f"Attempt {attempt + 1}: Clicking 'abc' added '{textarea_text}'")
|
||||
else:
|
||||
print(f" ✓ OK")
|
||||
|
||||
print("\n✓ SUCCESS: All 5 attempts worked correctly")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
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.ui.keyboard import MposKeyboard
|
||||
from graphical_test_helper import 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
|
||||
|
||||
# Check if comma and abc are at same index
|
||||
if "," in lowercase_buttons and "abc" in numbers_buttons:
|
||||
comma_idx = lowercase_buttons[","]
|
||||
abc_idx = numbers_buttons["abc"]
|
||||
print(f"\nComparison:")
|
||||
print(f" Comma in lowercase: index {comma_idx}")
|
||||
print(f" 'abc' in numbers: index {abc_idx}")
|
||||
|
||||
if comma_idx == abc_idx:
|
||||
print(" WARNING: Comma and 'abc' share the same index!")
|
||||
print(" This could explain why comma appears when clicking 'abc'")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user