# Test — ProtectedRoute, RBAC & Auth Spinner

**Task**: AZ-467_test_protected_route_rbac
**Name**: ProtectedRoute spinner + timeout + RBAC route gating
**Description**: Implement the 7 blackbox tests that pin `<ProtectedRoute>`'s auth-loading spinner (a11y), the 10 s timeout fallback, and the client-side RBAC gating for `/admin` and `/settings` (defence in depth; server enforces too).
**Complexity**: 4 points
**Dependencies**: AZ-456_test_infrastructure
**Component**: 02_auth + 03_shared-ui (Blackbox Tests)
**Tracker**: AZ-467
**Epic**: AZ-455

## Problem

`<ProtectedRoute>` is the single client-side gate; getting it wrong leaks RBAC. The spinner + timeout fallback prevents indefinite waits if the bootstrap refresh hangs. RBAC tests run with three seed users (Operator, Admin, integrator-Dave-without-SETTINGS).

## Outcome

- 7 scenarios pass: 4 RBAC paths + 3 spinner/timeout paths.

## Scope

### Included

| Scenario | Profile | Source file |
|----------|---------|-------------|
| FT-P-32 — ProtectedRoute spinner a11y | fast | blackbox-tests.md |
| FT-P-33 — ProtectedRoute timeout fallback after 10 s | fast | blackbox-tests.md |
| FT-N-03 — authenticated non-admin → `/admin` redirects to `/flights` | fast + e2e | blackbox-tests.md |
| FT-N-05 — authenticated user without SETTINGS permission → `/settings` | fast + e2e | blackbox-tests.md |
| NFT-SEC-05 — `/admin` blocks non-admins client-side | fast | security-tests.md |
| NFT-SEC-06 — `/settings` route gate per RBAC | fast | security-tests.md |
| NFT-RES-04 — ProtectedRoute loading timeout fallback after 10 s | fast | resilience-tests.md |

### Excluded

- Unauthenticated `/admin` (FT-N-04 — covered in 02_test_auth_token_handling).
- Server-side enforcement (suite-level test, out of UI scope).

## Acceptance Criteria

**AC-1: Spinner a11y**
`role="status"` + `aria-live="polite"` + accessible label on the loading element.

**AC-2: Timeout fallback**
After 10 s without bootstrap-refresh resolution, fallback UI appears with a retry affordance.

**AC-3: RBAC redirects**
Operator → `/admin` redirects to `/flights`. integrator-Dave → `/settings` redirects per the policy. Operator + Admin → `/admin` reaches it normally.

**AC-4: Both fast + e2e**
RBAC tests run in both profiles. Fast asserts redirect via Router state; e2e asserts via `page.url()`.

## System Under Test Boundary

- System under test: `<ProtectedRoute>` + Router + `<AuthContext>`.
- Allowed stubs: MSW for `/api/admin/auth/me` returning the right RBAC payload per seed user; real `admin/` in e2e.
- Disallowed: stubbing `<ProtectedRoute>`, `<AuthContext>`, or Router.
- Expected observables per `results_report.md` rows for FT-P-32, 33, FT-N-03, 05, NFT-SEC-05, 06, NFT-RES-04.

## Constraints

- Use seed users `op_alice` (Operator), `admin_carol` (Admin), `integrator_dave` (no SETTINGS) per test-data.md.

## Risks & Mitigation

**Risk 1 — Timeout test flakiness**
- *Risk*: 10 s wait is long for a fast suite; CI variance may flake.
- *Mitigation*: use Vitest fake-timers to advance the clock instantaneously.
