#!/usr/bin/env bash # WCAG 2.1 AA audit script — runs Lighthouse + axe-core against key pages. # # Usage: # ./scripts/wcag-audit.sh # Default: https://didi.integrare.local # BASE_URL=http://localhost:5173 ./scripts/wcag-audit.sh # # Required deps (auto-install if missing): # - @axe-core/cli # - lighthouse # # Output: # - reports/wcag//lighthouse-.html # - reports/wcag//axe-.json # - reports/wcag//SUMMARY.md # # Audit produces a formal report for PNRR recepție (cerință E5 caiet sarcini). set -euo pipefail BASE_URL="${BASE_URL:-https://didi.integrare.local}" TIMESTAMP=$(date -u +"%Y%m%d-%H%M%S") OUT_DIR="reports/wcag/${TIMESTAMP}" mkdir -p "$OUT_DIR" PAGES=( "/" "/dashboard" "/demo" "/email-verified" ) echo "=== WCAG 2.1 AA audit — $(date -u) ===" echo "Base URL: $BASE_URL" echo "Output: $OUT_DIR" echo "" # Auto-install tools if missing if ! command -v lighthouse >/dev/null 2>&1; then echo "Installing lighthouse globally..." npm install -g lighthouse@latest >/dev/null 2>&1 fi if ! command -v axe >/dev/null 2>&1; then echo "Installing @axe-core/cli globally..." npm install -g @axe-core/cli@latest >/dev/null 2>&1 fi SUMMARY="$OUT_DIR/SUMMARY.md" cat > "$SUMMARY" <&1 || echo "Lighthouse failed for $URL" # axe-core (WCAG-specific violations) axe "$URL" \ --tags wcag2a,wcag2aa,wcag21a,wcag21aa \ --save "$OUT_DIR/axe-$SAFE_NAME.json" \ --exit 0 2>&1 || echo "Axe failed for $URL" # Extract scores for summary if [ -f "$OUT_DIR/lighthouse-$SAFE_NAME.report.json" ]; then A11Y_SCORE=$(python3 -c " import json d = json.load(open('$OUT_DIR/lighthouse-$SAFE_NAME.report.json')) print(int(d['categories']['accessibility']['score'] * 100)) " 2>/dev/null || echo "N/A") SEO_SCORE=$(python3 -c " import json d = json.load(open('$OUT_DIR/lighthouse-$SAFE_NAME.report.json')) print(int(d['categories'].get('seo', {}).get('score', 0) * 100)) " 2>/dev/null || echo "N/A") else A11Y_SCORE="N/A"; SEO_SCORE="N/A" fi AXE_VIOLATIONS=$(python3 -c " import json try: d = json.load(open('$OUT_DIR/axe-$SAFE_NAME.json')) if isinstance(d, list) and d: d = d[0] print(len(d.get('violations', []))) except: print('N/A') " 2>/dev/null || echo "N/A") echo "" >> "$SUMMARY" echo "### \`$page\`" >> "$SUMMARY" echo "- Lighthouse A11y score: **$A11Y_SCORE / 100**" >> "$SUMMARY" echo "- Lighthouse SEO score: **$SEO_SCORE / 100**" >> "$SUMMARY" echo "- Axe-core violations (WCAG 2.1 AA): **$AXE_VIOLATIONS**" >> "$SUMMARY" echo "- Reports: [lighthouse]($(basename "$OUT_DIR")/lighthouse-$SAFE_NAME.report.html), [axe]($(basename "$OUT_DIR")/axe-$SAFE_NAME.json)" >> "$SUMMARY" done echo "" >> "$SUMMARY" echo "## WCAG 2.1 AA Compliance threshold" >> "$SUMMARY" echo "" >> "$SUMMARY" echo "- **Target**: Lighthouse A11y ≥ 95, axe-core violations = 0" >> "$SUMMARY" echo "- **Caiet sarcini cere**: WCAG 2.1 AA demonstrabil (contrast 4.5:1, focus visible, keyboard nav, ARIA, screen readers)" >> "$SUMMARY" echo "" >> "$SUMMARY" echo "## Next steps if violations found" >> "$SUMMARY" echo "" >> "$SUMMARY" echo "1. Open \`axe-.json\` — see \`violations[]\` array" >> "$SUMMARY" echo "2. Each violation has \`description\`, \`helpUrl\`, \`nodes[]\` with selector" >> "$SUMMARY" echo "3. Fix in source code" >> "$SUMMARY" echo "4. Re-run script — verify violations = 0" >> "$SUMMARY" echo "" echo "=== Audit complete ===" echo "Summary: $SUMMARY" echo "Open lighthouse HTML reports in browser for visual review."