""" Graphical tests for MposKeyboard. Tests keyboard visual appearance, text input via simulated button presses, and mode switching. 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 from mpos import MposKeyboard, wait_for_render, AppearanceManager class TestGraphicalMposKeyboard(unittest.TestCase): """Test suite for MposKeyboard graphical verification.""" def setUp(self): """Set up test fixtures before each test method.""" print(f"\n=== Graphical Keyboard Test Setup ===") 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. """ 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) 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) 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) 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) 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) # 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) print("=== Comparison test PASSED ===")