DEV Community

Rizwan Saleem
Rizwan Saleem

Posted on

Integrating Accessibility QA into Your CI/CD Pipeline

Integrating Accessibility QA into Your CI/CD Pipeline

Integrating Accessibility QA into Your CI/CD Pipeline

Accessibility (a11y) is essential for inclusive products, yet many teams treat it as a separate checklist that happens late in development. This tutorial shows how to integrate accessibility testing into your CI/CD pipeline so every PR and deployment is evaluated for inclusivity. You’ll learn practical strategies, concrete tooling, and a repeatable workflow you can adopt in minutes.

What you’ll build

  • A lightweight, automated a11y test suite that runs on every pull request
  • Clear, actionable failure signals that don’t block engineers with noisy errs
  • A sustainable process for tracking accessibility issues alongside code changes

Prerequisites

  • A modern JavaScript/TypeScript web app (React, Vue, Angular, or plain HTML)
  • Node.js and npm/yarn installed
  • A Git-based workflow with pull requests
  • Basic familiarity with CI/CD tools (GitHub Actions used in examples)

Overview of the approach

  • Use automated accessibility testing to catch common issues at the UI level.
  • Integrate tests into CI to fail PRs when regressions appear.
  • Add lightweight visual checks and manual QA gates where automated checks aren’t enough.
  • Maintain an accessibility scoreboard to track progress over time.

Section 1: Choosing the right accessibility tests

  • Structural checks: Ensure semantic HTML is used (correct landmarks, headings order, ARIA attributes only where needed).
  • Per-element checks: Verify color contrast, focus visibility, keyboard operability.
  • Interaction checks: Validate that common widgets (buttons, menus, modals) are accessible via keyboard and provide proper screen reader hints.
  • Dynamic content checks: Ensure live regions and ARIA updates announce changes to assistive tech.

Recommended tooling (focused on automated checks)

  • Axe-core: Core accessibility engine that runs in the browser and can be integrated into unit/integration tests.
  • Axe Core CLI or axe-core with a11y automation libraries (e.g., @axe-core/puppeteer, axe-playwright).
  • Pa11y or Pa11y-ci for headless browser accessibility testing.
  • Lighthouse accessibility audits for performance- and UX-oriented checks.
  • Color contrast checkers (e.g., accessible-color-contrast or axe plugin coverage).

Section 2: Setting up automated tests locally
Goal: get quick feedback during development and before pushing code.

1) Install dependencies

  • If you’re using npm:
    • npm install save-dev axe-core @axe-core/puppeteer pa11y-pa11y lighthouse
  • If you’re using yarn:
    • yarn add dev axe-core @axe-core/puppeteer pa11y-pa11y lighthouse

2) Add a local test script
Sample script (Node.js) to run axe against a local page:

  • Create test/axe-test.js
    • const puppeteer = require('puppeteer');
    • const { axe } = require('axe-core');
    • (simplified example) launch browser, navigate to http://localhost:3000, inject axe, run, and fail if violations found.

3) Basic usage example

  • Start your app locally (e.g., npm run start)
  • Run node test/axe-test.js and review violations
  • Focus on high-severity violations first (contrast, missing alt text, incorrect landmark usage)

4) Add color-contrast checks

  • Integrate with axe or run a separate color-contrast library to flag insufficient contrast ratios ( WCAG 2.1 AA requires at least 4.5:1 for normal text).

Section 3: Integrating into CI (GitHub Actions example)
Goal: automatically test accessibility on every PR and PR review.

1) Create a workflow file

  • Path: .github/workflows/accessibility.yml
  • Triggers: on pull_request, on push to main (optional)
  • Jobs:
    • name: Build runs-on: ubuntu-latest steps:
      • uses: actions/checkout@v4
      • name: Use Node.js uses: actions/setup-node@v4 with: node-version: '18'
      • name: Install run: npm ci
      • name: Build run: npm run build
      • name: Run accessibility tests run: node test/axe-test.js
      • name: Run Pa11y run: npx pa11y http://localhost:3000 Note: If your app isn’t hosted in CI, you can use a headless browser approach with Puppeteer to spin up the app in CI and run tests against it, or deploy a temporary preview URL to test against.

2) Treat results as gate decisions

  • Configure the workflow to fail if any violations exceed a threshold or if critical violations exist.
  • Example: fail if axe findings include any with impact: critical or failure count > 0 for critical issues in a PR.

3) Optional: artifactizing results

  • Save a11y results as artifacts so developers can inspect them.
  • Example: upload the JSON report or generate a human-readable HTML report.

Section 4: Handling flaky tests and maintenance

  • Flakiest issues: color contrast can vary with themes; ensure tests are robust by testing against a representative theme.
  • Reduce noise: focus thresholds on critical items first (e.g., ensure button labels are readable, not hidden behind hover).
  • De-duplicate violations by element or component to avoid repetitive failures in the same area.

Section 5: Manual QA gates and integration with design/story process

  • Automated tests cover baseline issues; manual checks confirm nuanced flows.
  • Create a11y checklists for reviewers in PR templates:
    • Can I navigate with keyboard?
    • Are all actionable controls visible and labeled?
    • Do dynamic updates announce changes?
    • Are images and icons properly described?
  • Use design reviews or a11y champions in your team to perform periodic audits on complex components (accordions, carousels, custom widgets).

Section 6: Progressive improvements and metrics

  • Track metrics over time to show progress:
    • Number of accessibility violations per PR
    • Time to fix for critical issues
    • Coverage of components with tested a11y attributes
  • Visualize progress with a simple dashboard:
    • A line chart of critical violations over sprints
    • A heatmap of components with consistent issues
  • Set realistic targets (e.g., reduce critical violations by 75% in 6 months, maintain 0 critical violations in main branch).

Section 7: Example: integrating with a React app
1) Install dependencies

  • npm install save-dev @axe-core/puppeteer puppeteer 2) Simple axe-test.js (outline)
  • Start a dev server in CI, navigate to the page, run axe-core, and log results. 3) Add script to package.json
  • "test:a11y": "node test/axe-test.js" 4) Update CI workflow to run npm run build && npm run test:a11y

Section 8: Example: a minimal local test using Playwright

  • Install: npm i -D @playwright/test
  • Create tests/a11y.spec.ts
    • Use Playwright to open page, inject axe-core, run, and assert no violations
  • Run: npx playwright test

Illustrative example: a simple component and an a11y check

  • Component: a custom modal with an overlay
  • Potential issues:
    • Overlay lacks aria-hidden when modal is open
    • Focus trap not implemented
    • Close button lacks accessible label
  • Automated checks would catch missing aria-labels, missing roles, and focus management gaps, prompting quick fixes before merge.

Common pitfalls and how to avoid them

  • Pitfall: Treating a11y as a one-off task
    • Solution: Treat it as an ongoing quality gate integrated into CI/CD and design reviews.
  • Pitfall: Over-reliance on automated checks
    • Solution: Combine automated tests with manual audits for complex components and real-world usage scenarios.
  • Pitfall: Slow CI due to heavy tests
    • Solution: Run lightweight checks on PRs and schedule deeper audits in nightly builds or during release cycles.

Final checklist before shipping

  • Automated a11y checks fail builds on critical issues
  • PRs include at least one fix for any reported critical or high-severity issues
  • Manual QA covers keyboard navigation and screen reader compatibility for core flows
  • Accessibility metrics are tracked and show improvement over time
  • A11y champions are available for ongoing guidance and reviews

If you’d like, I can tailor this to your stack (React, Vue, or Svelte), show exact code snippets for your setup, or draft a ready-to-paste CI workflow for GitHub Actions, GitLab CI, or CircleCI. Which stack and CI/CD platform are you using?

-

Rizwan Saleem | https://rizwansaleem.co

Sources

Top comments (0)