Claude-skill-registry accessibility-test-axe
Эксперт по a11y тестированию. Используй для axe-core, automated testing и accessibility audits.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/accessibility-test-axe" ~/.claude/skills/majiayu000-claude-skill-registry-accessibility-test-axe && rm -rf "$T"
manifest:
skills/data/accessibility-test-axe/SKILL.mdsafety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
- references .env files
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content
Axe-Core Accessibility Testing Expert
Эксперт по автоматизированному тестированию доступности с использованием axe-core — индустриального стандарта для проверки соответствия WCAG.
Основная философия
Используйте shift-left подход — интегрируйте проверки доступности на ранних этапах разработки, а не после релиза. Комбинируйте автоматизированное сканирование axe-core с ручным тестированием.
Настройка axe-core
Установка
npm install axe-core @axe-core/playwright @axe-core/react
Базовое использование в браузере
import axe from 'axe-core'; async function runAccessibilityAudit(element = document) { try { const results = await axe.run(element, { runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa', 'wcag21aa'] } }); return { violations: results.violations, passes: results.passes, incomplete: results.incomplete, inapplicable: results.inapplicable }; } catch (error) { console.error('Accessibility audit failed:', error); throw error; } }
Интеграция с Playwright
import { test, expect } from '@playwright/test'; import AxeBuilder from '@axe-core/playwright'; test.describe('Accessibility Tests', () => { test('should not have accessibility violations', async ({ page }) => { await page.goto('/'); const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag21aa']) .analyze(); expect(accessibilityScanResults.violations).toEqual([]); }); test('specific component accessibility', async ({ page }) => { await page.goto('/components/modal'); const results = await new AxeBuilder({ page }) .include('#modal-component') .exclude('.decorative-element') .analyze(); expect(results.violations).toEqual([]); }); });
Интеграция со Storybook
// .storybook/test-runner.js const { injectAxe, checkA11y } = require('axe-playwright'); module.exports = { async preRender(page) { await injectAxe(page); }, async postRender(page) { await checkA11y(page, '#storybook-root', { detailedReport: true, detailedReportOptions: { html: true } }); } };
CI/CD интеграция (GitHub Actions)
name: Accessibility Tests on: [push, pull_request] jobs: a11y: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Install Playwright run: npx playwright install --with-deps - name: Run accessibility tests run: npm run test:a11y - name: Upload results if: failure() uses: actions/upload-artifact@v3 with: name: a11y-report path: a11y-results.json
Обработка результатов
function processViolations(violations) { const report = { critical: [], serious: [], moderate: [], minor: [] }; violations.forEach(violation => { const issue = { id: violation.id, impact: violation.impact, description: violation.description, help: violation.help, helpUrl: violation.helpUrl, nodes: violation.nodes.map(node => ({ html: node.html, target: node.target, failureSummary: node.failureSummary })) }; report[violation.impact].push(issue); }); return report; }
Конфигурация правил
const axeConfig = { rules: [ // Отключение правил для декоративных элементов { id: 'image-alt', enabled: true }, { id: 'color-contrast', enabled: true }, { id: 'label', enabled: true }, // Исключения для специфичных случаев { id: 'button-name', selector: 'button:not(.icon-only)' } ], // Исключение областей exclude: [ '.third-party-widget', '#ads-container' ] };
React интеграция
import React from 'react'; import ReactDOM from 'react-dom'; import axe from '@axe-core/react'; if (process.env.NODE_ENV !== 'production') { axe(React, ReactDOM, 1000); } // Компонент отчёта function AccessibilityReport({ violations }) { if (!violations.length) { return <div className="a11y-pass">No accessibility violations found</div>; } return ( <div className="a11y-violations" role="alert"> <h2>Accessibility Issues Found: {violations.length}</h2> <ul> {violations.map(violation => ( <li key={violation.id}> <strong>{violation.impact}</strong>: {violation.description} <a href={violation.helpUrl} target="_blank" rel="noopener"> Learn more </a> </li> ))} </ul> </div> ); }
Типичные нарушения и исправления
Недостаточный контраст цвета
/* Плохо */ .text-light { color: #999; background: #fff; } /* Хорошо - соотношение 4.5:1 */ .text-light { color: #767676; background: #fff; }
Отсутствие label у формы
<!-- Плохо --> <input type="email" placeholder="Email"> <!-- Хорошо --> <label for="email">Email</label> <input type="email" id="email" placeholder="email@example.com">
Кнопка без текста
<!-- Плохо --> <button><svg>...</svg></button> <!-- Хорошо --> <button aria-label="Close menu"> <svg aria-hidden="true">...</svg> </button>
Мониторинг и отчётность
class AccessibilityMonitor { constructor() { this.history = []; } async audit(url) { const results = await runAccessibilityAudit(); this.history.push({ timestamp: new Date().toISOString(), url, violationCount: results.violations.length, violations: results.violations }); return this.generateTrend(); } generateTrend() { const recent = this.history.slice(-10); return { current: recent[recent.length - 1]?.violationCount || 0, trend: this.calculateTrend(recent), history: recent }; } }
Лучшие практики
- Интегрируйте в CI/CD — блокируйте merge при critical нарушениях
- Тестируйте рано — используйте в dev режиме React/Vue
- Комбинируйте методы — автоматические тесты + ручное тестирование
- Документируйте исключения — объясняйте почему правило отключено
- Отслеживайте тренды — мониторьте количество нарушений во времени