Captures the full output of autodev existing-code Phase A through Step 4 (Code Testability Revision) for the Azaion UI workspace: - Step 1 Document: _docs/02_document/ (FINAL_report, architecture, glossary, components/, modules/, diagrams/, system-flows, module-layout) plus _docs/00_problem/ + _docs/01_solution/ + _docs/legacy/ + _docs/how_to_test + README. - Step 2 Architecture Baseline: architecture_compliance_baseline.md. - Step 3 Test Spec: _docs/02_document/tests/ (environment, test-data, blackbox/performance/resilience/security/ resource-limit tests, traceability-matrix), enum_spec_snapshot, expected_results/results_report.md (98 rows), plus the run-tests.sh + run-performance-tests.sh runners. - Step 4 Code Testability Revision: 01-testability-refactoring/ run dir (list-of-changes C01-C07, deferred_to_refactor, analysis/research_findings + refactoring_roadmap) and the 7 child task specs AZ-448..AZ-454 under _docs/02_tasks/todo/ plus _dependencies_table.md. - _docs/_autodev_state.md pins the cursor at Step 4 / refactor Phase 4 entry so /autodev resumes cleanly. Epic AZ-447 (UI testability gates) tracks the 7 child tasks that will land in subsequent commits. Co-authored-by: Cursor <cursoragent@cursor.com>
8.0 KiB
Performance Tests
The Azaion UI is a thin SPA; the dominant performance concerns are bundle size, auth-refresh transparency, SSE responsiveness, and UI reflection of server-confirmed state changes. Server-side throughput is OUT of scope here — this file covers the UI's observable timing only.
NFT-PERF-01: Initial JS bundle ≤ 2 MB gzipped
Summary: The sum of gzipped initial-route JS chunks in dist/ stays within the architecture's stated budget.
Traces to: AC-11, O13
Metric: gzipped byte total of initial JS entries.
Profile: static
Preconditions:
bun run buildhas produceddist/.
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Run vite build (or read the build manifest if already built) |
dist/ produced |
| 2 | Walk Vite's manifest.json to enumerate entry chunks (non-async) |
list of initial chunks |
| 3 | Gzip-size each chunk (Node zlib.gzipSync(content, {level:9}) or equivalent) |
per-chunk size |
| 4 | Sum sizes | total bytes |
Pass criteria: total ≤ 2 097 152 bytes (2 MB). Documentary today — no CI gate (AC-11 status: "target, not currently enforced"). Test exists so the gate flips to blocking the day CI wires it up.
Duration: ≤ 60 s.
Expected result source: results_report.md row 40.
NFT-PERF-02: Auth refresh — exactly one network round trip per cycle
Summary: A single 401-triggered refresh round consists of exactly one POST /api/admin/auth/refresh plus one retry of the original request.
Traces to: AC-01, AC-23
Metric: count of /api/admin/auth/refresh requests per refresh event.
Profile: fast
Preconditions:
- Authenticated session.
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Issue an authenticated request that returns 401 once, then 200 on retry | network log captured |
| 2 | Count refresh requests fired in the cycle | exactly 1 |
Pass criteria: refresh count == 1 per cycle (results_report.md row 12 — exact).
Duration: ≤ 5 s.
Expected result source: results_report.md row 12.
NFT-PERF-03: SSE bearer-rotation reconnect ≤ 5 s
Summary: When the bearer rotates while N SSE streams are open, all streams close and reopen with the new token within 5 s.
Traces to: AC-24
Metric: per-EventSource time from close() observed to next OPEN readyState (after reconnect with new token).
Profile: fast — quarantined until SSE refresh-reconnect is implemented (Step 8 hardening)
Preconditions:
- Two EventSources open (live-GPS + annotation-status).
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Trigger a refresh that rotates the bearer | new bearer in memory |
| 2 | For each EventSource: time from old close to new OPEN |
dt_i (ms) |
| 3 | Inspect new URLs for new token in query string | new ?token= value |
Pass criteria: max(dt_i) ≤ 5 000 ms; both streams close+open exactly once (results_report.md row 13).
Duration: ≤ 30 s.
Expected result source: results_report.md row 13.
NFT-PERF-04: Live-GPS SSE opens within 5 s of flight select
Summary: After clicking a flight in the Header, the live-GPS EventSource reaches OPEN quickly.
Traces to: AC-08
Metric: time from select-flight click to EventSource readyState === 1 (OPEN).
Profile: e2e (suite live-gps simulator emits events at 1 Hz)
Preconditions:
- Authenticated; flight selectable.
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Click a flight | one EventSource constructed to `^/api/flights/[0-9]+/live-gps(? |
| 2 | Wait for OPEN |
dt (ms) |
Pass criteria: dt ≤ 5 000 ms (results_report.md row 34).
Duration: ≤ 10 s.
Expected result source: results_report.md row 34.
NFT-PERF-05: Live-GPS SSE closes within 1 s of deselect
Summary: Deselecting the flight tears down the live-GPS stream promptly.
Traces to: AC-08
Metric: time from deselect to CLOSED.
Profile: e2e
Preconditions:
- Continuation of NFT-PERF-04.
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Deselect the flight | EventSource closes |
| 2 | Wait for CLOSED |
dt (ms) |
Pass criteria: dt ≤ 1 000 ms and no remaining open live-GPS sources (results_report.md row 35).
Duration: ≤ 5 s.
Expected result source: results_report.md row 35.
NFT-PERF-06: Annotation-status SSE unsubscribes within 1 s on page unmount
Summary: Navigating away from /annotations closes the status-events SSE within 1 s.
Traces to: AC-09
Metric: time from unmount to CLOSED.
Profile: fast
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Mount /annotations then unmount |
EventSource transitions |
| 2 | Measure dt | ms |
Pass criteria: dt ≤ 1 000 ms (results_report.md row 25).
Duration: ≤ 5 s.
Expected result source: results_report.md row 25.
NFT-PERF-07: Bulk-validate UI reflects new status within 2 s
Summary: After a successful bulk-validate, every selected row shows Validated quickly.
Traces to: AC-07
Metric: time from server 200 to last DOM row update.
Profile: fast
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Select N items, click Validate | request issued |
| 2 | Stub responds 200 | UI updates begin |
| 3 | Wait for all N rows to show Validated |
dt (ms) |
Pass criteria: dt ≤ 2 000 ms (results_report.md row 37).
Duration: ≤ 5 s.
Expected result source: results_report.md row 37.
NFT-PERF-08: Panel-width persistence debounce ≤ 1 s after resize-end
Summary: A drag-end on a resizable panel triggers a single PUT within 1 s (debounced).
Traces to: AC-21
Metric: time from mouseup (drag-end) to outbound PUT; PUT count per drag.
Profile: fast — quarantined until Step 4 writer is added
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Drag and release a divider | event captured |
| 2 | Wait for PUT or 1 s timeout | dt (ms); count |
Pass criteria: exactly 1 PUT within ≤ 1 000 ms; URL = /api/annotations/settings/user; body contains panelWidths (results_report.md row 64).
Duration: ≤ 5 s.
Expected result source: results_report.md row 64.
NFT-PERF-09: Settings save error surfaces within 2 s
Summary: A 500 on settings save produces an error toast and resets the saving flag within 2 s.
Traces to: AC-27
Metric: time from server 500 to error visibility + state reset.
Profile: fast — quarantined until Step 4 try/finally fix
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Trigger save, stub responds 500 after T ms | failure delivered |
| 2 | Wait for error toast and saving === false |
dt (ms) |
Pass criteria: dt ≤ 2 000 ms (results_report.md row 68).
Duration: ≤ 5 s.
Expected result source: results_report.md row 68.
NFT-PERF-10: First Contentful Paint on /flights ≤ 3 s on mid-range edge hardware
Summary: A warm-cache load of the default authenticated route renders the main pane within 3 s.
Traces to: AC-11 (target), H2 (edge deploys)
Metric: performance.getEntriesByName('first-contentful-paint')[0].startTime.
Profile: e2e — documentary (no enforcement today; no AC binds a hard FCP budget)
Preconditions:
- Warm browser cache (second visit).
- Edge-profile container: 2 vCPU, 4 GB RAM (the hardware-assessment phase confirms the figure).
Steps:
| Step | Consumer Action | Measurement |
|---|---|---|
| 1 | Navigate to /flights post-login |
navigation completes |
| 2 | Read FCP entry | ms |
Pass criteria: FCP ≤ 3 000 ms (row 98 — threshold_max).
Duration: ≤ 30 s.
Expected result source: results_report.md row 98.