test(admin): Auth (admin-only gate) — fill gaps + lifecycle test

This commit is contained in:
Bas van Rossem
2026-07-23 14:25:04 +02:00
parent e174c29a77
commit 64911a0052
3 changed files with 226 additions and 0 deletions

View File

@@ -355,3 +355,28 @@ Guaranteed behaviors:
`['sessions']` query cache on success.
- Lifecycle (`src/App.test.tsx`): unauthenticated renders `Login` with no navigation; authenticated
renders the Stopwatch screen under the tab bar and no login form.
## Auth (admin-only gate) — admin client
Src covered (admin `apps/admin`): `src/auth/AuthContext.tsx` and `src/screens/Login.tsx` — both at
100% stmts/branch/funcs/lines. No `c8 ignore`s needed.
Guaranteed behaviors:
- `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)`, then fetches `/api/me`:
**admin-only gate** — an `admin` role flips the context to authenticated; a non-admin role clears the
stored token and throws `NotAdminError` (`"not-admin"`), leaving the context unauthenticated.
- `AuthContext.signOut` resets the router path to `/` (so the next authed mount lands on Live, not
whatever tab the admin logged out from), clears the stored token, and flips 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 `signIn`.
- `Login` distinguishes the two failure modes: a `NotAdminError` surfaces
`"Geen toegang — alleen beheerders."` while any other failure surfaces `"Inloggen mislukt"`; a stale
error is cleared on the next submit.
- `Login` disables the submit button while the sign-in is pending, re-enabling it once it settles.
- Lifecycle (`src/screens/Login.test.tsx`): from the unauthenticated app, worker credentials are
rejected with the `"Geen toegang — alleen beheerders."` message and the shell never renders; admin
credentials then flip the gate so the authed shell (Sidebar nav) renders.