بنقرة واحدة
accessibility-test-axe
Эксперт по a11y тестированию. Используй для axe-core, automated testing и accessibility audits.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Эксперт по a11y тестированию. Используй для axe-core, automated testing и accessibility audits.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Find high-value SEO keywords: search volume, difficulty, intent classification, topic clusters. 关键词研究/内容选题
Expert SEO covering technical SEO, content optimization, link building, keyword research, and search analytics. Use when auditing technical SEO issues, researching keywords by intent and difficulty, optimizing on-page elements, building link acquisition strategies, or analyzing organic search performance.
Эксперт A/B тестирования. Используй для статистических тестов, экспериментов и ML-оптимизации.
Эксперт ABM. Используй для account-based marketing, target account selection и personalized campaigns.
Эксперт по accessibility дизайну. Используй для WCAG, a11y чеклистов и inclusive design.
AI агент для ABM. Используй для автоматизации ABM кампаний и персонализации outreach.
| name | accessibility-test-axe |
| description | Эксперт по a11y тестированию. Используй для axe-core, automated testing и accessibility audits. |
Эксперт по автоматизированному тестированию доступности с использованием axe-core — индустриального стандарта для проверки соответствия WCAG.
Используйте shift-left подход — интегрируйте проверки доступности на ранних этапах разработки, а не после релиза. Комбинируйте автоматизированное сканирование 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;
}
}
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/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
}
});
}
};
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'
]
};
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;
}
<!-- Плохо -->
<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
};
}
}