Skip to content

Commit 5cd3d40

Browse files
Remove tests/base/* stuff to fix --ondevice tests
1 parent b36ff9d commit 5cd3d40

10 files changed

Lines changed: 246 additions & 471 deletions

File tree

internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets/osupdate.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -708,20 +708,7 @@ def __init__(self, download_manager=None, json_module=None):
708708
self.json = json_module if json_module else ujson
709709

710710
def get_update_url(self, hardware_id):
711-
"""Determine the update JSON URL based on hardware ID.
712-
713-
Args:
714-
hardware_id: Hardware identifier string
715-
716-
Returns:
717-
str: Full URL to update JSON file
718-
"""
719-
if hardware_id == "waveshare_esp32_s3_touch_lcd_2":
720-
# First supported device - no hardware ID in URL
721-
infofile = "osupdate.json"
722-
else:
723-
infofile = f"osupdate_{hardware_id}.json"
724-
return f"https://updates.micropythonos.com/{infofile}"
711+
return f"https://updates.micropythonos.com/osupdate_{hardware_id}.json"
725712

726713
async def fetch_update_info(self, hardware_id):
727714
"""Fetch and parse update information from server.

internal_filesystem/lib/mpos/net/wifi_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ def attempt_connecting(ssid, password, network_module=None, time_module=None):
258258
time_mod = time_module if time_module else time
259259

260260
if WifiService.is_hotspot_enabled(network_module=network_module):
261-
WifiService._needs_hotspot_restore = False
261+
WifiService._needs_hotspot_restore = True
262262
WifiService.disable_hotspot(network_module=network_module)
263263

264264
# Desktop mode - simulate successful connection

internal_filesystem/lib/mpos/ui/testing.py

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,239 @@
4444
import lvgl as lv
4545
import time
4646

47+
try:
48+
import unittest
49+
except ImportError: # pragma: no cover - fallback for device builds without unittest
50+
unittest = None
51+
4752
# Simulation globals for touch input
4853
_touch_x = 0
4954
_touch_y = 0
5055
_touch_pressed = False
5156
_touch_indev = None
5257

5358

59+
class GraphicalTestCase(unittest.TestCase if unittest else object):
60+
"""
61+
Base class for graphical tests.
62+
63+
Provides:
64+
- Automatic screen creation and cleanup
65+
- Common UI testing utilities
66+
67+
Class Attributes:
68+
SCREEN_WIDTH: Default screen width (320)
69+
SCREEN_HEIGHT: Default screen height (240)
70+
DEFAULT_RENDER_ITERATIONS: Default iterations for wait_for_render (5)
71+
72+
Instance Attributes:
73+
screen: The LVGL screen object for the test
74+
"""
75+
76+
SCREEN_WIDTH = 320
77+
SCREEN_HEIGHT = 240
78+
DEFAULT_RENDER_ITERATIONS = 5
79+
80+
def setUp(self):
81+
"""Set up test fixtures before each test method."""
82+
self.screen = lv.obj()
83+
self.screen.set_size(self.SCREEN_WIDTH, self.SCREEN_HEIGHT)
84+
lv.screen_load(self.screen)
85+
self.wait_for_render()
86+
87+
def tearDown(self):
88+
"""Clean up after each test method."""
89+
lv.screen_load(lv.obj())
90+
self.wait_for_render()
91+
92+
def wait_for_render(self, iterations=None):
93+
"""Wait for LVGL to render."""
94+
if iterations is None:
95+
iterations = self.DEFAULT_RENDER_ITERATIONS
96+
wait_for_render(iterations)
97+
98+
def find_label_with_text(self, text, parent=None):
99+
"""Find a label containing the specified text."""
100+
if parent is None:
101+
parent = lv.screen_active()
102+
return find_label_with_text(parent, text)
103+
104+
def verify_text_present(self, text, parent=None):
105+
"""Verify that text is present on screen."""
106+
if parent is None:
107+
parent = lv.screen_active()
108+
return verify_text_present(parent, text)
109+
110+
def print_screen_labels(self, parent=None):
111+
"""Print all labels on screen (for debugging)."""
112+
if parent is None:
113+
parent = lv.screen_active()
114+
print_screen_labels(parent)
115+
116+
def click_button(self, text, use_send_event=True):
117+
"""Click a button by its text."""
118+
return click_button(text, use_send_event=use_send_event)
119+
120+
def click_label(self, text, use_send_event=True):
121+
"""Click a label by its text."""
122+
return click_label(text, use_send_event=use_send_event)
123+
124+
def simulate_click(self, x, y):
125+
"""Simulate a click at specific coordinates."""
126+
simulate_click(x, y)
127+
self.wait_for_render()
128+
129+
def assertTextPresent(self, text, msg=None):
130+
"""Assert that text is present on screen."""
131+
if msg is None:
132+
msg = f"Text '{text}' not found on screen"
133+
self.assertTrue(self.verify_text_present(text), msg)
134+
135+
def assertTextNotPresent(self, text, msg=None):
136+
"""Assert that text is NOT present on screen."""
137+
if msg is None:
138+
msg = f"Text '{text}' should not be on screen"
139+
self.assertFalse(self.verify_text_present(text), msg)
140+
141+
142+
class KeyboardTestCase(GraphicalTestCase):
143+
"""
144+
Base class for keyboard tests.
145+
146+
Extends GraphicalTestCase with keyboard-specific functionality.
147+
148+
Instance Attributes:
149+
keyboard: The MposKeyboard instance (after create_keyboard_scene)
150+
textarea: The textarea widget (after create_keyboard_scene)
151+
"""
152+
153+
DEFAULT_RENDER_ITERATIONS = 10
154+
155+
def setUp(self):
156+
"""Set up test fixtures."""
157+
super().setUp()
158+
self.keyboard = None
159+
self.textarea = None
160+
161+
def create_keyboard_scene(self, initial_text="", textarea_width=200, textarea_height=30):
162+
"""
163+
Create a standard keyboard test scene with textarea and keyboard.
164+
165+
Args:
166+
initial_text: Initial text in the textarea
167+
textarea_width: Width of the textarea
168+
textarea_height: Height of the textarea
169+
170+
Returns:
171+
tuple: (keyboard, textarea)
172+
"""
173+
from mpos import MposKeyboard
174+
175+
self.textarea = lv.textarea(self.screen)
176+
self.textarea.set_size(textarea_width, textarea_height)
177+
self.textarea.set_one_line(True)
178+
self.textarea.align(lv.ALIGN.TOP_MID, 0, 10)
179+
self.textarea.set_text(initial_text)
180+
self.wait_for_render()
181+
182+
self.keyboard = MposKeyboard(self.screen)
183+
self.keyboard.set_textarea(self.textarea)
184+
self.keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0)
185+
self.wait_for_render()
186+
187+
return self.keyboard, self.textarea
188+
189+
def click_keyboard_button(self, button_text):
190+
"""
191+
Click a keyboard button by its text.
192+
193+
Args:
194+
button_text: The text of the button to click (e.g., "q", "a", "Enter")
195+
196+
Returns:
197+
bool: True if button was clicked successfully
198+
"""
199+
if self.keyboard is None:
200+
raise RuntimeError("No keyboard created. Call create_keyboard_scene() first.")
201+
202+
return click_keyboard_button(self.keyboard, button_text)
203+
204+
def get_textarea_text(self):
205+
"""Get the current text in the textarea."""
206+
if self.textarea is None:
207+
raise RuntimeError("No textarea created. Call create_keyboard_scene() first.")
208+
return self.textarea.get_text()
209+
210+
def set_textarea_text(self, text):
211+
"""Set the textarea text."""
212+
if self.textarea is None:
213+
raise RuntimeError("No textarea created. Call create_keyboard_scene() first.")
214+
self.textarea.set_text(text)
215+
self.wait_for_render()
216+
217+
def clear_textarea(self):
218+
"""Clear the textarea."""
219+
self.set_textarea_text("")
220+
221+
def type_text(self, text):
222+
"""Type a string by clicking each character on the keyboard."""
223+
for char in text:
224+
if not self.click_keyboard_button(char):
225+
return False
226+
return True
227+
228+
def assertTextareaText(self, expected, msg=None):
229+
"""Assert that the textarea contains the expected text."""
230+
actual = self.get_textarea_text()
231+
if msg is None:
232+
msg = f"Textarea text mismatch. Expected '{expected}', got '{actual}'"
233+
self.assertEqual(actual, expected, msg)
234+
235+
def assertTextareaEmpty(self, msg=None):
236+
"""Assert that the textarea is empty."""
237+
if msg is None:
238+
msg = f"Textarea should be empty, but contains '{self.get_textarea_text()}'"
239+
self.assertEqual(self.get_textarea_text(), "", msg)
240+
241+
def assertTextareaContains(self, substring, msg=None):
242+
"""Assert that the textarea contains a substring."""
243+
actual = self.get_textarea_text()
244+
if msg is None:
245+
msg = f"Textarea should contain '{substring}', but has '{actual}'"
246+
self.assertIn(substring, actual, msg)
247+
248+
def get_keyboard_button_text(self, index):
249+
"""Get the text of a keyboard button by index."""
250+
if self.keyboard is None:
251+
raise RuntimeError("No keyboard created. Call create_keyboard_scene() first.")
252+
253+
try:
254+
return self.keyboard.get_button_text(index)
255+
except:
256+
return None
257+
258+
def find_keyboard_button_index(self, button_text):
259+
"""Find the index of a keyboard button by its text."""
260+
for i in range(100):
261+
text = self.get_keyboard_button_text(i)
262+
if text is None:
263+
break
264+
if text == button_text:
265+
return i
266+
return None
267+
268+
def get_all_keyboard_buttons(self):
269+
"""Get all keyboard buttons as a list of (index, text) tuples."""
270+
buttons = []
271+
for i in range(100):
272+
text = self.get_keyboard_button_text(i)
273+
if text is None:
274+
break
275+
if text:
276+
buttons.append((i, text))
277+
return buttons
278+
279+
54280
def wait_for_render(iterations=10):
55281
"""
56282
Wait for LVGL to process UI events and render.

tests/base/__init__.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)