test(api): Work-sessions — fill gaps + lifecycle test
Drives src/routes/sessions.ts and src/lib/work-session.ts to 100% stmts/branch/funcs/lines (branch was 84.12% / 83.33%). - sessions.test.ts: added error/edge branch tests — malformed-JSON start (400), non-numeric id on pause/resume/stop/discard (404), pause/resume of a no-longer-active session (409), discard missing (404) + already-closed (409), stop missing (404), and discard ownership scoping (user B → 404). - work-session.test.ts: mapper unit tests — null insoleType, nullish pausedSeconds → 0, null durationSeconds/notes, full-field shape with activity/user opts, and opts defaulting to undefined. - test/integration/worker-session-lifecycle.test.ts: the anchor lifecycle test (start→pause→resume→stop→history→export). No bugs found — the code was correct. The two remaining uncovered branches were the defensive `row.pausedSeconds ?? 0` guards in resume/stop; pausedSeconds is NOT NULL DEFAULT 0 in the schema, so the null branch is unreachable via any route. Annotated both with `/* c8 ignore next -- reason */` (comment only, no behavior change).
This commit is contained in:
@@ -90,3 +90,40 @@ Guaranteed behaviors:
|
||||
unknown id).
|
||||
- Lifecycle: an admin creates three activities → reorders them → a worker's GET reflects the new
|
||||
order → the admin deletes one → it is gone from the list.
|
||||
|
||||
## Work-sessions
|
||||
|
||||
Src covered: `src/routes/sessions.ts` and `src/lib/work-session.ts` — both at
|
||||
100% stmts/branch/funcs/lines. The two `row.pausedSeconds ?? 0` guards in `sessions.ts`
|
||||
(resume/stop) are `c8 ignore`d with a reason — `paused_seconds` is `NOT NULL DEFAULT 0`, so the
|
||||
null branch is unreachable via any route.
|
||||
|
||||
Guaranteed behaviors:
|
||||
|
||||
- `start`, `pause`, `resume`, `stop`, `discard` all require a session (401 without a token), as do
|
||||
the reads `GET /api/sessions` and `GET /api/sessions/active`.
|
||||
- `POST /api/sessions/start`: 200 creates an `active`, `source: 'app'` session (null `end_time` /
|
||||
`duration_seconds`); 400 on an invalid body **and** on a malformed-JSON body; 404 when the
|
||||
`activity_id` does not exist.
|
||||
- `POST /:id/pause`: 200 sets `paused_at` on a running session; 404 for a non-numeric or unknown
|
||||
id; 409 on a double pause (already paused) and 409 when the session is no longer active.
|
||||
- `POST /:id/resume`: 200 clears `paused_at` and accumulates `paused_seconds`; 404 for a
|
||||
non-numeric or unknown id; 409 when the session is running (not paused) and 409 when it is no
|
||||
longer active.
|
||||
- `POST /:id/stop`: 200 completes the session, folds an open pause span into `paused_seconds`, and
|
||||
computes `duration_seconds = wall-clock − paused_seconds` (never negative); a never-paused stop
|
||||
keeps `paused_seconds = 0` and `duration = wall-clock`; 404 for a non-numeric/unknown id; 409
|
||||
when already closed.
|
||||
- `POST /:id/discard`: 200 marks the session `discarded` with a null `duration_seconds`; 404 for a
|
||||
non-numeric/unknown id; 409 when already closed.
|
||||
- Ownership scoping: user B can neither stop nor discard user A's session — both return 404 and
|
||||
leave A's session untouched (still `active`).
|
||||
- Reads: `GET /api/sessions` returns the caller's sessions only, newest-first, joined to the
|
||||
activity `name`; `GET /api/sessions/active` returns only that user's `active` sessions.
|
||||
- `toWorkSession` maps every field to the API contract (incl. `paused_at`, `paused_seconds`,
|
||||
`notes`, `created_at`), threads `activity_name` / `user_name` / `user_email` opts through
|
||||
(undefined when omitted), maps a null `insoleType` / `durationSeconds` / `notes` to null, and
|
||||
coalesces a nullish `paused_seconds` to 0.
|
||||
- Lifecycle: start → pause → (backdate) resume accumulates paused time → (backdate) stop excludes
|
||||
paused time from worked duration → the completed session appears in history with its activity
|
||||
name → `GET /api/export` returns a CSV with exactly the header + one data row.
|
||||
|
||||
Reference in New Issue
Block a user