mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 20:41:11 +00:00
38eb87fb08
Scaffolds the Blackbox test project per AZ-456 / environment.md across
the three profiles:
- fast : Vitest 3.x + jsdom + MSW 2.x + RTL/jest-dom; tests/setup.ts
boots the MSW Node server with onUnhandledRequest:'error',
afterEach resets handlers, clears bearer + navigate-to-login
spy. Default handlers ship for every suite service plus OWM
and tile stand-ins. Fixtures mirror seed_* in test-data.md.
- e2e : Playwright ^1.49 with chromium + firefox projects against the
suite docker-compose stack; owm-stub + tile-stub Bun servers,
playwright-runner image, seeds.sql for the test-db.
- static: scripts/run-tests.sh extended — tsc --noEmit (test config),
vite build, ripgrep checks (with grep -r fallback), CSV
report at test-output/static-report.csv per AC-7 columns.
Smoke tests cover AC-3, AC-4 (fast, 5 tests, PASS) and AC-1, AC-2,
AC-5, AC-8 (e2e, gated by Risk 4 docker availability). Static profile
(13 checks) PASS — STC-SEC1 (no literal OWM key) lifted from
QUARANTINE per AZ-447 with a narrowed pattern.
Files:
+24 tests/**, +10 e2e/**, +vitest.config.ts, +tsconfig.test.json
~package.json (test scripts + devDeps for vitest, @testing-library/*,
msw, @playwright/test, jsdom, @types/node, @vitest/coverage-v8)
~scripts/run-tests.sh, scripts/run-performance-tests.sh — switched
RESULTS_DIR to test-output/, compose path to project-local
~.gitignore — added /test-output/
Verification:
bun run test:fast → 11 / 11 PASS
./scripts/run-tests.sh → static 13/13 + fast 11/11 PASS, exit 0
Tracker: AZ-456 → In Testing.
Co-authored-by: Cursor <cursoragent@cursor.com>
174 lines
7.2 KiB
Bash
Executable File
174 lines
7.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Azaion UI — performance test runner.
|
|
#
|
|
# Generated by .cursor/skills/test-spec phase 4. Implements the NFT-PERF-* scenarios
|
|
# from _docs/02_document/tests/performance-tests.md. Thresholds are sourced from
|
|
# _docs/00_problem/input_data/expected_results/results_report.md (rows 11, 40, 98 + AC-11 + AC-23).
|
|
#
|
|
# Most NFT-PERF-* tests are observable browser timings, not server load tests. The
|
|
# script therefore runs Playwright-based measurements rather than k6/locust.
|
|
#
|
|
# Profile mapping (per environment.md → Test Execution):
|
|
# - NFT-PERF-01 (bundle ≤ 2 MB gzip) : static — checks dist/ on host
|
|
# - NFT-PERF-02..09 : fast or e2e — Playwright
|
|
# - NFT-PERF-10 (FCP ≤ 3 000 ms on /flights) : e2e — Playwright against the suite stack
|
|
#
|
|
# Usage:
|
|
# scripts/run-performance-tests.sh # run all NFT-PERF-* (skips quarantined)
|
|
# scripts/run-performance-tests.sh --static-only # only NFT-PERF-01 (bundle size)
|
|
# scripts/run-performance-tests.sh --e2e-only # only NFT-PERF-* that require the stack
|
|
# scripts/run-performance-tests.sh --bundle-max-bytes 2097152 # override bundle threshold
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
SUITE_ROOT="$(cd "$PROJECT_ROOT/.." && pwd)"
|
|
RESULTS_DIR="$PROJECT_ROOT/test-output"
|
|
|
|
RUN_STATIC=true
|
|
RUN_E2E=true
|
|
|
|
# Thresholds (defaults from results_report.md; overridable via flags).
|
|
BUNDLE_MAX_BYTES=$((2 * 1024 * 1024)) # AC-11 / NFT-PERF-01 (row 40): 2 MB gzipped initial JS
|
|
FCP_MAX_MS=3000 # NFT-PERF-10 (row 98): warm-cache FCP on /flights, edge profile
|
|
AUTH_REFRESH_MAX_MS=200 # NFT-PERF-02 (row 11): refresh round-trip target
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--static-only) RUN_STATIC=true; RUN_E2E=false ;;
|
|
--e2e-only) RUN_STATIC=false; RUN_E2E=true ;;
|
|
--bundle-max-bytes=*) BUNDLE_MAX_BYTES="${arg#*=}" ;;
|
|
--bundle-max-bytes) shift; BUNDLE_MAX_BYTES="${1:-$BUNDLE_MAX_BYTES}" ;;
|
|
--fcp-max-ms=*) FCP_MAX_MS="${arg#*=}" ;;
|
|
--fcp-max-ms) shift; FCP_MAX_MS="${1:-$FCP_MAX_MS}" ;;
|
|
--auth-refresh-max-ms=*) AUTH_REFRESH_MAX_MS="${arg#*=}" ;;
|
|
--auth-refresh-max-ms) shift; AUTH_REFRESH_MAX_MS="${1:-$AUTH_REFRESH_MAX_MS}" ;;
|
|
-h|--help)
|
|
sed -n '2,22p' "$0" | sed 's/^# \{0,1\}//'
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown argument: $arg" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
E2E_COMPOSE_STARTED_HERE=false
|
|
|
|
cleanup() {
|
|
if [ "$E2E_COMPOSE_STARTED_HERE" = "true" ]; then
|
|
docker compose -f "$PROJECT_ROOT/e2e/docker-compose.suite-e2e.yml" down -v --remove-orphans || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p "$RESULTS_DIR"
|
|
|
|
cd "$PROJECT_ROOT"
|
|
|
|
echo "[run-performance-tests] thresholds:"
|
|
echo " bundle (NFT-PERF-01) : ≤ $BUNDLE_MAX_BYTES bytes gzipped"
|
|
echo " FCP (NFT-PERF-10) : ≤ $FCP_MAX_MS ms"
|
|
echo " auth refresh (NFT-PERF-02): ≤ $AUTH_REFRESH_MAX_MS ms"
|
|
echo " static : $RUN_STATIC"
|
|
echo " e2e : $RUN_E2E"
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Install deps (matches run-tests.sh).
|
|
# ----------------------------------------------------------------------------
|
|
if ! command -v bun >/dev/null 2>&1; then
|
|
echo "[run-performance-tests] FATAL: bun is required (project pins bun@1.3.11)." >&2
|
|
exit 1
|
|
fi
|
|
echo "[run-performance-tests] installing dependencies..."
|
|
if [ -f "$PROJECT_ROOT/bun.lock" ] || [ -f "$PROJECT_ROOT/bun.lockb" ]; then
|
|
bun install --frozen-lockfile
|
|
else
|
|
bun install
|
|
fi
|
|
|
|
OVERALL_EXIT=0
|
|
SUMMARY_FILE="$RESULTS_DIR/performance-summary.txt"
|
|
: > "$SUMMARY_FILE"
|
|
|
|
record() {
|
|
# $1 = scenario id, $2 = result (PASS|FAIL|SKIP|QUARANTINE), $3 = measured, $4 = threshold
|
|
printf '%-14s %-12s measured=%-14s threshold=%s\n' "$1" "$2" "$3" "$4" | tee -a "$SUMMARY_FILE"
|
|
}
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# Static perf scenarios.
|
|
# ----------------------------------------------------------------------------
|
|
if [ "$RUN_STATIC" = "true" ]; then
|
|
echo "[run-performance-tests] === NFT-PERF-01 (bundle size) ==="
|
|
if [ ! -d "$PROJECT_ROOT/dist" ]; then
|
|
echo "[NFT-PERF-01] dist/ not present — running 'bun run build'..."
|
|
bun run build
|
|
fi
|
|
|
|
# Sum gzipped sizes of dist/assets/*.js (the initial JS bundle is index-*.js per Vite).
|
|
BUNDLE_BYTES=$(
|
|
find "$PROJECT_ROOT/dist/assets" -maxdepth 1 -name '*.js' -print0 2>/dev/null \
|
|
| xargs -0 -I{} sh -c 'gzip -c "{}" | wc -c' \
|
|
| awk '{ s += $1 } END { print (s ? s : 0) }'
|
|
)
|
|
echo "[NFT-PERF-01] gzipped dist/assets/*.js = $BUNDLE_BYTES bytes"
|
|
if [ "$BUNDLE_BYTES" -le "$BUNDLE_MAX_BYTES" ]; then
|
|
record "NFT-PERF-01" "PASS" "${BUNDLE_BYTES}B" "≤ ${BUNDLE_MAX_BYTES}B"
|
|
else
|
|
record "NFT-PERF-01" "FAIL" "${BUNDLE_BYTES}B" "≤ ${BUNDLE_MAX_BYTES}B"
|
|
OVERALL_EXIT=1
|
|
fi
|
|
fi
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# E2E perf scenarios (Playwright-based).
|
|
# The Playwright project lands at autodev Step 5 (Decompose Tests). Until it
|
|
# ships, NFT-PERF-02..10 are SKIPPED (not FAILED) so this script can run on
|
|
# the spec-only baseline without producing false negatives.
|
|
# ----------------------------------------------------------------------------
|
|
if [ "$RUN_E2E" = "true" ]; then
|
|
COMPOSE_FILE="$PROJECT_ROOT/e2e/docker-compose.suite-e2e.yml"
|
|
PERF_PROJECT="$PROJECT_ROOT/e2e/playwright.perf.config.ts"
|
|
|
|
if [ ! -f "$PERF_PROJECT" ]; then
|
|
echo "[run-performance-tests] Playwright perf project ($PERF_PROJECT) not yet wired."
|
|
echo "[run-performance-tests] Awaiting NFT-PERF-* task implementations (AZ-457..AZ-482); until then the e2e perf scenarios are SKIPPED."
|
|
for id in NFT-PERF-02 NFT-PERF-03 NFT-PERF-04 NFT-PERF-05 NFT-PERF-06 NFT-PERF-07 NFT-PERF-08 NFT-PERF-09 NFT-PERF-10; do
|
|
record "$id" "SKIP" "n/a" "deferred to per-AC test tasks"
|
|
done
|
|
elif [ ! -f "$COMPOSE_FILE" ]; then
|
|
echo "[run-performance-tests] FATAL: $COMPOSE_FILE not found." >&2
|
|
OVERALL_EXIT=1
|
|
elif ! command -v docker >/dev/null 2>&1; then
|
|
echo "[run-performance-tests] FATAL: docker is required for the e2e perf profile." >&2
|
|
OVERALL_EXIT=1
|
|
else
|
|
echo "[run-performance-tests] starting compose stack..."
|
|
docker compose -f "$COMPOSE_FILE" up -d --build
|
|
E2E_COMPOSE_STARTED_HERE=true
|
|
|
|
echo "[run-performance-tests] running Playwright perf project..."
|
|
if FCP_MAX_MS="$FCP_MAX_MS" AUTH_REFRESH_MAX_MS="$AUTH_REFRESH_MAX_MS" \
|
|
bunx playwright test --config "$PERF_PROJECT" 2>&1 | tee "$RESULTS_DIR/perf-playwright.txt"; then
|
|
echo "[run-performance-tests] Playwright perf PASSED"
|
|
else
|
|
echo "[run-performance-tests] Playwright perf FAILED — see $RESULTS_DIR/perf-playwright.txt"
|
|
OVERALL_EXIT=1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Quarantined scenarios (documentary only — never gate today).
|
|
record "NFT-PERF-03" "QUARANTINE" "—" "Step 8 hardening (SSE refresh rotation)"
|
|
record "NFT-PERF-08" "QUARANTINE" "—" "Step 4 fix (panel-width persistence)"
|
|
record "NFT-PERF-09" "QUARANTINE" "—" "Step 4 fix (settings save error surfacing)"
|
|
|
|
echo ""
|
|
echo "[run-performance-tests] summary written to $SUMMARY_FILE"
|
|
echo "[run-performance-tests] exit code: $OVERALL_EXIT"
|
|
|
|
exit "$OVERALL_EXIT"
|