Files
portal/docs/scheduler-overhaul-phase5-results.md
T

9.7 KiB

Scheduler Overhaul — Phase 5 Verification Results

Prepared during Phase 5 against a locally running Portal on a fresh database. This records what was actually executed and observed. It is a companion to scheduler-overhaul-release-notes.md (rollout steps) and schedule-api-contract.md (the contract). Where a scenario could not be run without real Kiosk hardware or an interactive display, the row is marked and the equivalent automated coverage is cited.

Environment:

  • Portal dev server (npm run dev) on http://localhost:5173, pointed at a fresh scratch database (rwportal_p5) created and migrated for this phase.
  • Kiosk schedule logic exercised through the C++ test harness (test_schedule_engine) and the Kiosk API client's JSON parsing.
  • No display/Xvfb available, so the SDL Kiosk UI was not driven interactively; see the manual checklist in the release notes.

Legend: PASS = executed, AUTO = verified by automated test (not interactively), MANUAL = requires a human on hardware/display.

# Scenario Result Evidence / notes
a Kiosk shows AM/PM everywhere; System Settings contains Email, License Key, System Name, Schedule toggle, WiFi, Timezone, Date Format AUTO test_date_format (12h conversion), test_settings_menu (exactly the 7 entries incl. System Name + Schedule). UI rendering itself is MANUAL.
b Validate a License Key, name the Kiosk, see the name read-only on the Portal PASS + MANUAL HTTP: validation without name → 200 unchanged; with name → 200 ok. Portal render is MANUAL (release-notes checklist).
c Two systems in one account: duplicate name in any casing rejected and reverted on the Kiosk PASS HTTP: case-insensitive duplicate → validation 200 conflict; PUT duplicate → 409 name_taken; blank → 400 invalid_name; unknown → 404 unknown_license. Kiosk revert covered by test_license_service/test_system_name.
d Rename a system on the Kiosk; its Schedule stays attached (License Key reference) AUTO Schedules are keyed by licenseKeyId; naming only touches systemName. Portal schedule-copy/service tests operate purely on License Key IDs.
e Create a daily Schedule via the Portal picker; Kiosk fetches and applies it PASS Opt-in integration spec: daily schedule with 2 blocks created via the service; key-only GET returns it; captured live payload parsed and evaluated by the Kiosk (SchedulePortalParityTest).
f Weekly: Block boundaries, adjacent (end 7:00 / start 7:00), midnight-crossing, Sunday→Monday spillover PASS + AUTO Integration spec: weekly sun crossing + adjacent mon blocks, Sunday spillover collision rejected. Engine tests: adjacency boundary, midnight self-wrap, Sunday→Monday spillover.
g Gap plays local Proclamations; dynamicAudio true → dynamic, false → local AUTO Engine tests: gaps return no block; per-block dynamicAudio flag; ScrollerPage::effectiveDynamicAudio honored via playback wiring (build passes).
h Schedule toggle Off stops schedule effects; On resumes AUTO ScheduleManagerTest.DisabledReturnsNoBlock; toggle stored in config.yaml (schedule_enabled, default on).
i Schedules assigned to system A never affect system B PASS Integration spec: A daily, B weekly simultaneously; independent payloads.
j Copy a Schedule to another named system; that Kiosk picks it up PASS Integration spec: copy A→second system yields daily with 2 blocks; independence confirmed; target ETag differs. Portal schedule-copy.spec covers overwrite/multi-target/rollback/new IDs.
k Offline uses cached Schedule; corrupt cache ignored; timezone change re-evaluates AUTO ScheduleCacheTest (round-trip, corrupt ignored), ScheduleManagerTest (offline cache, 304 handled). Timezone is passed as wall-clock minutes (wall-clock means DST-safe).
l Portal shows geoip/fallback timezone with kiosk-timezone note; manual minute entry alongside 5-minute options AUTO UI note is browser-fallback (no external dep); TimeInput tests cover 5-minute options and typed minutes. Visual render MANUAL.

Additional checks

Check Result Notes
Old-Kiosk compatibility (validate without systemName; legacy schedule endpoint) PASS 200 unchanged; name never cleared; legacy GET /api/v2/schedule still returns email + blocks; modern vs legacy version equal.
Cross-account isolation PASS Legacy schedule with another account's key → 400; copy rejects non-owned source/targets.
Conditional GET PASS Matching If-None-Match → 304; stale ETag → 200; unknown key → 404.
Migration up PASS Applied cleanly to a fresh DB (29 migrations); fresh seed succeeded.
Migration down/up on realistic data PASS (with caveat) Phase 2 and Phase 3 down/up round-tripped structurally on a clone; the Phase 3 down path is lossy (deletes per-License-Key schedules). Documented in the contract (Open item 22) and release notes.
Portal svelte-check / ESLint / tests PASS 0 errors/warnings; 394 passed, 4 skipped (opt-in integration).
Kiosk build + tests PASS Full build; 21 test binaries pass.
Formatters PASS Portal Prettier clean except the pre-existing .gitea/workflows/deploy.yaml (unchanged from before this branch). Kiosk follows .clang-format (no binary available to run).

Not verified here (requires hardware/display)

The interactive SDL Kiosk UI (rendering, key handling, onboarding walkthrough) was not driven; all Kiosk behavior above is covered by the engine/client/cache tests and by parsing live Portal payloads. See the manual checklist in scheduler-overhaul-release-notes.md.