|
| 1 | +#!/bin/bash |
| 2 | +# Lighthouse audit sweep for web.codebar. |
| 3 | +# |
| 4 | +# Builds production assets, serves them (bypassing the Vite dev server, whose |
| 5 | +# JS-injected CSS causes false-positive layout-shift scores), runs Lighthouse |
| 6 | +# (desktop preset) against every page in pages.json, then restores dev mode. |
| 7 | +# |
| 8 | +# Usage: |
| 9 | +# tests/lighthouse/run.sh # all pages in pages.json |
| 10 | +# tests/lighthouse/run.sh home ai_index # only the named pages |
| 11 | +# |
| 12 | +# Env vars: |
| 13 | +# BASE_URL default https://web.codebar.test |
| 14 | +# |
| 15 | +# Output: tests/lighthouse/reports/<timestamp>/<name>.json + summary.md |
| 16 | + |
| 17 | +set -uo pipefail |
| 18 | + |
| 19 | +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 20 | +REPO_ROOT="$(cd "$DIR/../.." && pwd)" |
| 21 | +BASE_URL="${BASE_URL:-https://web.codebar.test}" |
| 22 | +RUN_LABEL="$(date +%Y%m%d-%H%M%S 2>/dev/null || echo run)" |
| 23 | +OUT_DIR="$DIR/reports/$RUN_LABEL" |
| 24 | +PAGES_JSON="$DIR/pages.json" |
| 25 | + |
| 26 | +mkdir -p "$OUT_DIR" |
| 27 | + |
| 28 | +cd "$REPO_ROOT" |
| 29 | + |
| 30 | +echo "==> Building production assets" |
| 31 | +npm run build |
| 32 | + |
| 33 | +HOT_MOVED=0 |
| 34 | +if [ -f public/hot ]; then |
| 35 | + mv public/hot public/hot.disabled-for-lighthouse |
| 36 | + HOT_MOVED=1 |
| 37 | +fi |
| 38 | + |
| 39 | +restore_hot() { |
| 40 | + if [ "$HOT_MOVED" = "1" ] && [ -f public/hot.disabled-for-lighthouse ]; then |
| 41 | + mv public/hot.disabled-for-lighthouse public/hot |
| 42 | + fi |
| 43 | +} |
| 44 | +trap restore_hot EXIT |
| 45 | + |
| 46 | +# Filter pages.json down to requested names (all, if none given) |
| 47 | +if [ "$#" -gt 0 ]; then |
| 48 | + FILTER_JSON=$(printf '%s\n' "$@" | jq -R . | jq -s .) |
| 49 | + PAGES=$(jq -c --argjson names "$FILTER_JSON" '[.[] | select(.name as $n | $names | index($n))]' "$PAGES_JSON") |
| 50 | +else |
| 51 | + PAGES=$(jq -c '.' "$PAGES_JSON") |
| 52 | +fi |
| 53 | + |
| 54 | +COUNT=$(echo "$PAGES" | jq 'length') |
| 55 | +echo "==> Running Lighthouse against $COUNT page(s), output -> $OUT_DIR" |
| 56 | + |
| 57 | +echo "$PAGES" | jq -c '.[]' | while read -r page; do |
| 58 | + name=$(echo "$page" | jq -r '.name') |
| 59 | + path=$(echo "$page" | jq -r '.path') |
| 60 | + echo ">>> $name -> $path" |
| 61 | + npx --yes lighthouse "${BASE_URL}${path}" \ |
| 62 | + --output=json --output-path="$OUT_DIR/${name}.json" \ |
| 63 | + --chrome-flags="--headless=new --ignore-certificate-errors" \ |
| 64 | + --preset=desktop \ |
| 65 | + --only-categories=performance,accessibility,best-practices,seo \ |
| 66 | + --quiet || echo "FAILED: $name" |
| 67 | +done |
| 68 | + |
| 69 | +echo "==> Building summary" |
| 70 | +{ |
| 71 | + echo "# Lighthouse summary — $RUN_LABEL" |
| 72 | + echo |
| 73 | + printf '| %-20s | %-10s | %-6s | %-6s | %-13s | %-6s | %-6s |\n' "page" "perf" "a11y" "bp" "seo" "cls" "lcp" |
| 74 | + printf '|%s|%s|%s|%s|%s|%s|%s|\n' "----------------------" "------------" "--------" "--------" "---------------" "--------" "--------" |
| 75 | + for f in "$OUT_DIR"/*.json; do |
| 76 | + [ -e "$f" ] || continue |
| 77 | + name=$(basename "$f" .json) |
| 78 | + perf=$(jq -r '(.categories.performance.score // "n/a") | if type=="number" then .*100 else . end' "$f") |
| 79 | + a11y=$(jq -r '(.categories.accessibility.score // "n/a") | if type=="number" then .*100 else . end' "$f") |
| 80 | + bp=$(jq -r '(.categories["best-practices"].score // "n/a") | if type=="number" then .*100 else . end' "$f") |
| 81 | + seo=$(jq -r '(.categories.seo.score // "n/a") | if type=="number" then .*100 else . end' "$f") |
| 82 | + cls=$(jq -r '.audits["cumulative-layout-shift"].displayValue // "n/a"' "$f") |
| 83 | + lcp=$(jq -r '.audits["largest-contentful-paint"].displayValue // "n/a"' "$f") |
| 84 | + printf '| %-20s | %-10s | %-6s | %-6s | %-13s | %-6s | %-6s |\n' "$name" "$perf" "$a11y" "$bp" "$seo" "$cls" "$lcp" |
| 85 | + done |
| 86 | +} | tee "$OUT_DIR/summary.md" |
| 87 | + |
| 88 | +echo |
| 89 | +echo "==> Reports saved in $OUT_DIR" |
0 commit comments