Playwright 集成 axe-core 做无障碍回归与 CI 断言
问题场景
无障碍回归常见问题是人工检查成本高、动态组件容易漏检。目标是在 Playwright 测试中,页面加载后注入 axe-core,运行 axe.run,只把 impact 为 serious 或 critical 的违规视为阻塞;断言阻塞列表为空,失败时输出违规节点选择器和帮助链接,便于定位。
最小可运行示例
安装依赖并准备浏览器:
npm init -y
npm i -D @playwright/test axe-core http-server
npx playwright install chromium
创建最小页面 index.html。示例按钮带 aria-label,因此默认应通过;移除 aria-label 后,axe 会报告按钮可访问名称问题,可用于观察失败输出。
<!doctype html>
<html lang='zh-CN'>
<head>
<meta charset='utf-8'>
<title>无障碍回归示例</title>
</head>
<body>
<main>
<h1>示例页面</h1>
<button aria-label='关闭提示'><span aria-hidden='true'>×</span></button>
<div data-a11y-ignore>第三方控件占位</div>
</main>
</body>
</html>
playwright.config.js 使用本地静态服务器,并把 baseURL 指向它:
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
use: { baseURL: 'http://127.0.0.1:4173' },
webServer: {
command: 'npx http-server . -p 4173 -c-1',
url: 'http://127.0.0.1:4173',
reuseExistingServer: true,
},
});
测试文件 tests/a11y.spec.js 在页面加载后注入 axe,运行 axe.run,并格式化阻塞违规:
const { test, expect } = require('@playwright/test');
const AXE_PATH = require.resolve('axe-core/axe.min.js');
test.describe('无障碍回归', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
await page.addScriptTag({ path: AXE_PATH });
await page.waitForLoadState('networkidle');
});
test('无 serious/critical 违规', async ({ page }) => {
const results = await page.evaluate(async () => {
const context = {
exclude: [['[data-a11y-ignore]']],
};
const options = {
resultTypes: ['violations'],
rules: {
// 仅当第三方组件已有书面无障碍声明时,才考虑禁用对应规则
// 'color-contrast': { enabled: false },
},
};
return await axe.run(context, options);
});
const blocking = results.violations
.filter(v => ['serious', 'critical'].includes(v.impact))
.map(v => ({
id: v.id,
impact: v.impact,
help: v.help,
helpUrl: v.helpUrl,
nodes: v.nodes.map(n => ({
target: n.target.join(' '),
summary: n.failureSummary,
})),
}));
if (blocking.length > 0) {
console.error(JSON.stringify(blocking, null, 2));
}
expect(blocking).toEqual([]);
});
});
运行方法:在项目根目录执行 npm install 生成锁文件,执行 npx playwright test。测试会自动启动 4173 端口。若移除按钮的 aria-label,测试失败并打印包含 target 与 helpUrl 的阻塞项。
排除规则与注入说明
示例通过 page.addScriptTag 注入本地 axe-core/axe.min.js,不依赖外部 CDN。exclude: [['[data-a11y-ignore]']] 只排除明确标记的第三方容器;排除范围应尽量小,并在代码评审中记录原因。禁用规则只作为最后手段,不要关闭 serious/critical 相关规则。若页面有严格 CSP,注入可能受限,应优先使用测试环境允许的脚本注入方式。
CI 最小示例
首次本地 npm install 后提交 package-lock.json,CI 使用 npm ci:
name: a11y
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx playwright test
边界与限制
axe-core 只能覆盖可自动检测的规则,不能替代键盘走查、屏幕阅读器测试和人工评审;impact 是启发式等级,过滤 serious/critical 会漏掉 moderate 问题。示例仅分析主文档,跨域 iframe、Shadow DOM 和动态异步内容需要单独等待与注入策略,networkidle 不宜作为唯一等待条件。第三方排除项和规则禁用应定期复核,axe-core 版本应锁定,CI 环境需安装浏览器依赖。
- 点赞
- 收藏
- 关注作者
评论(0)