axe-accessibilitySkill axe-accessibility

axe-accessibility技能是专门用于网站和Web应用无障碍性测试的工具,集成了axe-core库,能够自动执行无障碍性扫描,解释WCAG违规行为,生成合规性报告,并与主流测试框架集成,是保障网站可达性的重要工具。

测试 0 次安装 0 次浏览 更新于 2/25/2026

axe-accessibility

你是 axe-accessibility - 一个专门用于axe-core无障碍测试集成的特殊技能,提供全面的WCAG合规性验证能力。

概览

这个技能使得AI驱动的无障碍测试成为可能,包括:

  • 执行axe-core无障碍扫描
  • 解释WCAG违规和影响
  • 生成无障碍合规性报告
  • 配置规则包含/排除
  • 与Playwright/Cypress集成进行自动化a11y测试
  • 处理动态内容扫描
  • 将违规行为映射到WCAG标准
  • 提供补救指导

前提条件

  • Node.js环境用于axe-core
  • 测试自动化框架(Playwright,Cypress或Selenium)
  • 浏览器自动化能力
  • 可选:axe-playwright或axe-cypress包

能力

1. Playwright集成

使用axe-core与Playwright进行无障碍测试:

import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';

test.describe('无障碍测试', () => {
  test('首页不应有违规行为', async ({ page }) => {
    await page.goto('https://example.com');

    const accessibilityScanResults = await new AxeBuilder({ page }).analyze();

    expect(accessibilityScanResults.violations).toEqual([]);
  });

  test('首页不应有严重违规行为', 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('表单页面无障碍性', async ({ page }) => {
    await page.goto('https://example.com/contact');

    // 等待表单完全加载
    await page.waitForSelector('form');

    const results = await new AxeBuilder({ page })
      .include('form')
      .analyze();

    // 日志违规行为以供调试
    if (results.violations.length > 0) {
      console.log('发现违规行为:', JSON.stringify(results.violations, null, 2));
    }

    expect(results.violations).toEqual([]);
  });
});

2. Cypress集成

使用axe-core与Cypress:

// cypress/support/commands.js
import 'cypress-axe';

// cypress/e2e/accessibility.cy.js
describe('无障碍测试', () => {
  beforeEach(() => {
    cy.visit('/');
    cy.injectAxe();
  });

  it('加载时没有可检测到的无障碍违规行为', () => {
    cy.checkA11y();
  });

  it('主要内容中没有违规行为', () => {
    cy.checkA11y('#main-content');
  });

  it('没有严重违规行为', () => {
    cy.checkA11y(null, {
      includedImpacts: ['critical', 'serious']
    });
  });

  it('记录违规行为以供审查', () => {
    cy.checkA11y(null, null, (violations) => {
      violations.forEach((violation) => {
        cy.log(`${violation.id}: ${violation.description}`);
        violation.nodes.forEach((node) => {
          cy.log(`  - ${node.target}`);
        });
      });
    }, true);
  });
});

3. 独立的axe-core使用

直接axe-core使用:

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);

  // 注入axe-core
  await page.addScriptTag({ path: require.resolve('axe-core') });

  // 运行分析
  const results = await page.evaluate(async () => {
    return await axe.run();
  });

  await browser.close();
  return results;
}

// 使用
const results = await runAccessibilityAudit('https://example.com');
console.log`发现 ${results.violations.length} 违规行为');

4. WCAG合规性配置

为特定WCAG标准配置axe:

import AxeBuilder from '@axe-core/playwright';

// WCAG 2.1 Level AA合规性
const wcag21AAResults = await new AxeBuilder({ page })
  .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
  .analyze();

// WCAG 2.2 Level AA合规性
const wcag22AAResults = await new AxeBuilder({ page })
  .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
  .analyze();

// Section 508合规性
const section508Results = await new AxeBuilder({ page })
  .withTags(['section508'])
  .analyze();

// 最佳实践(不严格合规)
const bestPracticesResults = await new AxeBuilder({ page })
  .withTags(['best-practice'])
  .analyze();

5. 规则配置

包含/排除特定规则:

import AxeBuilder from '@axe-core/playwright';

const results = await new AxeBuilder({ page })
  // 只包含特定规则
  .withRules(['color-contrast', 'image-alt', 'label', 'link-name'])
  .analyze();

// 或排除规则
const resultsExcluding = await new AxeBuilder({ page })
  .disableRules(['region', 'landmark-one-main'])
  .analyze();

// 专注于特定元素
const formResults = await new AxeBuilder({ page })
  .include('#contact-form')
  .analyze();

// 排除有问题的区域
const mainResults = await new AxeBuilder({ page })
  .exclude('#third-party-widget')
  .analyze();

6. 违规行为分析

分析和分类违规行为:

function analyzeViolations(results) {
  const summary = {
    total: results.violations.length,
    byImpact: {},
    byWCAG: {},
    criticalIssues: []
  };

  for (const violation of results.violations) {
    // 按影响计数
    summary.byImpact[violation.impact] =
      (summary.byImpact[violation.impact] || 0) + violation.nodes.length;

    // 按WCAG标准计数
    for (const tag of violation.tags) {
      if (tag.startsWith('wcag')) {
        summary.byWCAG[tag] = (summary.byWCAG[tag] || 0) + 1;
      }
    }

    // 收集严重问题
    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. 报告生成

生成无障碍报告:

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>无障碍报告</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>无障碍报告</h1>
  <p>URL: ${report.url}</p>
  <p>生成: ${report.timestamp}</p>

  <h2>摘要</h2>
  <ul>
    <li>违规行为: ${report.summary.violations}</li>
    <li>通过: ${report.summary.passes}</li>
    <li>不完整: ${report.summary.incomplete}</li>
  </ul>

  <h2>违规行为 (${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>如何修复:</strong> ${v.help}</p>
      <p><a href="${v.helpUrl}" target="_blank">了解更多</a></p>
      <p><strong>WCAG:</strong> ${v.wcagCriteria.join(', ')}</p>
      <p><strong>受影响元素 (${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集成

将无障碍测试集成到流程中:

# GitHub Actions
name: 无障碍测试

on: [push, pull_request]

jobs:
  a11y:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: 设置Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: 安装依赖
        run: npm ci

      - name: 安装Playwright浏览器
        run: npx playwright install --with-deps

      - name: 运行无障碍测试
        run: npm run test:a11y

      - name: 上传报告
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: accessibility-report
          path: accessibility-report.html

WCAG标准参考

影响 示例 优先级
严重 缺少alt文本,缺少表单标签 P1 - 立即修复
严重 低对比度颜色,缺少ARIA P2 - 发布前修复
中等 跳过链接问题,标题顺序 P3 - 尽快修复
轻微 多余的ARIA,最佳实践 P4 - 待办事项

常见违规行为

规则ID 问题 修复
color-contrast 颜色对比度不足 调整前景/背景颜色
image-alt 缺少图像alt文本 添加描述性alt属性
label 表单输入缺少标签 添加相关联的标签元素
link-name 链接没有可访问名称 添加链接文本或aria-label
button-name 按钮没有可访问名称 添加按钮文本或aria-label
html-has-lang 缺少lang属性 在html元素上添加lang
region 内容不在地标中 使用语义元素或ARIA

MCP服务器集成

这个技能可以利用以下MCP服务器增强能力:

服务器 描述 安装
ronantakizawa/a11ymcp 经过验证的A11y MCP服务器 GitHub
priyankark/a11y-mcp axe-core MCP集成 GitHub
PashaBoiko/playwright-axe-mcp Playwright无障碍MCP Glama
mcp-accessibility-scanner Playwright + Axe-core扫描器 Playbooks

最佳实践

  1. 早期测试 - 在开发工作流程中包含a11y测试
  2. 持续自动化 - 在CI/CD中运行a11y测试
  3. 关注影响 - 优先处理严重和严重问题
  4. 手动验证 - 用手动审查补充自动化测试
  5. 屏幕阅读器测试 - 用实际辅助技术进行测试
  6. 键盘导航 - 验证完整的键盘可访问性
  7. 记录例外 - 跟踪并证明任何规则排除

流程集成

这个技能与以下流程集成:

  • accessibility-testing.js - a11y测试的所有阶段
  • e2e-test-suite.js - E2E测试中a11y集成
  • quality-gates.js - a11y合规性门
  • continuous-testing.js - CI/CD a11y集成

输出格式

执行操作时,提供结构化输出:

{
  "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
  }
}

错误处理

  • 优雅地处理页面加载失败
  • 慢速页面的超时处理
  • 动态内容的重试逻辑
  • 不支持元素的回退
  • 配置问题清晰的错误信息

限制

  • 自动化测试不能捕获所有无障碍问题
  • 使用辅助技术进行手动测试是必要的
  • 一些问题需要人类判断
  • 文档处理误报
  • 考虑用户测试以获得完整验证