Skip to content

feat: accessibility audit — axe-core E2E tests, Lighthouse CI gate, and summary reporting#82

Open
dsanchezcr with Copilot wants to merge 8 commits into
mainfrom
copilot/accessibility-improvements-cicd
Open

feat: accessibility audit — axe-core E2E tests, Lighthouse CI gate, and summary reporting#82
dsanchezcr with Copilot wants to merge 8 commits into
mainfrom
copilot/accessibility-improvements-cicd

Conversation

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Adds a layered accessibility quality gate to the CI/CD pipeline: axe-core WCAG scanning in Playwright, a Lighthouse CI score threshold job, and per-run reporting surfaced directly in PR checks.

New files

  • e2e/accessibility.spec.ts — axe-core tests (wcag2a/2aa/21a/21aa) against home, create-game, and privacy pages. Fails on critical/serious violations with per-violation details; moderate/minor are recorded but non-blocking. Each test writes playwright-report/a11y/<page>.json for the summary script.
  • lighthouserc.yml — Lighthouse CI config: serves dist/ locally, runs accessibility category only, enforces score ≥ 0.90, uploads report to temporary-public-storage.

CI/CD changes (ci-cd.yml)

New accessibility-audit job runs in parallel with e2e (both need build):

  • Installs @lhci/cli@0.14.x, runs lhci autorun, captures exit code without killing the run
  • Extracts score from .lighthouseci/manifest.json, uploads lighthouse-report artifact
  • Posts/updates a marker-keyed PR comment with score, threshold, and temporary storage link
  • Final step fails the job explicitly if lhci exited non-zero

Both deploy-pr-infrastructure and deploy-qa-infrastructure now require [e2e, accessibility-audit] — accessibility is a hard gate before any environment is provisioned.

Summary script (scripts/e2e-summary.sh)

Appends an ♿ Accessibility Violations table to $GITHUB_STEP_SUMMARY by aggregating playwright-report/a11y/*.json violation counts by severity (critical / serious / moderate / minor). Section is omitted automatically when the directory is absent.

Copilot AI added 2 commits July 15, 2026 19:02
…, and e2e-summary extension

- e2e/accessibility.spec.ts: axe-core WCAG 2.x scans for home, create-game, and privacy pages; fail on critical/serious violations; write per-page violation JSON to playwright-report/a11y/
- lighthouserc.yml: Lighthouse CI config with accessibility ≥ 0.90 threshold, onlyCategories:accessibility, and temporary-public-storage upload
- .github/workflows/ci-cd.yml: new accessibility-audit job (needs: build) — runs lhci autorun, uploads artifact, posts/updates PR comment with score and report link, gates deploy-pr-infrastructure and deploy-qa-infrastructure via needs: [e2e, accessibility-audit]
- scripts/e2e-summary.sh: appends accessibility violation count table (critical/serious/moderate/minor) from playwright-report/a11y/*.json to the step summary
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

❌ Lighthouse Accessibility Score

Category Score Threshold
♿ Accessibility N/A% ≥ 90%

⚠️ Score is below the 90% threshold — please fix the violations.

🔗 View full Lighthouse report (expires in 7 days)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an accessibility-focused quality gate to the existing CI pipeline by introducing axe-core-based Playwright E2E checks, a Lighthouse CI accessibility threshold job, and surfacing both results in GitHub Actions summaries / PR comments.

Changes:

  • Added Playwright E2E accessibility scans (axe-core) for key pages and wrote per-page JSON outputs for aggregation.
  • Added Lighthouse CI configuration and a new accessibility-audit workflow job that enforces an accessibility score threshold and posts a marker-based PR comment.
  • Extended the existing E2E summary script to include an aggregated accessibility-violations table when axe outputs are present.
Show a summary per file
File Description
scripts/e2e-summary.sh Appends an axe-core violations severity table to the GitHub Actions step summary.
lighthouserc.yml Defines Lighthouse CI collection/assert/upload settings for accessibility-only runs.
e2e/accessibility.spec.ts Adds axe-core scans for home/create-game/privacy pages and persists violation JSON for reporting.
.github/workflows/ci-cd.yml Introduces a Lighthouse accessibility audit job and gates infra provisioning on it.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 5
  • Review effort level: Low

Comment thread scripts/e2e-summary.sh
Comment thread .github/workflows/ci-cd.yml
Comment thread e2e/accessibility.spec.ts Outdated
Comment thread e2e/accessibility.spec.ts Outdated
Comment thread e2e/accessibility.spec.ts Outdated
dsanchezcr and others added 5 commits July 15, 2026 15:18
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@dsanchezcr

Copy link
Copy Markdown
Member

@copilot fix the accessibility issues reported to fix the violations and make sure the build and test pass as expected.

…add aria-labels

- PrivacyView: change motion.div initial opacity from 0→1 to 1→1 so axe-core
  does not encounter semi-transparent text when scanning the page. The fade-in
  animation (opacity: 0 → 1) caused color-contrast failures on 6 of 7 sections
  because axe-core runs immediately after domcontentloaded, before Framer Motion
  animations complete.
- CreateGameView: add aria-label={t('selectCurrency')} to SelectTrigger so the
  currency dropdown button has a discernible accessible name, fixing the
  critical button-name violation.
- CreateGameView: add aria-label to the icon-only remove-participant button
  (step 2) that only contains an X icon, fixing a future button-name violation.

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix the accessibility issues reported to fix the violations and make sure the build and test pass as expected.

Fixed in commit fix: resolve accessibility violations. Two root causes were identified from the CI logs:

  1. Privacy page — [serious] color-contrast (6 nodes): Framer Motion's initial={{ opacity: 0, y: 20 }} caused all 7 section cards to start invisible. axe-core runs immediately after domcontentloaded, before the animations complete, so 6 sections had near-zero contrast. Fixed by changing initial={{ opacity: 0, y: 20 }}initial={{ opacity: 1, y: 20 }} across all motion.div elements in PrivacyView.tsx — preserves the slide-up effect while keeping content always visible to assistive tools.

  2. Create-game page — [critical] button-name (1 node): The currency SelectTrigger rendered as a button without a discernible accessible name (Radix Select's item registry is only populated after the dropdown opens). Fixed by adding aria-label={t('selectCurrency')} to the SelectTrigger. Additionally added a descriptive aria-label to the icon-only remove-participant button in step 2 as a preventive fix.

@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://salmon-river-08d16b30f-82.eastus2.7.azurestaticapps.net

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants