Tracking app — system tests (TRK-ST-*)
Human-driven protocol for @enode/tracking, executed on a real device
(iOS or Android Capacitor build) against backdev. Environment, accounts,
and run recording: system test plan. Requirements
covered: tracking-app.md +
shared.md.
Work top to bottom; sections marked (hardware) need SmartBar sensors.
Record Result (✅ / ❌ / ⚠️ / ⛔) and Notes in a copy of the run
template (docs/testing/test-runs/_template.md). Case IDs are
TRK-ST-<section>.<case> and are stable — append, never renumber.
Preconditions for the whole run: Pro coach account on backdev with today's scheduled workout, ≥1 template, ≥2 athletes; a One account; 2 charged SmartBar sensors; device with camera permission available.
1. Auth & app entry
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 1.1 | Pro sign-in | SHR-AUTH-01, TRK-AUTH-01 | Fresh install/cleared storage → sign in with the Pro coach account | Login transition plays; lands on /workouts/today with today's schedule | [automate] | |
| 1.2 | One user blocked | TRK-AUTH-02 | Sign in with the One account | Blocked with a message pointing to the One app (backend 314); no session created | ||
| 1.3 | Registration | SHR-AUTH-03 | Register a fresh account; try an invalid email/short password on the way | Validation errors shown on the step; valid input completes and signs in | ||
| 1.4 | Cold-start redirect | SHR-AUTH-02 | Kill the app while signed in; relaunch | No login screen; straight to /workouts/today | [automate] | |
| 1.5 | Sign out | SHR-AUTH-05 | Sign out from the profile/settings drawer | Returns to login; relaunch shows login (token cleared) |
2. Today's schedule
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 2.1 | Week's workouts listed | TRK-SCHED-01 | Open the today pane | Today's scheduled + recurring workouts for the current week appear with correct names | [automate] | |
| 2.2 | Pull-to-refresh | TRK-SCHED-02 | Create a new scheduled workout for today in the portal, then pull to refresh | The new workout appears without app restart | ||
| 2.3 | Empty state | TRK-SCHED-03 | Use an account/day with no workouts | Explicit empty state (no blank screen, no error) | ||
| 2.4 | Load failure retry | TRK-SCHED-03, SHR-ERR-04 | Load the pane with connectivity off, then restore and tap "Try again" | Failure shows the try-again state; retry recovers to the list |
3. Stations & recording slots
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 3.1 | Multi-station layout | TRK-STATION-01 | On a tablet, open 3 stations; on a phone observe layout | Tablet: up to 3 columns side by side; phone: exactly 1 full-viewport station | ||
| 3.2 | Open/close stations | TRK-STATION-02 | Open stations from the rail/spine; close one; shrink so open stations no longer fit | Stations open/close cleanly; the "close hidden stations" confirm appears when they don't fit | ||
| 3.3 | Recording-slot licensing | TRK-STATION-03 | Open more stations than the device session's recording weight allows; try to record in an over-limit station | Over-limit station shows the "request another slot" overlay instead of recording | ||
| 3.4 | Athlete pinned to one station | TRK-STATION-04 | Sign in as an athlete-role user | Only a single station is available |
4. Starting & editing workouts
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 4.1 | Start scheduled workout | TRK-WORKOUT-01 | FAB → start today's scheduled workout in a station | Prep drawer shows its exercises/participants; starting mounts the live session in that station | [automate] | |
| 4.2 | Create workout from scratch | TRK-WORKOUT-01 | FAB → new workout → add 2 exercises + 1 participant → start | Session starts with exactly those exercises/participants | ||
| 4.3 | Start from template | TRK-WORKOUT-01 | FAB → template picker → pick the test template → start | Session matches the template's exercises | ||
| 4.4 | Pre-start editing | TRK-WORKOUT-02 | Before starting: edit participants, tags, notes; build a superset; reorder exercises | All edits reflected in the prep drawer and carried into the started session | ||
| 4.5 | Feedback-only training | TRK-WORKOUT-03 | FAB → feedback (sensor-only) training | Sensor-only session starts without a workout plan | ||
| 4.6 | Retrospective log | TRK-WORKOUT-04 | FAB → log past workout → pick a source workout → fill sets → save | Filled sets upload; the session appears in history as a past workout | ||
| 4.7 | Blocked athlete can't record | TRK-WORKOUT-05 | Add a blocked athlete + an active one to a workout; start it; complete a set for the active athlete; finish | Picker warns "No data will be recorded" but still allows the pick; the blocked athlete's chip is badged; they are absent from the athlete switcher; the upload carries only the active athlete's session | needs a blocked athlete on backdev | |
| 4.8 | All-blocked workout can't start | TRK-WORKOUT-05 | Build a workout whose only participant(s) are blocked | Start is disabled with "No data can be recorded for these athletes." | needs a blocked athlete on backdev | |
| 4.9 | Archived athlete hidden from a workout | SHR-ARCH-01, SHR-ARCH-02 | Schedule a workout for 2 athletes in the portal; archive one; reopen the workout in tracking and start it | The archived athlete is absent from the participant chips and the athlete switcher; the picker doesn't offer them; finishing uploads no session for them. The other athlete is unaffected | needs an athlete archived after scheduling |
5. Sensors & live tracking (hardware)
Precondition: 2 charged SmartBar sensors; Bluetooth on.
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 5.1 | Single-sensor pairing | TRK-LIVE-01 | In a live session, open the connect-sensor sheet; connect 1 sensor | Sensor pairs; connection state visible on the station | ||
| 5.2 | Dual-sensor + placement | TRK-LIVE-01 | Connect a 2nd sensor to the same station | Both pair; the sensor-placement prompt guides positioning | ||
| 5.3 | Live rep detection | TRK-LIVE-02 | Perform a set of ~5 controlled reps with the sensor on a bar | Reps appear live (pending-rep overlay/flash); final count matches performed reps | ||
| 5.4 | Focus metric & rest timer | TRK-LIVE-03 | Complete a set; observe between-set UI | Configured focus metric shown for the set; rest timer counts toward the rest target | ||
| 5.5 | Video capture | TRK-VIDEO-01 | Record a clip via the camera overlay during a set | Clip records and attaches to the set; no crash on permission grant | ||
| 5.6 | Video review | TRK-VIDEO-02 | Open the recorded clip | Player opens; scrubbing works |
6. Set completion & in-session tools
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 6.1 | Complete-set sheet | TRK-LIVE-04 | After a set, open the complete-set sheet; adjust reps and load; save | Detected values pre-filled; edits persist to the set list | ||
| 6.2 | Edit 1RM | TRK-LIVE-05 | Edit a participant's 1RM in-session; repeat on a bodyweight exercise | New 1RM applies to load recommendations; bodyweight handled (no absurd values) | ||
| 6.3 | Reorder sets | TRK-LIVE-06 | Drag a set to a new position via the move-set drawer | New order persists | ||
| 6.4 | Recommendations | TRK-LIVE-07 | Trigger conditions for a switch/rest-stop recommendation (e.g. degrading velocity across sets) | Recommendation card appears; accepting it applies the change | flag SWITCH_RECOMMENDATIONS | |
| 6.5 | Spoken rep feedback | TRK-LIVE-08 | Enable rep voice; perform reps | Reps spoken via TTS, matching the on-screen feedback | flag-gated | |
| 6.6 | Muscle-quality view | TRK-LIVE-09 | Open the muscle-quality body view mid-session | Body view renders with plausible per-muscle tinting; no crash | ||
| 6.7 | Technique feedback mode | TRK-LIVE-10 | Set the feedback mode to Technique on a barbell exercise; record a set with the camera overlay open, then one without it; repeat on a flywheel exercise | Sagittal + frontal bar path render side by side over their body backdrops; the focus-metric values are fully readable (not vertically clipped) in both layouts; the flywheel exercise shows metrics/velocity only, with no empty trajectory grid | Layout preview without a sensor: /debug/recording |
7. Insights & finishing
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 7.1 | Overview tab | TRK-INSIGHT-01 | Open the insights sheet after ≥2 completed sets | Session summary reflects completed sets | ||
| 7.2 | Performance tab | TRK-INSIGHT-02 | Open the Performance tab | Per-metric/per-rep charts render for the session's sets | ||
| 7.3 | Technique tab | TRK-INSIGHT-03 | Open the Technique tab after a sensor set | Orientation/velocity traces render; force vectors per flag state | flag FORCE_VECTORS | |
| 7.4 | Finish → set review | TRK-FINISH-01 | Finish the training | Set-review overlay lists all sets for confirmation | ||
| 7.5 | Results persisted | TRK-FINISH-02 | Confirm the review; then check portal history | Session appears in the portal history with matching sets | [automate] (assertion half) | |
| 7.6 | Technique follows the latest set | TRK-INSIGHT-05 | Record ≥2 sensor sets, open the Technique tab, then record another set | The tab opens on the newest set (not set 1) and switches to each newly recorded set as it arrives | Also check the tablet split view (trackingDetailMode), where the tab stays mounted | |
| 7.7 | Empty finish is confirmed | TRK-FINISH-03 | Start a training, record nothing, tap "Finish training" | "Nothing recorded yet" confirm appears; "Keep training" (or backdrop/Escape/Back) returns to the training with the workout intact; "Close and discard" closes it | Regression: with ≥1 completed set the confirm must NOT appear | |
| 7.8 | Sensor prompt is escapable | TRK-FINISH-04 | With a sensor paired, trigger finish and discard; on "Keep sensor connected?" use the corner ✕, backdrop, Escape and Back in turn | Each returns to the training — sensor still connected, sets and videos intact, station not closed | One Back press closes only the prompt; a second shows "Leave training?" |
8. Offline, sync & crash recovery
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 8.1 | Offline banner | TRK-OFFLINE-01, SHR-ERR-01 | Enable airplane mode in the app | Offline banner appears; disabling it clears the banner | ||
| 8.2 | Offline start | TRK-OFFLINE-01 | With today's bundle loaded, go offline; start a cached workout | Workout starts and is trackable without network | ||
| 8.3 | Upload drain | TRK-OFFLINE-02 | Complete a (manual-entry) training while offline; observe the pending-uploads indicator; go online | Indicator shows queued upload; reconnect drains it; session reaches the backend | ||
| 8.4 | Crash recovery | TRK-OFFLINE-03 | Mid-training, force-kill the app; relaunch | "Resume interrupted training?" prompt; resuming restores the session state (sets, participants) | ||
| 8.5 | Leave-training guard | TRK-OFFLINE-04 | Mid-training, press system back / edge-swipe | Discard confirmation appears; cancel keeps the session intact |
9. Settings & profile
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 9.1 | Settings & version | TRK-SET-01 | Open settings and profile drawers from the spine/header | Both open; app version displayed | ||
| 9.2 | Unit switch | SHR-UNITS-01, SHR-UNITS-02, TRK-SET-02 | Toggle metric ↔ imperial; look at loads in an open session and 1RM sheet | All weights convert immediately, no reload | ||
| 9.3 | Language switch | SHR-I18N-02, SHR-I18N-03, TRK-SET-02 | Switch the app language | Static UI text changes language; exercise names stay correctly localized by id | ||
| 9.4 | i18n scan | SHR-I18N-01 | Scan all screens visited this run | No raw translation keys, undefined, or untranslated dev strings |
10. Cross-cutting & platform
| # | Use case | Covers | Steps | Expected result | Result | Notes |
|---|---|---|---|---|---|---|
| 10.1 | Keep-awake | TRK-PLATFORM-01 | Leave a live session idle past the device's screen timeout | Screen stays on during the session; normal timeout applies outside a session | ||
| 10.2 | Error surfaces | SHR-ERR-02 | Provoke a recoverable failure (e.g. save with backend briefly unreachable) | Toast/inline alert with the backend's message or translated fallback — no raw error, no crash | ||
| 10.3 | Native shell sanity | TRK-PLATFORM-02 | Run the full protocol on the Capacitor build | Safe areas respected (no content under notch/home bar); API calls succeed through the native HTTP stack | ||
| 10.4 | Debug hidden in prod | TRK-PLATFORM-03 | On a production build, navigate to /debug | 404 / not found; no debug entry point visible |
Coverage table
| Requirement | Cases |
|---|---|
| TRK-AUTH-01 | 1.1 |
| TRK-AUTH-02 | 1.2 |
| TRK-SCHED-01 | 2.1 |
| TRK-SCHED-02 | 2.2 |
| TRK-SCHED-03 | 2.3, 2.4 |
| TRK-STATION-01 | 3.1 |
| TRK-STATION-02 | 3.2 |
| TRK-STATION-03 | 3.3 |
| TRK-STATION-04 | 3.4 |
| TRK-WORKOUT-01 | 4.1, 4.2, 4.3 |
| TRK-WORKOUT-02 | 4.4 |
| TRK-WORKOUT-03 | 4.5 |
| TRK-WORKOUT-04 (flag on) | 4.6 |
| TRK-WORKOUT-05 | 4.7, 4.8 |
| SHR-ARCH-01/02 | 4.9 |
| TRK-LIVE-01 | 5.1, 5.2 |
| TRK-LIVE-02 | 5.3 |
| TRK-LIVE-03 | 5.4 |
| TRK-LIVE-04 | 6.1 |
| TRK-LIVE-05 | 6.2 |
| TRK-LIVE-06 | 6.3 |
| TRK-LIVE-07 (flag) | 6.4 |
| TRK-LIVE-08 (flag) | 6.5 |
| TRK-LIVE-09 | 6.6 |
| TRK-VIDEO-01 | 5.5 |
| TRK-VIDEO-02 | 5.6 |
| TRK-INSIGHT-01 | 7.1 |
| TRK-INSIGHT-02 | 7.2 |
| TRK-INSIGHT-03 (flag) | 7.3 |
| TRK-INSIGHT-04 | — mocked; known behaviour |
| TRK-FINISH-01 | 7.4 |
| TRK-FINISH-02 | 7.5 |
| TRK-OFFLINE-01 | 8.1, 8.2 |
| TRK-OFFLINE-02 | 8.3 |
| TRK-OFFLINE-03 | 8.4 |
| TRK-OFFLINE-04 | 8.5 |
| TRK-SET-01 | 9.1 |
| TRK-SET-02 | 9.2, 9.3 |
| TRK-SET-03 | — flag off; not testable |
| TRK-PLATFORM-01 | 10.1 |
| TRK-PLATFORM-02 | 10.3 |
| TRK-PLATFORM-03 | 10.4 |
| SHR-AUTH-01/02/03/05 | 1.1, 1.4, 1.3, 1.5 |
| SHR-I18N-01/02/03 | 9.4, 9.3 |
| SHR-UNITS-01/02 | 9.2 |
| SHR-ERR-01/02/04 | 8.1, 10.2, 2.4 |
Known/expected behaviours (not defects)
- Insight tabs show placeholder skeletons while history/metrics load
(
SKELETON_PREVIEW, TRK-INSIGHT-04) — visual placeholders, not wrong data. - The enode Portal link in the sidebar is intentionally hidden
(
PORTAL_LINK_ENABLED = false, TRK-SET-03). - Flag-gated cases (6.4, 6.5, 7.3 force vectors, 4.6) apply only when the flag is ON in the release build — note the flag state in the run file.
- Device-session recording weight is dev-toggleable pending backend support; use the value your license actually grants for 3.3.