Drove Live.tsx from 93.24% to 100% (stmts/branch/funcs/lines); elapsed.ts already 100%. Added tests for the error state, non-array payload fallback, placeholder labels (missing name/activity/type), the busy/disabled action buttons, the loading state, and a combined running+paused lifecycle test. No production behavior changed; no bugs found.
Drive the worker Auth domain to 100% coverage:
- AuthContext.tsx: 91.3/80 -> 100/100 (signIn body, mount-restore branches, useAuth guard)
- Login.tsx: 78/50 -> 100/100 (handleSubmit success/error/pending, submit disable)
- auth-storage.ts: already 100 (no change)
New Login.test.tsx adds the domain lifecycle test: from the unauthenticated app,
a successful login stores the token and flips the context to the authenticated
tabbed shell. Extended AuthContext.test.tsx covers signIn delegation, mount
restore (token present/absent), and the out-of-provider throw.
No bugs found; code was already correct. Note: the design checklist's
'clears on 401' worker behavior is not implemented (no global 401 interceptor)
and is left as-is (missing feature, not a defect).
Fill the remaining coverage gaps in src/routes/admin-users.ts and add the
domain lifecycle test, bringing the file to 100% stmts/branch/funcs/lines.
New tests (apps/api/test/admin-users.test.ts):
- password route: 404 unknown id; 400 when better-auth setUserPassword throws
(driven via a spy so the catch path is deterministic).
- toListItem: a null DB role lists as 'worker' (nullish-coalescing fallback).
- role route: 400 on an invalid role body; 404 on an unknown id.
- reactivate route: 404 on an unknown id.
Lifecycle (apps/api/test/integration/user-lifecycle.test.ts): admin creates a
worker -> worker signs in and the bearer authorizes /api/me -> admin deactivates
(session rows deleted, so the pre-issued token 401s and fresh sign-in is blocked)
-> admin reactivates -> sign-in works again.
The two last-admin guards (role + deactivate routes) are unreachable over HTTP
(the self-demote / self-deactivate guards above already handle caller===target,
so any caller reaching them is a distinct active admin and
activeAdminsExcluding(target) >= 1). Annotated with /* c8 ignore */ + reasons
rather than left as silent gaps; the guard logic is unit-tested via
activeAdminsExcluding.
No production behavior changed; no bugs found.
Drives the report/export parts of src/routes/admin.ts to 100%
stmts/branch/funcs/lines. Adds one lifecycle test plus gap tests for the
previously-uncovered branches; no production behavior changed.
Tests added (apps/api/test):
- report.test.ts: invalid insole_type / non-numeric activity_id → 400;
activity filter narrows; null insole_type bucketed "Onbekend"; null
duration counts as 0 worked; export 400 on missing/inverted range.
Migrated the report + export describes to resetDb(beforeEach) so exact
totals are order-independent (removed the activity_id isolation
workaround in the all-users export test).
- integration/report-aggregation.test.ts: lifecycle — 2 workers × 2
activities × 2 types → exact totals + every by_worker/by_activity/
by_type row (values and worked-desc order) → user_id filter narrows.
Defensive annotations in admin.ts report loop (behavior unchanged):
- pausedSeconds/pairCount ?? 0 — NOT NULL columns, DB-impossible nulls.
- user_name/activity_name ?? 'Onbekend' — unreachable; userId FK cascades
on delete and activityId FK is enforced (libsql enforces FKs), so every
session always joins to a real user and activity.
No bugs found; the code was already correct.
Fills the session-part coverage gaps in src/routes/admin.ts (cross-user list,
active list, manual create/edit, admin stop/discard) and adds the admin↔worker
lifecycle test.
New route-level tests (apps/api/test/admin.test.ts):
- manual create: 400 on schema-invalid body; 400 when paused_seconds > span.
- edit: 404 non-numeric id; 400 schema-invalid body; 400 unparseable start_time;
400 paused_seconds > span; 404 unknown activity.
- stop: 404 non-numeric/unknown id; folds an open pause into paused_seconds.
- discard: 404 non-numeric/unknown id; 409 when already closed.
Lifecycle (apps/api/test/integration/admin-worker-session.test.ts): worker
starts → admin stops via the admin endpoint → session lands in /api/admin/report
and /api/admin/export with matching totals (uses resetDb for exact counts).
admin.ts session parts now at 100% stmts/lines; every session-part branch
covered. The one remaining session-part branch (row.pausedSeconds ?? 0 in the
stop route) is c8-ignored — paused_seconds is NOT NULL DEFAULT 0, so the null
branch is DB-impossible. The remaining uncovered branches in admin.ts are the
report/export parts, owned by the Reports domain (B-A6).
No behavior-changing bugs found; all session-part code was already correct.
Drove src/lib/csv.ts to 100% stmts/branch/funcs/lines (was 97.95%/55.55%):
- added a null-fallback row test covering every ?? default (activityName,
userName, insoleType→Kurk, pairCount→2, duration/paused→0) and the null
end-time branch (line 65).
- added CSV-escaping edge tests: commas, embedded quotes, and newlines inside
a field stay inside the quoted cell.
- added formatDuration edge (hours >99 → 100:00:00).
- added a /api/export ordering-by-start-time behavior test and adopted
resetDb per-test isolation in the export suite.
No bugs found; CSV code behaves correctly. sessions.ts /api/export route
already at 100%. Full api suite green (150 tests).
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).
Drives all infra src files to 100% (env.ts, db/client.ts, db/ensure-dir.ts,
db/migrate.ts, db/seed.ts, routes/health.ts).
- env.test.ts: dev defaults when unset, overrides when set (PORT coerced),
CORS_ORIGINS parsing (trim + drop empties) and empty-fallback.
- db.test.ts: runMigrations idempotency; ensureDbDir no-op for non-file URLs
and bare filenames (branch coverage).
- seed.test.ts: production guard — no dev users seeded when NODE_ENV=production.
- c8-ignore the migrate.ts/seed.ts CLI direct-run blocks (unreachable under vitest).
No lifecycle test (infra domain, per plan). No bugs found — infra code correct;
only coverage gaps. All 112 API tests green; typecheck + oxlint clean.