#!/usr/bin/env bash # Frontend clean install + static gates + mocked Playwright (spec §14, Phase 1). # # Gates: npm ci (HUSKY=0) -> lint, unit tests, production build (tsc -b inside), # mocked Playwright e2e. lint/test are independent of build; e2e needs build # tooling installed but drives its own dev server (playwright.config webServer). # # The repo's `verify`/governance script is deliberately NOT run here: it fails # closed without full git history, and the PR's own CI already runs it — that # result is ingested into evidence via resolve-pr-head.sh. # # Reads: FRONTEND_DIR (default $WORKSPACE_DIR/frontend), # RUN_MOCKED_E2E (default true) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=lib.sh source "$SCRIPT_DIR/lib.sh" FRONTEND_DIR="${FRONTEND_DIR:-$WORKSPACE_DIR/frontend}" RUN_MOCKED_E2E="${RUN_MOCKED_E2E:-true}" cd "$FRONTEND_DIR" [ -f package.json ] || die "package.json not found in $FRONTEND_DIR" export HUSKY=0 overall=0 if ! run_gate frontend.install frontend-install.log npm ci; then record_gate frontend.lint BLOCKED "install failed" record_gate frontend.unit_tests BLOCKED "install failed" record_gate frontend.build BLOCKED "install failed" record_gate frontend.e2e_mocked BLOCKED "install failed" exit 1 fi run_gate frontend.lint frontend-lint.log npm run lint || overall=1 run_gate frontend.unit_tests frontend-unit.log npm test || overall=1 # Production build includes TypeScript compilation (tsc -b). VITE_API_URL must # end in /api or the build's contract guard throws by design; use the relative # default so the committed .env.production absolute URL is not baked in. if run_gate frontend.build frontend-build.log env VITE_API_URL="/api" npm run build; then build_ok=1 else build_ok=0 overall=1 fi if [ "$RUN_MOCKED_E2E" != "true" ]; then record_gate frontend.e2e_mocked NOT_RUN "disabled by run_mocked_e2e input" elif ! jq -e '.scripts["test:e2e"]' package.json >/dev/null 2>&1; then record_gate frontend.e2e_mocked NOT_RUN "no test:e2e script at this head" elif [ "$build_ok" -ne 1 ]; then record_gate frontend.e2e_mocked BLOCKED "production build failed" overall=1 else if run_gate frontend.e2e_browsers frontend-e2e-install.log \ npx playwright install --with-deps chromium; then # Mocked suite: Playwright's webServer starts the dev server itself; all # backend calls in the suite are page.route-fulfilled. This is NOT live # integration coverage and evidence records it as mocked only. run_gate frontend.e2e_mocked frontend-e2e.log npm run test:e2e || overall=1 else record_gate frontend.e2e_mocked BLOCKED "playwright browser install failed" overall=1 fi fi exit "$overall"