Files
HaloKeymind/test/test_indicator_messages_profile.py
T
mikecarper 7eb398aee9 Repair CI regressions for display policy and dual-radio sleep guards
Replace obsolete reader-timeout and message-thread source assertions with
compiled regressions for bookmark saving across battery/USB transitions and
newest-visible message summaries in History, Pending, and Unread modes.
Extend the MQTT sleep harness with dual-radio state and verify both blockers
release when disabled. All 19 post-native verification groups pass on Linux,
including the complete UI and browser runtime suites.
2026-09-13 08:44:55 -07:00

105 lines
4.3 KiB
Python

#!/usr/bin/env python3
from pathlib import Path
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
PROFILE = ROOT / "variants" / "sensecap_indicator-espnow" / "platformio.ini"
UI = ROOT / "examples" / "companion_radio" / "ui-new" / "UITask.cpp"
class IndicatorMessagesProfileTest(unittest.TestCase):
def test_touch_profile_has_one_navigation_bar_and_no_hidden_channel_targets(self):
profile = PROFILE.read_text()
ui = UI.read_text()
for flag in ("UI_BUTTON_READER_HINT", "UI_READER_TOUCH_BAR"):
self.assertIn(f"-D {flag}=1", profile)
self.assertIn("-D UI_MESSAGE_CHANNEL_FOOTER=0", profile)
self.assertIn("curr == msg_preview && UI_MESSAGE_CHANNEL_FOOTER == 1", ui)
# Compile the real gate: HAS_TOUCH must not overwrite the explicit
# physical-button footer setting with zero.
start = ui.index("#ifndef UI_BUTTON_READER_HINT")
gate = ui[start:ui.index("#if COMPANION_FEATURE_JOHN", start)]
result = subprocess.run(["c++", "-E", "-P", "-x", "c++", "-"],
input="#define HAS_TOUCH 1\n#define UI_BUTTON_READER_HINT 1\n" + gate +
"\n#if UI_BUTTON_READER_HINT != 1\n#error reader hint disabled\n#endif\n",
text=True, capture_output=True)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("static_cast<MsgPreviewScreen*>(msg_preview)->readerTouchBar()", ui)
self.assertIn("static_cast<JohnReaderScreen*>(john_reader)->readerTouchBar()", ui)
def test_indicator_enables_messages_home_page(self):
profile = PROFILE.read_text()
ui = UI.read_text()
self.assertIn("-D UI_MESSAGES_HOME_PAGE=1", profile)
self.assertIn("-D UI_COMPACT_MESSAGE_STATUS=1", profile)
self.assertIn("#if UI_MESSAGES_HOME_PAGE == 1\n MESSAGES,", ui)
self.assertIn("_page == HomePage::MESSAGES", ui)
def test_wifi_setup_is_eighth_without_reordering_existing_pages(self):
ui = UI.read_text(encoding="utf-8")
enum_start = ui.index(" enum HomePage {")
enum_end = ui.index("\n };", enum_start) + len("\n };")
enum_source = ui[enum_start:enum_end].replace(
" enum HomePage", "enum HomePage"
)
source = f"""
#define UI_MESSAGES_HOME_PAGE 1
#define COMPANION_EXCLUSIVE_WIFI_BLE 1
#define ENV_INCLUDE_GPS 0
#define UI_SENSORS_PAGE 1
#define UI_NO_HIBERNATE 1
#define UI_WIFI_SETUP_HOME_PAGE 1
{enum_source}
static_assert(FIRST == 0, "first");
static_assert(MESSAGES == 1, "messages");
static_assert(RECENT == 2, "recent");
static_assert(RADIO == 3, "radio");
static_assert(TRANSPORT == 4, "transport");
static_assert(ADVERT == 5, "advert");
static_assert(SENSORS == 6, "sensors");
static_assert(WIFI_SETUP == 7, "wifi setup");
static_assert(Count == 8, "count");
int main() {{ return 0; }}
"""
with tempfile.TemporaryDirectory() as temp_dir:
executable = Path(temp_dir) / "home_pages"
compiled = subprocess.run(
["c++", "-std=c++11", "-x", "c++", "-", "-o", str(executable)],
input=source,
text=True,
capture_output=True,
check=False,
)
self.assertEqual(compiled.returncode, 0, compiled.stderr)
def test_full_message_chrome_uses_compact_visuals_only(self):
ui = UI.read_text(encoding="utf-8")
touch = (ROOT / "src/helpers/ui/TouchInput.h").read_text(
encoding="utf-8"
)
self.assertIn("makeCompanionMessageChromeLayout", ui)
self.assertIn("display.setCompactText(layout.compact_text)", ui)
self.assertIn("display.setCompactText(false)", ui)
self.assertIn("_start_y >= (height * 3) / 4", touch)
self.assertIn("_task->renderMessageSummary(display);", ui)
def test_history_is_not_cleared_when_companion_drains_messages(self):
ui = UI.read_text()
self.assertNotIn("MsgPreviewScreen*>(msg_preview)->clear()", ui)
self.assertIn(
"companionMessageElapsedMillis(entry->heard_millis)", ui
)
self.assertIn("esp_timer_get_time()", ui)
# Thread selection must respect the selected inbox view. The compiled
# summary regression in test_companion_inbox covers this behavior.
if __name__ == "__main__":
unittest.main()