Interactive accessibility testing for real-world forms Runs axe-coreafter the clicks, key-presses and dynamic DOM changes your users actually make.
Why not just run a static linter? Static axe / Lighthouse a11y-form-tester Scans the HTML that exists on first paint Re-runs axeafter each scenario (fill, submit, tab-loop, open-modal…) Misses fields that are revealed later Catches missing labels, duplicate IDs, modal issues, bad autocomplete tokens, etc. No keyboard interaction Simulates Tab navigation to surface focus-order defects
Plug-and-play CLI –npx a11y-form-tester "dist/**/*.html"Scenario engine static scan →submit form → dynamic scan auto-fill required fields tab-loop for focus-trap checks open modals / dialogs Deduplicated report – one line per unique rule + elementZero config CI – exits1 when violations are foundType-safe – written in TypeScript, published with.d.tsa11y-form-tester" <glob/of/pages/**/*.html>" [options]Options --report< file> Save pretty HTML report to the given path --max< n> Fail only when more than< n> violations (default: 0) --rules< list> Comma-separated axe rule IDs to run (defaults to smart subset) Example:
npx a11y-form-tester" build/**/*.html" --report a11y.html The CLI prints a coloured table and writesa11y.html next to your artefacts.
Scenario (ships in repo) Rule triggered Why static scan misses it Coupon code <select> appears after checkbox – has no labelselect-nameField not in initial DOM Dialog injected by JavaScript lacks accessible namearia-dialog-nameDialog exists only after click VAT ID field revealed with invalidautocomplete="tax-id"autocomplete-validAttribute not validated until shown Clone phone field duplicatesid="phone"duplicate-idClone added after checkbox Icon-only "help" button injected laterbutton-nameNo accessible name Referral input relies only ontitlelabel-title-onlyField hidden until user action Error message with poor color contrastcolor-contrastError shown only after validation Password field missing labellabelBasic but common oversight
All eight fixtures live undertest/fixtures/ for you to try.
Add to CI in 15 seconds (GitHub Actions) # .github/workflows/a11y.ymlname :a11y on :[push, pull_request] jobs :test :runs-on :ubuntu-latest steps : -uses :actions/checkout@v4 -uses :pnpm/action-setup@v3 with :{ version: 8 } -run :pnpm install --frozen-lockfile -run :pnpx a11y-form-tester "dist/**/*.html" Green build = zero violations.
Createa11y-form-tester.config.json in project root (optional):
{"rules" : [" label" ," select-name" ," autocomplete-valid" ],"max" :5 ,} PRs & issues are welcome! Here are some areas and suggestions I am looking to improve:
Unit Tests - Help us reach better coverage for:
CLI argument processing HTML report generation Axe rule configuration New Scenarios - Add more test scenarios insrc/runner/scenarios/:
Current scenarios include form submission, tab navigation, autofill, and modal opening We need scenarios for hover interactions, drag-and-drop, custom form controls, etc. Each scenario should be a simple async function that manipulates the page New Features - Priority items:
Config file support for project-specific settings Additional reporter formats (JUnit XML, JSON) Support for more axe rules (custom rule packs) MIT