Files
ui/_docs/02_tasks/done/AZ-458_test_sse_lifecycle.md
T
Oleksandr Bezdieniezhnykh 2051088706 [AZ-458] [AZ-467] [AZ-468] [AZ-482] Batch 3 - SSE/RBAC/Header/security tests
Implements 4 blackbox-test tasks for AZ-455 Phase A baseline:

- AZ-458 SSE lifecycle + bearer rotation: 9 fast tests (8 pass, 1
  QUARANTINE for annotation-status); 4 e2e scenarios (gated by suite
  stack). Uses tests/helpers/sse-mock.ts with globalThis.EventSource
  monkey-patch per AC-3 (no stub of src/api/sse.ts). AC-2 bearer
  rotation captured as documented drift via it.fails() — FlightsPage
  useEffect deps do not include the token today.

- AZ-467 ProtectedRoute spinner + timeout + RBAC: 9 new fast tests
  extending the AZ-457 file (6 pass, 3 QUARANTINE), plus 3 e2e
  scenarios. FT-P-32 spinner a11y is it.fails() drift; FT-P-33 timeout
  and FT-N-03/05 RBAC redirects are it.skip QUARANTINE (no production
  behavior today). Positive control: admin_carol reaches /admin.

- AZ-468 Header flight-dropdown a11y: 6 fast tests (5 pass, 1
  QUARANTINE). FT-P-30/31 are it.fails() drift (aria-expanded /
  role=listbox / aria-activedescendant currently missing); FT-N-09
  is it.skip QUARANTINE (no document keydown handler exists).

- AZ-482 Secrets + banned-libs + AC-N1 anti-criterion: 3 new static
  checks (STC-SEC13 legacy integrations, STC-SEC14 concurrent-edit,
  STC-SEC1B dist/ OWM key) plus refactor of 4 existing checks
  (STC-N2/N4/S13/S6) to read from tests/security/banned-deps.json
  via scripts/check-banned-deps.mjs per AZ-482 constraint
  ("deny-list lives in tests/security/banned-deps.json so additions
  are visible in code review"). All 22 static checks PASS.

Totals: 57 fast tests pass + 9 skipped; 22/22 static checks pass.
Self-review verdict PASS_WITH_WARNINGS — all five findings are
documented drifts captured by it.fails() / it.skip QUARANTINE +
control tests. See _docs/03_implementation/batch_03_report.md
for the per-task / per-AC matrix and recommended Phase B follow-up
production tasks (Header a11y; ProtectedRoute spinner/timeout/RBAC;
SSE bearer-rotation reconnect; AnnotationsPage SSE).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 03:46:18 +03:00

4.7 KiB

Test — SSE Lifecycle & Bearer Rotation

Task: AZ-458_test_sse_lifecycle Name: SSE lifecycle + bearer-rotation reconnect Description: Implement every blackbox test that exercises the SPA's SSE streams — live-GPS, annotation-status — covering open/close lifecycle and the bearer-rotation reconnect (≤5 s) after a token refresh. Complexity: 5 points Dependencies: AZ-456_test_infrastructure Component: 01_api-transport + 05_flights + 06_annotations (Blackbox Tests) Tracker: AZ-458 Epic: AZ-455

Problem

The SPA holds two long-running EventSource connections — live-GPS (per <FlightsPage>) and annotation-status (per <AnnotationsPage>) — using the in-query-string bearer pattern (ADR-008). The open/close timing and the reconnect-on-refresh path must be deterministic; otherwise tests downstream see flapping streams and undefined ordering.

Outcome

  • 9 test scenarios pass, asserting open/close timing and bearer-rotation reconnect behavior.
  • Fast tests use tests/helpers/sse-mock.ts (per AZ-456 Risk 3); e2e tests use the embedded LiveGPS + annotation-status generators in the suite test images.
  • No test reads or manipulates src/api/sse.ts internals.

Scope

Included

Scenario Profile Source file results_report row
FT-P-09 — annotation-status SSE opens on <AnnotationsPage> mount fast + e2e blackbox-tests.md per FT-P-09
FT-P-10 — annotation-status SSE closes on unmount fast blackbox-tests.md per FT-P-10
FT-P-18 — live-GPS SSE opens within 5 s of flight select fast + e2e blackbox-tests.md per FT-P-18
FT-P-19 — live-GPS SSE closes within 1 s of deselect fast blackbox-tests.md per FT-P-19
NFT-PERF-03 — SSE bearer-rotation reconnect ≤ 5 s e2e performance-tests.md per NFT-PERF-03
NFT-PERF-04 — live-GPS SSE opens within 5 s of flight select fast performance-tests.md per NFT-PERF-04
NFT-PERF-05 — live-GPS SSE closes within 1 s of deselect fast performance-tests.md per NFT-PERF-05
NFT-PERF-06 — annotation-status SSE unsubscribes within 1 s on page unmount fast performance-tests.md per NFT-PERF-06
NFT-RES-02 — SSE bearer rotation — both streams reconnect within 5 s e2e resilience-tests.md per NFT-RES-02

Excluded

  • SSE server-disconnect indicator (covered in 23_test_network_resilience).
  • The 401-retry path on fetch (covered in 02_test_auth_token_handling).
  • The async-video detect SSE (covered in 06_test_detection_endpoints — quarantined as Phase B target).

Acceptance Criteria

AC-1: Open/close timing Given a freshly-mounted <FlightsPage> or <AnnotationsPage>, When the relevant SSE should open or close per the scenario, Then the event happens within the timing budget and the observable EventSource state matches (readyState: 1 for open, closed connection for close).

AC-2: Bearer rotation Given an active SSE stream and an upcoming token refresh, When the bearer rotates, Then both live-GPS and annotation-status streams reconnect with the new bearer within 5 s; no event from before the rotation is replayed AFTER the new bearer is in use.

AC-3: No internal stubs The fast profile uses the published sse-mock.ts helper to simulate the wire-level SSE event stream. Tests MUST NOT replace src/api/sse.ts with a stub; if the SSE module misbehaves, the test FAILS.

System Under Test Boundary

  • System under test: src/api/sse.ts + the consumer hooks in <FlightsPage> / <AnnotationsPage> + the React tree.
  • Allowed stubs: the suite-side SSE endpoints — stubbed via the MSW SSE adapter / sse-mock.ts in fast, real flights/ and annotations/ services in e2e.
  • Disallowed: stubbing src/api/sse.ts, the SPA's SSE hooks, or the React tree.
  • Expected observables per results_report.md rows for FT-P-09, 10, 18, 19, NFT-PERF-03..06, NFT-RES-02.

Constraints

  • E2E tests rely on the embedded LiveGPS simulator and annotation-status event generator in the suite's test-mode images (per test-data.md).
  • Bearer in SSE URL ?token= per ADR-008 — tests assert the URL pattern, not stripped headers.
  • Bearer-rotation tests MUST drive the rotation through <AuthContext>'s normal refresh path, not by directly calling setToken.

Risks & Mitigation

Risk 1 — MSW SSE polyfill brittleness (AZ-456 Risk 3)

  • Risk: MSW 2.x does not have first-class SSE support. The sse-mock.ts helper introduces a small abstraction that, if buggy, makes tests pass that shouldn't.
  • Mitigation: every fast SSE scenario also has an e2e companion that exercises the real wire. If the two disagree, the e2e wins and the fast test is QUARANTINEd until the helper is fixed.