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

287 lines
10 KiB
Python

import unittest
import lvgl as lv
import mpos
import time
import sys
import os
# Import graphical test helper
from mpos import (
wait_for_render,
capture_screenshot,
find_label_with_text,
verify_text_present,
print_screen_labels
)
class TestOSUpdateGraphicalUI(unittest.TestCase):
"""Graphical tests for OSUpdate app UI state."""
def tearDown(self):
"""Clean up after each test method."""
# Navigate back to launcher
mpos.ui.back_screen()
wait_for_render(5)
def test_app_launches_successfully(self):
"""Test that OSUpdate app launches without errors."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result, "Failed to start OSUpdate app")
wait_for_render(10)
# Get active screen
screen = lv.screen_active()
self.assertIsNotNone(screen, "No active screen after launch")
def test_ui_elements_exist(self):
"""Test that all required UI elements are created."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(15)
screen = lv.screen_active()
# Find UI elements by searching for labels/text
current_version_label = find_label_with_text(screen, "Installed OS version")
self.assertIsNotNone(current_version_label, "Current version label not found")
# Check for force update checkbox text (might be "Force" or "Update")
force_checkbox_found = verify_text_present(screen, "Force") or verify_text_present(screen, "force")
self.assertTrue(force_checkbox_found, "Force checkbox text not found")
# Check for update button text (case insensitive)
update_button_found = verify_text_present(screen, "Update") or verify_text_present(screen, "update")
self.assertTrue(update_button_found, "Update button text not found")
def test_force_checkbox_initially_unchecked(self):
"""Test that force update checkbox starts unchecked."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(15)
screen = lv.screen_active()
# Find checkbox - it's the first checkbox on the screen
checkbox = None
def find_checkbox(obj):
nonlocal checkbox
if checkbox:
return
# Check if this object is a checkbox
try:
# In LVGL, checkboxes have specific flags/properties
if obj.get_child_count() >= 0: # It's a valid object
# Try to get state - checkboxes respond to STATE.CHECKED
state = obj.get_state()
# If it has checkbox-like text, it's probably our checkbox
for i in range(obj.get_child_count()):
child = obj.get_child(i)
if hasattr(child, 'get_text'):
text = child.get_text()
if text and "Force Update" in text:
checkbox = obj.get_parent() if obj.get_parent() else obj
return
except:
pass
# Recursively search children
for i in range(obj.get_child_count()):
child = obj.get_child(i)
find_checkbox(child)
find_checkbox(screen)
if checkbox:
state = checkbox.get_state()
is_checked = bool(state & lv.STATE.CHECKED)
self.assertFalse(is_checked, "Force Update checkbox should start unchecked")
def test_install_button_initially_disabled(self):
"""Test that install button starts in disabled state."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(15)
screen = lv.screen_active()
# Find the button
button = None
def find_button(obj):
nonlocal button
if button:
return
# Check if this object contains "Update OS" text
for i in range(obj.get_child_count()):
child = obj.get_child(i)
if hasattr(child, 'get_text'):
text = child.get_text()
if text and "Update OS" in text:
# Parent is likely the button
button = obj
return
# Recursively search children
for i in range(obj.get_child_count()):
child = obj.get_child(i)
find_button(child)
find_button(screen)
if button:
state = button.get_state()
is_disabled = bool(state & lv.STATE.DISABLED)
self.assertTrue(is_disabled, "Install button should start disabled")
def test_current_version_displayed(self):
"""Test that current OS version is displayed correctly."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(15)
screen = lv.screen_active()
# Find version label
version_label = find_label_with_text(screen, "Installed OS version:")
self.assertIsNotNone(version_label, "Version label not found")
# Check that it contains the current version
label_text = version_label.get_text()
current_version = mpos.info.CURRENT_OS_VERSION
self.assertIn(current_version, label_text,
f"Current version {current_version} not in label text: {label_text}")
def test_initial_status_message_without_wifi(self):
"""Test status message when wifi is not connected."""
# This test assumes desktop mode where wifi check returns True
# On actual hardware without wifi, it would show error
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(15)
screen = lv.screen_active()
# Should show either "Checking for OS updates..." or update info
# or wifi error depending on network state
checking_found = verify_text_present(screen, "Checking") or \
verify_text_present(screen, "version") or \
verify_text_present(screen, "WiFi")
self.assertTrue(checking_found, "Should show some status message")
def test_screenshot_initial_state(self):
"""Capture screenshot of initial app state."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(20)
screen = lv.screen_active()
# Print labels for debugging
print("\n=== OSUpdate Initial State Labels ===")
print_screen_labels(screen)
class TestOSUpdateGraphicalStatusMessages(unittest.TestCase):
"""Graphical tests for OSUpdate status messages."""
def setUp(self):
"""Set up test fixtures."""
self.hardware_id = mpos.info.get_hardware_id()
self.screenshot_dir = "tests/screenshots"
try:
os.stat(self.screenshot_dir)
except OSError:
try:
os.mkdir(self.screenshot_dir)
except OSError:
pass
def tearDown(self):
"""Clean up after test."""
mpos.ui.back_screen()
wait_for_render(5)
def test_status_label_exists(self):
"""Test that status label is created and visible."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(15)
screen = lv.screen_active()
# Status label should exist and show some text
# Look for common status messages
has_status = (
verify_text_present(screen, "Checking") or
verify_text_present(screen, "version") or
verify_text_present(screen, "WiFi") or
verify_text_present(screen, "Error") or
verify_text_present(screen, "Update")
)
self.assertTrue(has_status, "Status label should be present with some message")
def test_all_labels_readable(self):
"""Test that all labels are readable (no truncation issues)."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(15)
screen = lv.screen_active()
# Print all labels to verify they're readable
print("\n=== All OSUpdate Labels ===")
print_screen_labels(screen)
# At minimum, should have version label
version_found = verify_text_present(screen, "Installed OS version")
self.assertTrue(version_found, "Version label should be present and readable")
class TestOSUpdateGraphicalScreenshots(unittest.TestCase):
"""Screenshot tests for visual regression testing."""
def setUp(self):
"""Set up test fixtures."""
self.hardware_id = mpos.info.get_hardware_id()
self.screenshot_dir = "tests/screenshots"
try:
os.stat(self.screenshot_dir)
except OSError:
try:
os.mkdir(self.screenshot_dir)
except OSError:
pass
def tearDown(self):
"""Clean up after test."""
mpos.ui.back_screen()
wait_for_render(5)
def test_capture_main_screen(self):
"""Capture screenshot of main OSUpdate screen."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(20)
def test_capture_with_labels_visible(self):
"""Capture screenshot ensuring all text is visible."""
result = mpos.apps.start_app("com.micropythonos.osupdate")
self.assertTrue(result)
wait_for_render(20)
screen = lv.screen_active()
# Verify key elements are visible before screenshot (case insensitive)
has_version = verify_text_present(screen, "Installed") or verify_text_present(screen, "version")
has_force = verify_text_present(screen, "Force") or verify_text_present(screen, "force")
has_button = verify_text_present(screen, "Update") or verify_text_present(screen, "update")
self.assertTrue(has_version, "Version label should be visible")
self.assertTrue(has_force, "Force checkbox should be visible")
self.assertTrue(has_button, "Update button should be visible")