test(worker): Auth (context/storage/login) — fill gaps + lifecycle test
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).
This commit is contained in:
@@ -255,3 +255,31 @@ Guaranteed behaviors:
|
||||
and the bearer authorizes `/api/me` → admin deactivates → the session rows are deleted so the
|
||||
pre-issued token no longer authorizes `/api/me` (401) **and** a fresh sign-in is blocked → admin
|
||||
reactivates → the ban is cleared and sign-in works again.
|
||||
|
||||
## Auth (context/storage/login) — worker client
|
||||
|
||||
Src covered (worker `apps/worker`): `src/auth/AuthContext.tsx`, `src/lib/auth-storage.ts`, and
|
||||
`src/screens/Login.tsx` — all at 100% stmts/branch/funcs/lines. No `c8 ignore`s needed.
|
||||
|
||||
Guaranteed behaviors:
|
||||
|
||||
- `auth-storage`: `setToken` persists the bearer, `getToken` reads it back, `clearToken` removes it
|
||||
(`getToken` returns `null` when nothing is stored) — all via `localStorage`.
|
||||
- `AuthContext` starts **unauthenticated** when no token is stored and **restores** the
|
||||
authenticated state on mount when a token is already present (`getToken() !== null`).
|
||||
- `AuthContext.signIn` delegates to the api `signIn(email, password)` and, on success, flips the
|
||||
context to authenticated (`isAuthed` → true).
|
||||
- `AuthContext.signOut` resets the router path to `/` (so the next authed mount lands on Stopwatch,
|
||||
not Account), clears the stored token, and flips the context to unauthenticated.
|
||||
- `useAuth` throws `"useAuth must be used within an AuthProvider"` when called outside the provider.
|
||||
- `Login` renders the Dutch form (E-mailadres / Wachtwoord / Inloggen) and submits the typed
|
||||
credentials to `POST /api/auth/sign-in/email`, storing the returned bearer token.
|
||||
- `Login` shows the `"Inloggen mislukt"` error (and stores no token) when sign-in fails, and
|
||||
disables the submit button while the request is pending, re-enabling it once it settles.
|
||||
- Lifecycle (`src/screens/Login.test.tsx`): from the unauthenticated app, a successful login stores
|
||||
the token and flips the context so the tabbed authenticated shell (Stopwatch + TabBar) renders.
|
||||
|
||||
> Note: the design checklist mentions "clears on 401" for the worker auth context — this is **not
|
||||
> implemented** in the current code (there is no global 401 interceptor; `apiFetch` throws
|
||||
> `ApiError` and callers surface it via React Query). Left as-is (missing feature, not a defect);
|
||||
> not tested and not filed as a bug.
|
||||
|
||||
Reference in New Issue
Block a user