emdashes begone (#10847)

This commit is contained in:
Tom
2026-07-01 19:01:27 -05:00
committed by GitHub
co-authored by GitHub
parent dee94e0758
commit 3becaf2d95
276 changed files with 1795 additions and 1793 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
"""UI tier input-broker-driven screen navigation tests.
"""UI tier - input-broker-driven screen navigation tests.
Only runs when a screen-bearing role (esp32s3/heltec-v3) is present on the
hub AND the firmware was baked with `enable_ui_log=True` (so the
+1 -1
View File
@@ -122,7 +122,7 @@ def wait_for_reason(
) -> FrameEvent:
"""Wait for a frame event with `reason=<reason>` after call-start.
Matches only on `reason` useful when the caller knows *why* a
Matches only on `reason` - useful when the caller knows *why* a
transition should happen (e.g. `fn_f1`, `rebuild`) but not which named
frame the firmware will land on for this particular board.
"""
+15 -15
View File
@@ -24,11 +24,11 @@ from meshtastic_mcp.input_events import InputEventCode
from ._screen_log import FrameEvent, get_current_frame, wait_for_frame
# Roles that carry a screen the UI tier can drive. Only esp32s3 (heltec-v3
# SSD1306) qualifies today nrf52 (rak4631) has no display.
# SSD1306) qualifies today - nrf52 (rak4631) has no display.
UI_CAPABLE_ROLES = ("esp32s3",)
# Where per-test captures land. One subdirectory per session seed, then per
# sanitized test nodeid identical pattern to other pytest artifacts.
# sanitized test nodeid - identical pattern to other pytest artifacts.
CAPTURES_ROOT = Path(__file__).resolve().parent.parent / "ui_captures"
@@ -104,11 +104,11 @@ def _ocr_warm() -> None:
"""Pay easyocr's ~100 MB / cold-start cost ONCE per session.
Subsequent `ocr_text()` calls hit the cached reader and return quickly.
Swallows errors if OCR isn't installed, warm is a no-op.
Swallows errors - if OCR isn't installed, warm is a no-op.
"""
try:
ocr_mod.warm()
except Exception: # noqa: BLE001 belt: never block the suite on OCR init
except Exception: # noqa: BLE001 - belt: never block the suite on OCR init
pass
@@ -119,7 +119,7 @@ def _ui_screen_kept_on(
"""Keep the OLED on throughout the UI tier so input events aren't dropped.
Why: `InputBroker::handleInputEvent` (src/input/InputBroker.cpp:118-122)
silently DROPS any event that arrives while the screen is off it just
silently DROPS any event that arrives while the screen is off - it just
wakes the screen and returns. Every first event in each test would
disappear. We set `display.screen_on_secs = 86400` at session start
(effectively "always on" for the test window) and restore the prior
@@ -156,7 +156,7 @@ def _ui_screen_kept_on(
time.sleep(1.5) # Let the screen finish its wake transition.
except (
Exception
): # noqa: BLE001 best-effort; ui_home_state surfaces the real error
): # noqa: BLE001 - best-effort; ui_home_state surfaces the real error
pass
try:
@@ -193,7 +193,7 @@ class FrameCapture:
self._transcript_path = dir_path / "transcript.md"
self._dir.mkdir(parents=True, exist_ok=True)
self._transcript_path.write_text(
f"# {nodeid} {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}\n\n",
f"# {nodeid} - {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}\n\n",
encoding="utf-8",
)
@@ -242,7 +242,7 @@ class FrameCapture:
)
ocr_summary = (ocr_str or "").replace("\n", " / ")[:80]
fh.write(
f"{self._step}. **{label}** {frame_str} OCR: `{ocr_summary}`\n"
f"{self._step}. **{label}** - {frame_str} - OCR: `{ocr_summary}`\n"
)
return entry
@@ -273,7 +273,7 @@ def _send_event(port: str, event: InputEventCode) -> None:
try:
admin_mod.send_input_event(event_code=int(event), port=port)
except Exception: # noqa: BLE001
# Treat a failed event as soft the subsequent frame-log assertion
# Treat a failed event as soft - the subsequent frame-log assertion
# surfaces the real problem with better context.
pass
@@ -298,7 +298,7 @@ def ui_home_state(
instead of letting every test body fail with a confusing assertion.
Autouse scope is restricted to `tests/ui/` by virtue of this fixture
living in that directory's conftest.py no explicit nodeid guard
living in that directory's conftest.py - no explicit nodeid guard
needed (and earlier attempts at one were wrong, matching `/tests/ui/`
against a nodeid that has no leading slash).
"""
@@ -313,7 +313,7 @@ def ui_home_state(
start_len = len(lines)
# First: a wake event. The screen should already be kept on by
# `_ui_screen_kept_on`, but belt + suspenders if it somehow
# `_ui_screen_kept_on`, but belt + suspenders - if it somehow
# powered off (sleep after factory_reset, etc.), this first FN_F1
# gets dropped by InputBroker's screenWasOff guard. That's fine;
# the second FN_F1 below lands cleanly.
@@ -322,14 +322,14 @@ def ui_home_state(
_send_event(port, InputEventCode.FN_F1)
# Wait for the fn_f1 transition log. Any new `reason=fn_f1` line
# after call-start counts we don't care about the name (it should
# after call-start counts - we don't care about the name (it should
# be `home` or `deviceFocused` depending on board-specific frame order).
from ._screen_log import wait_for_reason
try:
wait_for_reason(lines, "fn_f1", timeout_s=5.0)
except TimeoutError:
# One more try FreeRTOS queue may be draining slowly.
# One more try - FreeRTOS queue may be draining slowly.
_send_event(port, InputEventCode.FN_F1)
try:
wait_for_reason(lines, "fn_f1", timeout_s=5.0)
@@ -345,12 +345,12 @@ def ui_home_state(
f"ui_home_state: events fire but none reach Screen "
f"(saw {len(frame_lines)} frame line(s), "
f"{len(processing_lines)} admin inject(s)). "
f"Device may be in an unusual state try `--force-bake`."
f"Device may be in an unusual state - try `--force-bake`."
)
else:
pytest.skip(
"ui_home_state: no `Screen: frame` log after FN_F1. "
"Firmware not baked with USERPREFS_UI_TEST_LOG "
"Firmware not baked with USERPREFS_UI_TEST_LOG - "
"run with `--force-bake` to reflash, or verify the "
"macro is active in the bake."
)
+1 -1
View File
@@ -39,7 +39,7 @@ def test_fn_jump_direct_frame(
) -> None:
lines: list[str] = request.node._debug_log_buffer
start = get_current_frame(lines)
assert start is not None, "no frame log yet USERPREFS_UI_TEST_LOG not wired?"
assert start is not None, "no frame log yet - USERPREFS_UI_TEST_LOG not wired?"
assert start.name in (
"home",
"deviceFocused",
+5 -5
View File
@@ -3,7 +3,7 @@
`Screen::handleInputEvent` dispatches FN_F5 unconditionally to
`ui->switchToFrame(4)`. The OLEDDisplayUi library typically clamps or
silently ignores out-of-range indices, but firmware bugs have existed
here this test protects against a regression that would wedge the UI.
here - this test protects against a regression that would wedge the UI.
If this test fails, first check: did the device actually crash (Guru
Meditation in the log)? Or did switchToFrame accept an OOB index and
@@ -33,7 +33,7 @@ def test_fn_f5_out_of_bounds(
if start.count > 5:
pytest.skip(
f"device has {start.count} frames; FN_F5 is in-bounds not testing OOB here"
f"device has {start.count} frames; FN_F5 is in-bounds - not testing OOB here"
)
frame_capture("initial-home")
@@ -43,11 +43,11 @@ def test_fn_f5_out_of_bounds(
try:
wait_for_reason(lines, "fn_f5", timeout_s=3.0)
except TimeoutError:
# Firmware may have ignored the event entirely acceptable.
# Firmware may have ignored the event entirely - acceptable.
pass
# Capture whatever is on screen (OCR will tell us if something weird
# happened). Device must remain responsive subsequent events should
# happened). Device must remain responsive - subsequent events should
# still land.
frame_capture("after-fn_f5-oob")
@@ -57,5 +57,5 @@ def test_fn_f5_out_of_bounds(
post = wait_for_reason(lines, "next", timeout_s=5.0)
assert (
post is not None
), "UI wedged after OOB FN_F5 RIGHT no longer produces frame log"
), "UI wedged after OOB FN_F5 - RIGHT no longer produces frame log"
frame_capture("after-recovery-right")
+5 -5
View File
@@ -1,7 +1,7 @@
"""SELECT on the home frame opens the home menu; BACK closes it.
The home menu is an overlay (menuHandler::homeBaseMenu), not a frame
transition so we verify via OCR difference between before/after
transition - so we verify via OCR difference between before/after
captures rather than a `Screen: frame` log line. The underlying
mechanism is still InputBroker → Screen::handleInputEvent → menu
callback.
@@ -39,25 +39,25 @@ def test_select_opens_home_menu(
opened = frame_capture("after-select")
# The menu is an overlay (not a frame change). We cannot use log
# assertion instead, OCR should differ because a menu list is now
# assertion - instead, OCR should differ because a menu list is now
# drawn on top.
initial_text = (initial.get("ocr_text") or "").strip()
opened_text = (opened.get("ocr_text") or "").strip()
if initial_text and opened_text:
# When OCR is available, require *some* difference between the two
# frames even a single menu title changes the transcribed text.
# frames - even a single menu title changes the transcribed text.
assert initial_text != opened_text, (
f"expected OCR diff after SELECT; both read {initial_text!r}. "
"If both are empty, check camera alignment + OCR backend."
)
# Back out the menu dismisses on BACK.
# Back out - the menu dismisses on BACK.
send_event(ui_port, InputEventCode.BACK)
time.sleep(0.8)
closed = frame_capture("after-back")
# Soft check: OCR after BACK should look different from the menu
# (either back to home or onto a previous frame BACK's exact
# (either back to home or onto a previous frame - BACK's exact
# behavior when the menu is up vs. not-up varies). We don't assert
# equality because OLED rendering is pixel-stable but camera sampling
# introduces noise.
@@ -3,7 +3,7 @@ message-scroll path (or opens CannedMessages on empty devices).
Weaker than a "no frame change" assertion because on a fresh bench
device the message store is usually empty, and the firmware's UP
handler in that case launches CannedMessage which DOES rebuild
handler in that case launches CannedMessage - which DOES rebuild
frames. We just verify the path doesn't crash + produce captures for
visual inspection.
"""
@@ -28,7 +28,7 @@ def test_up_down_on_textmessage_survives(
lines: list[str] = request.node._debug_log_buffer
frame_capture("initial")
# Walk RIGHT until we land on textMessage up to 15 hops.
# Walk RIGHT until we land on textMessage - up to 15 hops.
for _i in range(15):
send_event(ui_port, InputEventCode.RIGHT)
time.sleep(0.3)
@@ -37,7 +37,7 @@ def test_up_down_on_textmessage_survives(
break
else:
pytest.skip(
"couldn't reach textMessage frame within 15 RIGHTs not present on this board"
"couldn't reach textMessage frame within 15 RIGHTs - not present on this board"
)
wait_for_frame(lines, "textMessage", timeout_s=5.0)
@@ -57,4 +57,4 @@ def test_up_down_on_textmessage_survives(
# The next test's `ui_home_state` will error out if the device is
# unresponsive, so we don't need a stricter guarantee here.
final = get_current_frame(lines)
assert final is not None, "no frame log after UP/DOWN event path broke"
assert final is not None, "no frame log after UP/DOWN - event path broke"
+2 -2
View File
@@ -25,9 +25,9 @@ def test_input_right_cycles_frames(
) -> None:
lines: list[str] = request.node._debug_log_buffer
start = get_current_frame(lines)
assert start is not None, "no frame log yet USERPREFS_UI_TEST_LOG not wired?"
assert start is not None, "no frame log yet - USERPREFS_UI_TEST_LOG not wired?"
# FN_F1 in ui_home_state lands on frame 0. The name at frame 0 varies
# by board (home on heltec-v3, deviceFocused on others) accept either.
# by board (home on heltec-v3, deviceFocused on others) - accept either.
assert start.name in (
"home",
"deviceFocused",
@@ -38,7 +38,7 @@ def test_up_down_on_nodelist_no_frame_change(
frame_capture("on-nodelist")
# UP/DOWN on nodelist scroll internally + `return 0` before
# notifyObservers no frame-change log. Verify.
# notifyObservers - no frame-change log. Verify.
send_event(ui_port, InputEventCode.UP)
assert_no_frame_change(lines, wait_s=1.5)
send_event(ui_port, InputEventCode.DOWN)