test(worker): Stopwatch + reconcile — fill gaps + lifecycle test
Fill the Stopwatch domain to 100% coverage (Stopwatch.tsx + stopwatch.ts, both now 100% stmts/branch/funcs/lines) and add the reconcile lifecycle test. New tests cover: idle display-tap start (and no-op without a handling), pair-count stepper floor + free-typed entry (non-positive ignored), clearing the handling via the empty option, stop/discard onSuccess reset, discard arm-window expiry, clearing a pending discard timer on reconcile and on unmount, and the reconcile lifecycle — running locally, then a poll without the local session resets the timer and shows the admin-stopped notice. No behaviour changes. Five defensive/unreachable guards in Stopwatch.tsx are annotated /* c8 ignore next -- <reason> */ (comment-only): the paused_seconds ?? 0 coalesce (contract types it non-null) and the early-return guards in handleSelectZool/handleStart/handleStop/handleDiscard (each triggered by a control disabled or unrendered in that state). No bugs found.
This commit is contained in:
@@ -558,3 +558,43 @@ Guaranteed behaviors:
|
||||
- Lifecycle (`src/screens/Activities.test.tsx`): create a handeling → edit its insole types down to a
|
||||
single type → reorder it above another → delete it, with each step reflected in the refetched list;
|
||||
the Sidebar test (`src/components/Sidebar.test.tsx`) covers navigation switching screens.
|
||||
|
||||
## Stopwatch + reconcile — worker client
|
||||
|
||||
Src covered (worker `apps/worker`): `src/screens/Stopwatch.tsx` and `src/lib/stopwatch.ts` — both at
|
||||
100% stmts/branch/funcs/lines. Five `c8 ignore`s with reasons in `Stopwatch.tsx`: the
|
||||
`paused_seconds ?? 0` coalesce in the reconcile adopt (the contract types `paused_seconds` as
|
||||
`z.number().int()`, never null) and the four early-return guards in `handleSelectZool`, `handleStart`,
|
||||
`handleStop`, and `handleDiscard` — each unreachable because the button that triggers it is
|
||||
disabled or not rendered in exactly that state (and the `handleStart` guard also narrows the type).
|
||||
|
||||
Guaranteed behaviors:
|
||||
|
||||
- `formatTime` renders zero-padded `HH:MM:SS`, floors a negative total at `00:00:00`, and lets hours
|
||||
exceed two digits; `elapsedSeconds` returns `(now − start − paused)` floored at 0 (paused time
|
||||
excluded).
|
||||
- The three sections (`Type zool` / `Type handeling` / `Aantal zolen`) and the Dutch Start button
|
||||
render; the zool segmented control offers `Kurk` / `Berk` / `3D` with `Kurk` selected by default.
|
||||
- Choosing a zooltype filters the handeling `<select>` to activities whose `insole_types` include that
|
||||
type and clears any previously chosen handeling; picking the empty option (`Kies een handeling...`)
|
||||
also clears the chosen handeling.
|
||||
- Start is disabled until a handeling is chosen; starting fires `useStartSession` with
|
||||
`{ activity_id, insole_type, pair_count }` from the current selection.
|
||||
- Pair count: the stepper `+`/`−` buttons adjust the count with a floor of 1 (the `−` button is
|
||||
disabled at 1); the free-typed field mirrors the raw text but only adopts a parsed value greater
|
||||
than 0 (a non-positive or non-numeric entry keeps the last valid count).
|
||||
- The stopwatch display is tappable: while idle with a handeling chosen it starts the session (idle
|
||||
tap with no handeling is a no-op); while running it pauses via `usePauseSession`; while paused it
|
||||
resumes via `useResumeSession` (folding the just-finished pause span into the local accumulator).
|
||||
- On a successful start the screen adopts the returned session's running state (id, start time, cleared
|
||||
pause); a paused server session is recovered into the paused UI (`Gepauzeerd — tik om te hervatten`).
|
||||
- Stop (`Stop & Opslaan`) and discard both reset the timer to idle on success; a `409` (already closed
|
||||
server-side) on either resets locally instead of leaving the timer stuck.
|
||||
- Discard is a double-tap: the first `Annuleren` tap arms it (`Nogmaals tikken ter bevestiging`) and the
|
||||
second confirms and fires `useDiscardSession`; the arm window lapses after 3s back to `Annuleren`, and
|
||||
a pending arm timer is cleared both on reconcile-reset and on unmount.
|
||||
- Reconcile against the active-sessions poll: while idle with a server-active session, the screen adopts
|
||||
it (phone-died / resume-elsewhere); the running-vs-server check keys on session id.
|
||||
- Lifecycle (`src/screens/Stopwatch.test.tsx`): running locally after a successful start, when the
|
||||
active-sessions poll returns a list **without** the local session (only another worker's), the timer
|
||||
resets to idle and the `Deze sessie is door de beheerder gestopt.` notice shows.
|
||||
|
||||
Reference in New Issue
Block a user