Axe accessibility
Skill a5c-ai/babysitter/library/specializations/qa-testing-automation/skills/axe-accessibility
Babysitter enforces obedience on agentic workforces and enables them to manage extremely complex tasks and workflows through deterministic, hallucination-free self-orchestration
npx -y skills add a5c-ai/babysitter --skill axe-accessibilityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Deep integration with axe-core for automated accessibility testing. Execute accessibility scans, interpret WCAG violations, generate compliance reports, and integrate with Playwright/Cypress for comprehensive a11y testing.
SKILL.md
13.5 KB, as published. Nobody here has run it
axe-accessibility
You are axe-accessibility - a specialized skill for axe-core accessibility testing integration, providing comprehensive WCAG compliance validation capabilities.
Overview
This skill enables AI-powered accessibility testing including:
- Executing axe-core accessibility scans
- Interpreting WCAG violations and impacts
- Generating accessibility compliance reports
- Configuring rule inclusion/exclusion
- Integrating with Playwright/Cypress for automated a11y testing
- Handling dynamic content scanning
- Mapping violations to WCAG criteria
- Providing remediation guidance
Prerequisites
- Node.js environment for axe-core
- Test automation framework (Playwright, Cypress, or Selenium)
- Browser automation capability
- Optional: axe-playwright or axe-cypress packages
Capabilities
1. Playwright Integration
Use axe-core with Playwright for accessibility testing:
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test.describe('Accessibility Tests', () => {
test('homepage should have no violations', async ({ page }) => {
await page.goto('https://example.com');
const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
expect(accessibilityScanResults.violations).toEqual([]);
});
test('homepage should have no critical violations', async ({ page }) => {
await page.goto('https://example.com');
const accessibilityScanResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
.analyze();
const criticalViolations = accessibilityScanResults.violations
.filter(v => v.impact === 'critical' || v.impact === 'serious');
expect(criticalViolations).toEqual([]);
});
test('form page accessibility', async ({ page }) => {
await page.goto('https://example.com/contact');
// Wait for form to be fully loaded
await page.waitForSelector('form');
const results = await new AxeBuilder({ page })
.include('form')
.analyze();
// Log violations for debugging
if (results.violations.length > 0) {
console.log('Violations found:', JSON.stringify(results.violations, null, 2));
}
expect(results.violations).toEqual([]);
});
});
2. Cypress Integration
Use axe-core with Cypress:
// cypress/support/commands.js
import 'cypress-axe';
// cypress/e2e/accessibility.cy.js
describe('Accessibility Tests', () => {
beforeEach(() => {
cy.visit('/');
cy.injectAxe();
});
it('has no detectable accessibility violations on load', () => {
cy.checkA11y();
});
it('has no violations in main content', () => {
cy.checkA11y('#main-content');
});
it('has no critical violations', () => {
cy.checkA11y(null, {
includedImpacts: ['critical', 'serious']
});
});
it('logs violations for review', () => {
cy.checkA11y(null, null, (violations) => {
violations.forEach((violation) => {
cy.log(`${violation.id}: ${violation.description}`);
violation.nodes.forEach((node) => {
cy.log(` - ${node.target}`);
});
});
}, true);
});
});
3. Standalone axe-core Usage
Direct axe-core usage:
import { chromium } from 'playwright';
import axe from 'axe-core';
async function runAccessibilityAudit(url) {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
// Inject axe-core
await page.addScriptTag({ path: require.resolve('axe-core') });
// Run analysis
const results = await page.evaluate(async () => {
return await axe.run();
});
await browser.close();
return results;
}
// Usage
const results = await runAccessibilityAudit('https://example.com');
console.log(`Found ${results.violations.length} violations`);
4. WCAG Compliance Configuration
Configure axe for specific WCAG standards:
import AxeBuilder from '@axe-core/playwright';
// WCAG 2.1 Level AA compliance
const wcag21AAResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
.analyze();
// WCAG 2.2 Level AA compliance
const wcag22AAResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
.analyze();
// Section 508 compliance
const section508Results = await new AxeBuilder({ page })
.withTags(['section508'])
.analyze();
// Best practices (not strict compliance)
const bestPracticesResults = await new AxeBuilder({ page })
.withTags(['best-practice'])
.analyze();
5. Rule Configuration
Include/exclude specific rules:
import AxeBuilder from '@axe-core/playwright';
const results = await new AxeBuilder({ page })
// Include only specific rules
.withRules(['color-contrast', 'image-alt', 'label', 'link-name'])
.analyze();
// Or exclude rules
const resultsExcluding = await new AxeBuilder({ page })
.disableRules(['region', 'landmark-one-main'])
.analyze();
// Focus on specific element
const formResults = await new AxeBuilder({ page })
.include('#contact-form')
.analyze();
// Exclude problematic areas
const mainResults = await new AxeBuilder({ page })
.exclude('#third-party-widget')
.analyze();
6. Violation Analysis
Analyze and categorize violations:
function analyzeViolations(results) {
const summary = {
total: results.violations.length,
byImpact: {},
byWCAG: {},
criticalIssues: []
};
for (const violation of results.violations) {
// Count by impact
summary.byImpact[violation.impact] =
(summary.byImpact[violation.impact] || 0) + violation.nodes.length;
// Count by WCAG criteria
for (const tag of violation.tags) {
if (tag.startsWith('wcag')) {
summary.byWCAG[tag] = (summary.byWCAG[tag] || 0) + 1;
}
}
// Collect critical issues
if (violation.impact === 'critical' || violation.impact === 'serious') {
summary.criticalIssues.push({
id: violation.id,
impact: violation.impact,
description: violation.description,
help: violation.help,
helpUrl: violation.helpUrl,
affectedElements: violation.nodes.length
});
}
}
return summary;
}
7. Report Generation
Generate accessibility reports:
function generateA11yReport(results, format = 'html') {
const report = {
timestamp: new Date().toISOString(),
url: results.url,
summary: {
violations: results.violations.length,
passes: results.passes.length,
incomplete: results.incomplete.length,
inapplicable: results.inapplicable.length
},
violations: results.violations.map(v => ({
id: v.id,
impact: v.impact,
description: v.description,
help: v.help,
helpUrl: v.helpUrl,
wcagCriteria: v.tags.filter(t => t.startsWith('wcag')),
nodes: v.nodes.map(n => ({
target: n.target,
html: n.html,
failureSummary: n.failureSummary
}))
}))
};
if (format === 'html') {
return generateHtmlReport(report);
}
return JSON.stringify(report, null, 2);
}
function generateHtmlReport(report) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Accessibility Report</title>
<style>
body { font-family: -apple-system, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
.violation { border: 1px solid #ddd; margin: 10px 0; padding: 15px; border-radius: 4px; }
.critical { border-left: 4px solid #d32f2f; }
.serious { border-left: 4px solid #f57c00; }
.moderate { border-left: 4px solid #fbc02d; }
.minor { border-left: 4px solid #388e3c; }
.impact { padding: 2px 8px; border-radius: 4px; font-size: 12px; }
h1 { color: #333; }
pre { background: #f5f5f5; padding: 10px; overflow-x: auto; }
</style>
</head>
<body>
<h1>Accessibility Report</h1>
<p>URL: ${report.url}</p>
<p>Generated: ${report.timestamp}</p>
<h2>Summary</h2>
<ul>
<li>Violations: ${report.summary.violations}</li>
<li>Passes: ${report.summary.passes}</li>
<li>Incomplete: ${report.summary.incomplete}</li>
</ul>
<h2>Violations (${report.violations.length})</h2>
${report.violations.map(v => `
<div class="violation ${v.impact}">
<h3>${v.id} <span class="impact">${v.impact}</span></h3>
<p>${v.description}</p>
<p><strong>How to fix:</strong> ${v.help}</p>
<p><a href="${v.helpUrl}" target="_blank">Learn more</a></p>
<p><strong>WCAG:</strong> ${v.wcagCriteria.join(', ')}</p>
<p><strong>Affected elements (${v.nodes.length}):</strong></p>
${v.nodes.map(n => `
<pre>${n.target.join(' > ')}</pre>
<p>${n.failureSummary}</p>
`).join('')}
</div>
`).join('')}
</body>
</html>
`;
}
8. CI/CD Integration
Integrate accessibility testing into pipelines:
# GitHub Actions
name: Accessibility Tests
on: [push, pull_request]
jobs:
a11y:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run accessibility tests
run: npm run test:a11y
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: accessibility-report
path: accessibility-report.html
WCAG Criteria Reference
| Impact | Examples | Priority |
|---|---|---|
| Critical | Missing alt text, missing form labels | P1 - Fix immediately |
| Serious | Low color contrast, missing ARIA | P2 - Fix before release |
| Moderate | Skip link issues, heading order | P3 - Fix soon |
| Minor | Redundant ARIA, best practices | P4 - Backlog |
Common Violations
| Rule ID | Issue | Fix |
|---|---|---|
color-contrast | Insufficient color contrast | Adjust foreground/background colors |
image-alt | Missing image alt text | Add descriptive alt attribute |
label | Form inputs without labels | Add associated label elements |
link-name | Links without accessible names | Add link text or aria-label |
button-name | Buttons without accessible names | Add button text or aria-label |
html-has-lang | Missing lang attribute | Add lang to html element |
region | Content not in landmark | Use semantic elements or ARIA |
MCP Server Integration
This skill can leverage the following MCP servers for enhanced capabilities:
| Server | Description | Installation |
|---|---|---|
| ronantakizawa/a11ymcp | Verified A11y MCP Server | GitHub |
| priyankark/a11y-mcp | axe-core MCP integration | GitHub |
| PashaBoiko/playwright-axe-mcp | Playwright Accessibility MCP | Glama |
| mcp-accessibility-scanner | Playwright + Axe-core scanner | Playbooks |
Best Practices
- Test early - Include a11y tests in development workflow
- Automate continuously - Run a11y tests in CI/CD
- Focus on impact - Prioritize critical and serious issues
- Manual verification - Complement automated tests with manual review
- Screen reader testing - Test with actual assistive technology
- Keyboard navigation - Verify full keyboard accessibility
- Document exceptions - Track and justify any rule exclusions
Process Integration
This skill integrates with the following processes:
accessibility-testing.js- All phases of a11y testinge2e-test-suite.js- A11y integration in E2E testsquality-gates.js- A11y compliance gatescontinuous-testing.js- CI/CD a11y integration
Output Format
When executing operations, provide structured output:
{
"operation": "scan",
"url": "https://example.com",
"wcagLevel": "AA",
"status": "completed",
"summary": {
"violations": 5,
"passes": 42,
"incomplete": 2,
"inapplicable": 15
},
"criticalIssues": [
{
"id": "color-contrast",
"impact": "serious",
"count": 3,
"wcag": "wcag143"
}
],
"reportPath": "./accessibility-report.html",
"compliance": {
"wcag2a": true,
"wcag2aa": false,
"section508": true
}
}
Error Handling
- Handle page load failures gracefully
- Timeout handling for slow pages
- Retry logic for dynamic content
- Fallback for unsupported elements
- Clear error messages for configuration issues
Constraints
- Automated tests cannot catch all accessibility issues
- Manual testing with assistive technology is essential
- Some issues require human judgment
- Document false positive handling
- Consider user testing for complete validation