feat: add operator console and wire test scripts with event emission

- Add TestEventsPlugin for receiving ADB broadcast intents
- Create operator console UI (console/index.html, console.css, console.js)
- Add test plan structure (plan.json) with phases, tests, and steps
- Wire all test scripts (phase1, phase2, phase3) with step context and events
- Add event emission helpers to alarm-test-lib.sh (step_start, step_pass, etc.)
- Update test-phase1.sh with comprehensive prerequisite verification
- Register TestEventsPlugin in capacitor.plugins.json
- Add console documentation (CONSOLE-USAGE.md, CONSOLE-REMAINING-WORK.md)
- Add test implementation alignment tracking (TEST-IMPLEMENTATION-ALIGNMENT.md)

This enables real-time test progress tracking via structured events
from shell scripts to the operator console UI.
This commit is contained in:
Matthew Raymer
2025-12-29 09:37:12 +00:00
parent b53042d679
commit f6df9e13fb
13 changed files with 3216 additions and 7 deletions

View File

@@ -51,6 +51,9 @@ extract_scenario_from_logs() {
test1_boot_future_alarms() {
section "TEST 1: Boot with Future Alarms"
# Set test context
set_test_context "phase3" "phase3_test1" ""
info "Purpose: Verify alarms are recreated on boot when schedules have future run times."
info "Expected time: 2-3 minutes (includes 30-60s reboot)"
info "Automatable: Partial (requires manual reboot confirmation)"
@@ -60,6 +63,8 @@ test1_boot_future_alarms() {
pause
# Capture initial state
set_test_context "phase3" "phase3_test1" "p3_t1_s1"
step_start "p3_t1_s1" "Launch app & check plugin status"
capture_alarms "phase3_test1_initial"
capture_logcat "phase3_test1_initial" "DNP" 50
@@ -75,10 +80,14 @@ test1_boot_future_alarms() {
ui_prompt "2) Now schedule at least one future notification (e.g., click 'Test Notification' to schedule for a few minutes in the future)."
step_pass "p3_t1_s1" "Plugin configured and notification scheduled"
# Capture before reboot state
capture_alarms "phase3_test1_before_reboot"
substep "Step 2: Verify alarms are scheduled"
set_test_context "phase3" "phase3_test1" "p3_t1_s2"
step_start "p3_t1_s2" "Verify alarms scheduled"
show_alarms
local before_count system_before
before_count="$(get_plugin_alarm_count)"
@@ -88,20 +97,28 @@ test1_boot_future_alarms() {
if [[ "$before_count" -eq 0 ]]; then
warn "No plugin alarms found before reboot; TEST 1 may not be meaningful."
step_warn "p3_t1_s2" "No alarms found"
elif [[ "$before_count" -eq 1 ]]; then
ok "Single plugin alarm confirmed (one per day)"
step_pass "p3_t1_s2" "Alarms verified"
else
warn "Found $before_count plugin alarms (expected: 1)"
step_warn "p3_t1_s2" "Unexpected alarm count"
fi
pause
substep "Step 3: Reboot emulator"
set_test_context "phase3" "phase3_test1" "p3_t1_s3"
step_start "p3_t1_s3" "Reboot emulator"
warn "The emulator will reboot now. This will take 30-60 seconds."
pause
reboot_emulator
step_pass "p3_t1_s3" "Emulator rebooted"
substep "Step 4: Collect boot recovery logs"
set_test_context "phase3" "phase3_test1" "p3_t1_s4"
step_start "p3_t1_s4" "Collect boot recovery logs"
info "Collecting recovery logs from boot..."
sleep 2 # Give recovery a moment to complete
@@ -167,11 +184,16 @@ test1_boot_future_alarms() {
warn "Alarms were not recreated despite recovery success. Check alarm scheduling logic."
test1_message="Boot recovery succeeded but alarms not recreated (rescheduled=$rescheduled, after_count=$after_count)"
test1_passed=false
step_fail "p3_t1_s4" "Alarms not recreated"
elif [[ "$after_count" -gt 0 && "$test1_passed" == "true" ]]; then
ok "Alarms successfully recreated after boot (after_count=$after_count)"
step_pass "p3_t1_s4" "Boot recovery successful"
else
step_fail "p3_t1_s4" "Boot recovery failed"
fi
# Emit verdict
set_test_context "phase3" "phase3_test1" "p3_t1_s5"
if [[ "$test1_passed" == "true" ]]; then
verdict_pass "phase3_test1_boot_future_alarms" "$test1_message"
else
@@ -188,6 +210,9 @@ test1_boot_future_alarms() {
test2_boot_past_alarms() {
section "TEST 2: Boot with Past Alarms"
# Set test context
set_test_context "phase3" "phase3_test2" ""
info "Purpose: Verify missed alarms are detected and next occurrence is scheduled on boot."
info "Expected time: 5-6 minutes (includes 3min wait + 30-60s reboot)"
info "Automatable: Partial (requires manual time advancement or wait)"
@@ -198,6 +223,8 @@ test2_boot_past_alarms() {
pause
# Capture initial state
set_test_context "phase3" "phase3_test2" "p3_t2_s1"
step_start "p3_t2_s1" "Schedule notification for past time"
capture_alarms "phase3_test2_initial"
capture_logcat "phase3_test2_initial" "DNP" 50
@@ -215,18 +242,25 @@ test2_boot_past_alarms() {
After scheduling, we'll wait for the alarm time to pass, then reboot."
step_pass "p3_t2_s1" "Notification scheduled"
# Capture before wait state
capture_alarms "phase3_test2_before_wait"
substep "Step 2: Wait for alarm time to pass"
set_test_context "phase3" "phase3_test2" "p3_t2_s2"
step_start "p3_t2_s2" "Wait for alarm time to pass"
info "Waiting 3 minutes for scheduled alarm time to pass..."
warn "You can manually advance system time if needed (requires root/emulator)"
sleep 180 # Wait 3 minutes
step_pass "p3_t2_s2" "Alarm time passed"
# Capture after wait state
capture_alarms "phase3_test2_after_wait"
substep "Step 3: Verify alarm time has passed"
set_test_context "phase3" "phase3_test2" "p3_t2_s3"
step_start "p3_t2_s3" "Reboot emulator"
info "Alarm time should now be in the past"
show_alarms
@@ -236,8 +270,11 @@ test2_boot_past_alarms() {
warn "The emulator will reboot now. This will take 30-60 seconds."
pause
reboot_emulator
step_pass "p3_t2_s3" "Emulator rebooted"
substep "Step 5: Collect boot recovery logs"
set_test_context "phase3" "phase3_test2" "p3_t2_s4"
step_start "p3_t2_s4" "Collect boot recovery logs"
info "Collecting recovery logs from boot..."
sleep 2
@@ -288,7 +325,14 @@ test2_boot_past_alarms() {
test2_message="No missed alarms detected. Verify alarm time actually passed before reboot (missed=$missed, rescheduled=$rescheduled)"
fi
if [[ "$test2_passed" == "true" ]]; then
step_pass "p3_t2_s4" "Past alarms detected and rescheduled"
else
step_fail "p3_t2_s4" "Past alarms not detected"
fi
# Emit verdict
set_test_context "phase3" "phase3_test2" "p3_t2_s5"
if [[ "$test2_passed" == "true" ]]; then
verdict_pass "phase3_test2_boot_past_alarms" "$test2_message"
else
@@ -305,6 +349,9 @@ test2_boot_past_alarms() {
test3_boot_no_schedules() {
section "TEST 3: Boot with No Schedules"
# Set test context
set_test_context "phase3" "phase3_test3" ""
info "Purpose: Verify boot recovery handles empty database gracefully."
info "Expected time: 2-3 minutes (includes 30-60s reboot)"
info "Automatable: Yes"
@@ -314,6 +361,8 @@ test3_boot_no_schedules() {
pause
# Capture initial state (before uninstall)
set_test_context "phase3" "phase3_test3" "p3_t3_s1"
step_start "p3_t3_s1" "Fresh install"
capture_alarms "phase3_test3_initial"
substep "Step 1: Uninstall app to clear DB/state"
@@ -325,8 +374,10 @@ test3_boot_no_schedules() {
substep "Step 2: Reinstall app"
if $ADB_BIN install -r "$APK_PATH"; then
ok "App installed"
step_pass "p3_t3_s1" "Fresh install complete"
else
error "Reinstall failed"
step_fail "p3_t3_s1" "Reinstall failed"
exit 1
fi
@@ -337,12 +388,17 @@ test3_boot_no_schedules() {
pause
substep "Step 3: Reboot emulator WITHOUT scheduling anything"
set_test_context "phase3" "phase3_test3" "p3_t3_s2"
step_start "p3_t3_s2" "Reboot without schedules"
warn "Do NOT schedule any notifications. The app should have no schedules in the database."
warn "The emulator will reboot now. This will take 30-60 seconds."
pause
reboot_emulator
step_pass "p3_t3_s2" "Emulator rebooted"
substep "Step 4: Collect boot recovery logs"
set_test_context "phase3" "phase3_test3" "p3_t3_s3"
step_start "p3_t3_s3" "Verify no recovery ran"
info "Collecting recovery logs from boot..."
sleep 2
@@ -390,7 +446,14 @@ test3_boot_no_schedules() {
test3_message="Logs present but no rescheduling; review scenario handling to ensure it's explicit about NONE / NO_SCHEDULES (scenario=${scenario:-<none>}, rescheduled=$rescheduled)"
fi
if [[ "$test3_passed" == "true" ]]; then
step_pass "p3_t3_s3" "No recovery ran (correct)"
else
step_fail "p3_t3_s3" "Recovery ran when it shouldn't"
fi
# Emit verdict
set_test_context "phase3" "phase3_test3" "p3_t3_s4"
if [[ "$test3_passed" == "true" ]]; then
verdict_pass "phase3_test3_boot_no_schedules" "$test3_message"
else
@@ -407,6 +470,9 @@ test3_boot_no_schedules() {
test4_silent_boot_recovery() {
section "TEST 4: Silent Boot Recovery (App Never Opened)"
# Set test context
set_test_context "phase3" "phase3_test4" ""
info "Purpose: Verify boot recovery occurs even when the app is never opened after reboot."
info "Expected time: 2-3 minutes (includes 30-60s reboot)"
info "Automatable: Partial (requires manual verification that app was not opened)"
@@ -416,6 +482,8 @@ test4_silent_boot_recovery() {
pause
# Capture initial state
set_test_context "phase3" "phase3_test4" "p3_t4_s1"
step_start "p3_t4_s1" "Schedule notification"
capture_alarms "phase3_test4_initial"
capture_logcat "phase3_test4_initial" "DNP" 50
@@ -431,10 +499,14 @@ test4_silent_boot_recovery() {
ui_prompt "2) Click 'Test Notification' to schedule a notification for a few minutes in the future."
step_pass "p3_t4_s1" "Notification scheduled"
# Capture before reboot state
capture_alarms "phase3_test4_before_reboot"
substep "Step 2: Verify alarms are scheduled"
set_test_context "phase3" "phase3_test4" "p3_t4_s2"
step_start "p3_t4_s2" "Reboot without opening app"
show_alarms
local before_count system_before
before_count="$(get_plugin_alarm_count)"
@@ -444,10 +516,13 @@ test4_silent_boot_recovery() {
if [[ "$before_count" -eq 0 ]]; then
warn "No plugin alarms found; TEST 4 may not be meaningful."
step_warn "p3_t4_s2" "No alarms found"
elif [[ "$before_count" -eq 1 ]]; then
ok "Single plugin alarm confirmed (one per day)"
step_pass "p3_t4_s2" "Alarms verified"
else
warn "Found $before_count plugin alarms (expected: 1)"
step_warn "p3_t4_s2" "Unexpected alarm count"
fi
pause
@@ -457,8 +532,11 @@ test4_silent_boot_recovery() {
warn "The emulator will reboot now. This will take 30-60 seconds."
pause
reboot_emulator
step_pass "p3_t4_s2" "Emulator rebooted (app not opened)"
substep "Step 4: Collect boot recovery logs (without opening app)"
set_test_context "phase3" "phase3_test4" "p3_t4_s3"
step_start "p3_t4_s3" "Collect boot recovery logs"
info "Collecting recovery logs from boot (app was NOT opened)..."
sleep 2
@@ -518,7 +596,14 @@ test4_silent_boot_recovery() {
test4_message="Boot recovery not detected. Verify boot receiver is registered and has BOOT_COMPLETED permission (scenario=${scenario:-<none>}, rescheduled=$rescheduled)"
fi
if [[ "$test4_passed" == "true" ]]; then
step_pass "p3_t4_s3" "Silent boot recovery successful"
else
step_fail "p3_t4_s3" "Silent boot recovery failed"
fi
# Emit verdict
set_test_context "phase3" "phase3_test4" "p3_t4_s4"
if [[ "$test4_passed" == "true" ]]; then
verdict_pass "phase3_test4_silent_boot_recovery" "$test4_message"
else