klassijs-a11y-validator
v1.1.0
Published
This accessibility verification function serves as an automated accessibility testing tool that helps identify and document accessibility issues based on WCAG standards.
Maintainers
Readme
klassijs A11y (Accessibility) Validator
Overview
klassijs-a11y-validator is a powerful tool designed to automate the verification of accessibility compliance for digital content, such as websites or applications. It helps developers and testers identify accessibility issues to ensure compliance with WCAG (Web Content Accessibility Guidelines) by programmatically testing elements against established standards (e.g., WCAG 2.0,2.1,2.2 on level A, AA and AAA). The function aims to ensure a more inclusive user experience, especially for individuals with disabilities, by identifying and helping resolve accessibility issues.
Key Features:
- Automated Accessibility Testing: Quickly validates the accessibility of web pages and applications.
- Website Crawling: Automatically discovers and tests all pages on a website from a starting URL.
- Compliance Checks: Ensures your application meets WCAG 2.0/2.1/2.2 guidelines and other accessibility standards.
- Detailed Reporting: Provides detailed reports on accessibility issues found during validation.
- Customizable Rules: Customize which accessibility rules you want to check based on your project's needs.
- Integration Ready: Easily integrate into your CI/CD pipelines for continuous accessibility validation.
Installation
You can easily install the a11y-validator using pnpm. Follow the steps below:
- Open your terminal and navigate to your project directory.
- Run the following command:
pnpm add klassijs-a11y-validator
Additional Dependencies for Browser Automation
To run tests on real websites, you'll also need WebdriverIO and a browser driver:
# Install WebdriverIO
pnpm add -D @wdio/cli webdriverio
# For Chrome (recommended)
pnpm add -D chromedriver
# OR for Firefox
pnpm add -D geckodriverQuick Start - Testing a Real Website
The runner in src/run-a11y-test.js now supports four modes:
- Crawl and test an entire site from a start URL
- Crawl-only (discover pages without accessibility checks)
- Test specific page(s) only (single URL, comma list, or file list)
- Discover pages from XML sitemaps and test them
For crawl and crawl-only, discovery now works as:
- Try sitemap discovery first (
robots.txtsitemap entries, then/sitemap.xml) - If no sitemap pages are found, fall back to normal on-page link crawling
# 1) Crawl and test from a start URL
node src/run-a11y-test.js https://example.com
# 2) Crawl-only (discover pages, skip a11y tests)
node src/run-a11y-test.js https://example.com --crawl-only
# 3) Test specific pages only (no crawling)
node src/run-a11y-test.js https://example.com --pages /,/about,/contact
# Auth (optional): use login + credentials for private pages
node src/run-a11y-test.js https://example.com \
--login-url https://example.com/login \
--username test-user \
--password test-pass
# 4) Test pages from file (`.txt` or `.csv`)
node src/run-a11y-test.js --base-url https://example.com --pages-file ./pages.txt
node src/run-a11y-test.js --base-url https://example.com --pages-file ./pages.csv
# 5) CSV: ignore columns by header name or zero-based index
node src/run-a11y-test.js --base-url https://example.com --pages-file ./pages.csv --csv-ignore-columns notes,status
node src/run-a11y-test.js --base-url https://example.com --pages-file ./pages.csv --csv-ignore-columns 2,3
# 6) Discover pages from sitemap(s) and test them
node src/run-a11y-test.js --from-sitemap https://example.com
node src/run-a11y-test.js --from-sitemap --base-url https://example.com --sitemap-url https://example.com/sitemap.xml
# 7) Override rule selection from CLI
node src/run-a11y-test.js https://example.com --include-tags wcag2aa,wcag21aa
node src/run-a11y-test.js https://example.com --exclude-tags best-practice
node src/run-a11y-test.js https://example.com --exclude-rules color-contrast,image-alt
# 8) Experimental-only run (recommended as non-blocking signal)
node src/run-a11y-test.js https://example.com --include-tags experimentalNPM Scripts
The package provides scripts for each mode:
# Crawl and test
pnpm a11y:crawl https://example.com
# Crawl only
pnpm a11y:crawl-only https://example.com
# Specific page(s)
pnpm a11y:pages https://example.com/about
node src/run-a11y-test.js --base-url https://example.com --pages /,/about,/contact
# Pages from file
pnpm a11y:pages-file ./pages.txt
node src/run-a11y-test.js --base-url https://example.com --pages-file ./pages.txt
node src/run-a11y-test.js --base-url https://example.com --pages-file ./pages.csv
node src/run-a11y-test.js --base-url https://example.com --pages-file ./pages.csv --csv-ignore-columns notes,status
# From sitemap
node src/run-a11y-test.js --from-sitemap https://example.com
node src/run-a11y-test.js --from-sitemap --base-url https://example.com --sitemap-url https://example.com/sitemap.xml
# Auth examples (optional)
pnpm a11y:crawl https://example.com --login-url https://example.com/login --username test-user --password test-pass
# Experimental-only signal run (do not block pipeline)
pnpm a11y:experimental https://example.com || true
# Generate manual review checklist from latest summary
pnpm a11y:manual-checklist
# Generate locale/page-type coverage report
node src/report-coverage-by-page-type.js --inventory ./examples/page-inventory/en.csvpages.txt and pages.csv support:
- One URL or path per line
- Blank lines
- Comments starting with
#
For CSV files, you can ignore columns with:
--csv-ignore-columns notes,status(header names)--csv-ignore-columns 2,3(zero-based indexes)
Example:
# Relative paths
/
/about
/contact
# Absolute URL also works
https://example.com/pricingCSV example:
url,path
https://example.com/pricing,/about
/contact,Usage
You can use the validator via:
- The CLI runner (
src/run-a11y-test.js) for real-site automation - The API (
a11yValidator/a11yValidatorFromUrl) inside your own scripts
CLI Runner Modes (src/run-a11y-test.js)
1) Crawl and test a whole site
node src/run-a11y-test.js https://yourwebsite.comThis mode:
- Crawls internal pages from the start URL
- Runs accessibility checks on discovered pages
- Generates reports in the reports directory
- Uses sitemap-first discovery with crawler fallback automatically
2) Crawl-only (discover pages only)
node src/run-a11y-test.js https://yourwebsite.com --crawl-only
# OR
CRAWL_ONLY=true node src/run-a11y-test.js https://yourwebsite.comThis mode:
- Crawls and lists discoverable pages
- Skips accessibility checks
- Helps verify coverage before full testing
- Uses sitemap-first discovery with crawler fallback automatically
3) Test only specific pages (no crawling)
# Single explicit page
node src/run-a11y-test.js --pages https://yourwebsite.com/about
# Multiple pages using paths (with base URL)
node src/run-a11y-test.js https://yourwebsite.com --pages /,/about,/contact
# OR
node src/run-a11y-test.js --base-url https://yourwebsite.com --pages /,/about,/contact
# From file
node src/run-a11y-test.js --base-url https://yourwebsite.com --pages-file ./pages.txt
node src/run-a11y-test.js --base-url https://yourwebsite.com --pages-file ./pages.csvUse this mode when you only want to validate selected pages instead of the full site.
4) Test pages discovered from sitemaps
# Use robots.txt -> Sitemap directives (fallback to /sitemap.xml)
node src/run-a11y-test.js --from-sitemap https://yourwebsite.com
# Provide one or more sitemap URLs directly (comma-separated)
node src/run-a11y-test.js --from-sitemap --base-url https://yourwebsite.com --sitemap-url https://yourwebsite.com/sitemap.xml,https://yourwebsite.com/sitemap-posts.xmlThis mode:
- Discovers URLs from XML sitemap files (including sitemap indexes)
- Filters to the same domain as
--base-url(or the positional URL) - Tests discovered pages using the same report pipeline as other test modes
Single Page Validation
Import the Tool: Import the
a11y-validatormodule into your project:const { a11yValidator } = require('klassijs-a11y-validator');Run Accessibility Validation on Current Page: The
a11yValidatorfunction validates the page that the browser is currently on:// Make sure browser is already navigated to the page await browser.url('https://yourwebsite.com'); // Run validation await a11yValidator('home-page', true);
Multi-Page Validation from URL
Import the URL Validator:
const { a11yValidatorFromUrl } = require('klassijs-a11y-validator');Run Accessibility Validation on Entire Website:
async function validateEntireWebsite() { try { // Make sure browser is initialized before calling const results = await a11yValidatorFromUrl('https://yourwebsite.com', { maxPages: 50, // Maximum pages to crawl (default: 50) maxDepth: 3, // Maximum crawl depth (default: 3) excludePaths: ['/admin', '/api'], // Paths to exclude count: true, // Include total error count (default: true) // Accessibility rule configuration (optional): excludeTags: [], // Exclude WCAG tags (e.g., ['wcag22aa', 'best-practice']) excludeRules: [], // Exclude specific rules (e.g., ['color-contrast']) includeTags: null // Only check specific tags (overrides defaults) }); console.log(`Tested ${results.pagesTested} pages`); console.log(`Found ${results.totalErrors} total accessibility errors`); console.log(`Pages with errors: ${results.errors.length}`); } catch (error) { console.error('Error during accessibility validation:', error); } } validateEntireWebsite();The
a11yValidatorFromUrlfunction will:
- Crawl the website starting from the provided URL
- Discover internal pages using sitemap-first discovery (robots.txt sitemap entries + common sitemap locations), with crawler fallback if no sitemap URLs are found
- Test each discovered page for accessibility issues
- Generate individual reports for each page
- Return a summary of all results
- Review the Reports:
The results will contain:
- Individual HTML/JSON reports for each page tested (saved to reports directory)
- Summary object with:
- Total pages discovered and tested
- Total accessibility errors found
- List of pages with errors
- Error count per page
- Each report includes:
- Issue descriptions
- Severity levels (critical, serious, moderate, minor)
- Affected elements
- Recommended fixes
Configuration
Multi-Page Validation From Pages File (.txt / .csv)
If you want to test a specific list of pages (instead of crawling a whole site), use a11yValidatorFromPagesFile.
It supports:
.txt: one URL or relative path per line.csv: URL/path in the first usable column (optionally ignore columns viacsvIgnoreColumns)
Example:
const { a11yValidatorFromPagesFile } = require('klassijs-a11y-validator');
// Make sure `global.browser` is initialized before calling this.
await a11yValidatorFromPagesFile('./pages.csv', {
baseUrl: 'https://example.com', // required if your CSV/TXT contains relative paths
csvIgnoreColumns: ['pagetype'], // or ['2', '3'] / ['1'] depending on your file
maxPagesToTest: null, // null = test all entries
auth: null, // optional auth config
excludeTags: [],
excludeRules: [],
includeTags: null,
});Accessibility Rule Configuration
You can customize which accessibility standards and rules are checked:
await a11yValidatorFromUrl('https://yourwebsite.com', {
// Exclude specific WCAG standards
excludeTags: ['wcag22aa', 'best-practice'], // Exclude WCAG 2.2 Level AA and best practices
// Exclude specific rules
excludeRules: ['color-contrast', 'image-alt'], // Exclude color contrast and image alt checks
// Only check specific standards (overrides defaults)
includeTags: ['wcag2a', 'wcag2aa'], // Only check WCAG 2.0 Level A and AA
});Available WCAG Tags:
wcag2a- WCAG 2.0 Level Awcag2aa- WCAG 2.0 Level AAwcag2aaa- WCAG 2.0 Level AAAwcag21a- WCAG 2.1 Level Awcag21aa- WCAG 2.1 Level AAwcag21aaa- WCAG 2.1 Level AAAwcag22a- WCAG 2.2 Level Awcag22aa- WCAG 2.2 Level AAwcag22aaa- WCAG 2.2 Level AAAbest-practice- Additional best practices
Default Configuration:
By default, the tool runs all available axe rules and excludes only rules tagged experimental.
This provides broad automated coverage; manual review is still required for criteria that cannot be fully automated.
This default also includes rule/tag families such as:
section508section508.22.a...section508.22.p(legacy mapping tags)EN-301-549ACTcat.*category tags (for examplecat.color,cat.keyboard,cat.text-alternatives,cat.aria,cat.forms,cat.name-role-value)
Example: Check only WCAG 2.1 Level AA:
await a11yValidatorFromUrl('https://yourwebsite.com', {
includeTags: ['wcag21aa']
});Example: Exclude color contrast checks:
await a11yValidatorFromUrl('https://yourwebsite.com', {
excludeRules: ['color-contrast']
});CLI Rule Overrides
src/run-a11y-test.js supports optional flags:
--include-tags <csv>(example:wcag2aa,wcag21aa)--exclude-tags <csv>--exclude-rules <csv>
Environment variable equivalents:
A11Y_INCLUDE_TAGSA11Y_EXCLUDE_TAGSA11Y_EXCLUDE_RULES
When --include-tags is not provided, defaults apply (all non-experimental rules).
Enterprise / Global Readiness
1) Manual review process for non-automatable criteria
Generate a checklist from the latest comprehensive summary:
pnpm a11y:manual-checklistOutput:
reports/manual-a11y-review.md
2) Locale/language/template coverage
Use explicit page inventories per locale:
examples/page-inventory/en.csvexamples/page-inventory/es.csvexamples/page-inventory/ar.csv
Run by file:
node src/run-a11y-test.js --base-url https://example.com --pages-file ./examples/page-inventory/en.csv3) Experimental checks as non-blocking signal
Keep defaults in blocking runs. Run experimental separately as signal only:
pnpm a11y:experimental https://example.com || true4) Coverage tracking by page type
Generate coverage report from inventory + latest summary:
node src/report-coverage-by-page-type.js --inventory ./examples/page-inventory/en.csvOutput:
reports/coverage/page-type-coverage.json
Axe Rule Reference
Official axe rule catalog (maintained by Deque):
To print the exact rule IDs available in your installed axe-core version:
const axe = require('axe-core');
console.log(axe.getRules().map((rule) => rule.ruleId));Crawler Options
When using a11yValidatorFromUrl, you can customize the crawling behavior:
await a11yValidatorFromUrl('https://yourwebsite.com', {
maxPages: 100, // Maximum number of pages to crawl (default: 50)
maxDepth: 5, // Maximum depth to crawl from starting URL (default: 3)
excludePaths: [ // Paths to exclude from crawling
'/admin',
'/api',
'/private'
],
// Link crawl runs first by default; set true to load URLs from sitemap/robots before crawling.
sitemapFirst: false, // set to true to use sitemap discovery first (capped by maxPages)
sitemapUrl: null, // optional single sitemap URL
sitemapUrls: null, // optional array of sitemap URLs
maxPagesToTest: 5, // Limit how many pages to test (default: null = test all)
// Useful for quick checks: discover all pages but only test a few
count: true // Include total error count in output (default: true)
});Example: Quick Check (Discover All, Test Only 5)
// Discover all 83 pages, but only test 5 of them for a quick check
await a11yValidatorFromUrl('https://yourwebsite.com', {
maxPages: null, // Discover all pages
maxPagesToTest: 5, // But only test 5 pages
});Browser Requirements
The validator requires a browser instance to be available globally. Make sure you have initialized your browser automation framework (e.g., WebdriverIO) before calling the validator functions:
// Example with WebdriverIO
const { remote } = require('webdriverio');
(async () => {
global.browser = await remote({
capabilities: { browserName: 'chrome' }
});
// Now you can use the validator
await a11yValidatorFromUrl('https://yourwebsite.com');
await browser.deleteSession();
})();Authentication (Optional)
src/run-a11y-test.js can authenticate before crawling/testing when you pass login info.
CLI flags:
--login-url <url>--username <username>--password <password>
Environment variables (also supported):
LOGIN_URLA11Y_USERNAMEA11Y_PASSWORD
Example:
pnpm a11y:crawl https://example.com \
--login-url https://example.com/login \
--username test-user \
--password test-passNote: src/run-a11y-test-with-auth.js is still present as a standalone example, but the recommended approach is to use src/run-a11y-test.js with the auth flags above.
Troubleshooting
Quick Decision Tree
- If you get
EACCESorpermission denied: setCACHE_DIR=~/.webdriverio-cacheand retry. - If Chrome driver fails to start: use
BROWSER=safarion macOS for a quick unblock. - If Safari is not an option: install driver manually (
brew install chromedriverorbrew install geckodriver), then verify withwhich. - If issues persist: clear caches (
rm -rf /tmp/chromedriver* ~/.webdriverio-cache) and run again.
Browser Driver / Permission Errors
If you see errors such as EACCES, permission denied, or chromedriver/geckodriver executable issues:
# Use a user-writable cache directory
CACHE_DIR=~/.webdriverio-cache node src/run-a11y-test.js https://example.com
# Or export it for your session
export CACHE_DIR=~/.webdriverio-cache
node src/run-a11y-test.js https://example.comIf Chrome setup is problematic on macOS, use Safari (no extra driver install required):
BROWSER=safari node src/run-a11y-test.js https://example.comOr install a browser driver manually:
# Chrome
brew install chromedriver
# Firefox
brew install geckodriverUseful checks:
which chromedriver
which geckodriverIf you still have temp/cache issues, clean old driver caches and retry:
rm -rf /tmp/chromedriver* ~/.webdriverio-cacheContributing
We welcome contributions! If you encounter any bugs, have suggestions for new features, or want to improve the documentation, feel free to open an issue or submit a pull request.
License
This project is licensed under the MIT License.
