可访问性是使应用程序对每个人都可用的做法。这意味着要确保你的应用程序与辅助技术兼容,支持键盘导航、高色彩对比度模式、减少运动等等。
验证用户界面可及性的最准确方法是在真实设备上进行手动测试。但手动测试需要大量的精力,所以大多数团队使用Axe等自动化工具作为第一道防线。
本文展示了如何用Storybook运行自动可及性测试。你将学习如何配置Storybook测试运行器,在你的所有组件上运行Axe,并对可及性树进行快照:

在编码时测试可及性
在你编码的时候修复可及性问题比在应用部署后修复更容易。像Axe这样的自动化工具通过审计渲染的DOM来工作。这使开发人员能够在构建用户界面时发现并解决缺陷。
Axe根据WCAG规则和其他行业认可的最佳实践进行检查。使用Axe并不能自动使你的用户界面变得无障碍,但它平均可以发现57%的WCAG问题。
Storybook的可及性插件在当前选择的故事上运行Axe,并在可及性面板上将测试结果可视化。它甚至可以勾勒出DOM节点,以帮助你一目了然地指出违规行为。
当在一个组件上工作时,你可以循环浏览它的故事,以验证它的外观和发现可访问性问题。

自动捕捉可访问性的退步
对一个组件的改变可以无意中引入新的可访问性问题。为了捕捉这种回归,你要在打开拉动请求之前测试你的所有故事。
可访问性插件只在你查看故事时运行检查。我们希望通过Storybook测试运行器在所有故事上一次性运行Axe。它是一个独立的工具(由Jest和Playwright提供),用于检查故事中的渲染错误。
让我们继续设置测试运行器并配置它来运行Axe。我们首先安装测试运行器和相关软件包(注意,它需要Storybook 6.4或以上版本):
npm i -D jest @storybook/test-runner axe-playwright
并安装playwright的依赖项:
npx playwright install --with-deps
然后,你可以使用Storybook测试运行器和 axe-playwright将这些可及性测试整合到你的测试自动化管道中。
在你的Storybook目录里面添加一个新的配置文件,里面的内容如下:
// .storybook/test-runner.js
const { injectAxe, checkA11y } = require('axe-playwright');
module.exports = {
async preRender(page, context) {
await injectAxe(page);
},
async postRender(page, context) {
await checkA11y(page, '#root', {
detailedReport: true,
detailedReportOptions: {
html: true,
},
})
},
};
preRender 和 是方便的挂钩,允许你配置测试运行器来执行额外的任务。我们使用这些钩子将Axe注入一个故事中,然后一旦它渲染,就运行可访问性测试。postRender
你会注意到有几个选项被传递到checkA11y 函数中。我们将Axe设置为从故事的根元素开始,然后沿着DOM树向下移动以检查问题。它还会根据遇到的问题生成一份详细的报告,并输出一个违反可访问性规则的HTML元素的列表。
要运行测试,请将测试运行器的脚本添加到你的package.json:
{
"scripts": {
"test-storybook:ci": "yarn test-storybook --maxWorkers=2"
}
}
然后在一个终端窗口中用npm run storybook ,在另一个终端窗口中用npm run test-storybook ,启动你的故事书,测试运行器:

输出测试结果
默认情况下,结果是通过CLI报告的。要导出它们,请切换到getViolations 功能,并使用Node的fs API将它们保存到JSON文件:
// .storybook/test-runner.js
const { injectAxe, getViolations } = require('axe-playwright');
const fs = require('fs');
module.exports = {
setup() {
fs.mkdir(
process.cwd() + '/src/__accessibility__/',
{ recursive: true },
(err) => {
if (err) throw err;
}
);
},
async preRender(page, context) {
await injectAxe(page);
},
async postRender(page, context) {
const violations = await getViolations(page, '#root', {
detailedReport: true,
});
// Do something with violations
// For example, write them to a file
await new Promise((resolve, reject) => {
fs.writeFile(
process.cwd() + `/src/__accessibility__/${context.id}.json`,
JSON.stringify(violations, null, 2),
(err) => {
if (err) reject(err);
resolve();
}
);
});
},
};
对可访问性树进行快照以检查页面结构
盲人和视力受损的用户依靠屏幕阅读器等辅助技术来理解并与你的用户界面互动。浏览器将你的标记转换为一种叫做可及性树的内部表示。这是一种机制,使屏幕阅读器能够解析你的用户界面并将视觉界面翻译成语音。
对可访问性树进行快照有助于你了解用户界面是如何被这些辅助设备解析的。你可以检查页面结构是否正确,内容是否以适当的顺序呈现。更重要的是,在你修改或更新用户界面时,跟踪和扩散这些快照以捕捉倒退的情况:
// .storybook/test-runner.js
const { injectAxe, checkA11y } = require('axe-playwright');
module.exports = {
async preRender(page, context) {
await injectAxe(page);
},
async postRender(page, context) {
await checkA11y(page, '#root', {
detailedReport: true,
detailedReportOptions: {
html: true,
},
});
const accessibilityTree = await page.accessibility.snapshot();
expect(accessibilityTree).toMatchSnapshot();
},
};
结论
在美国,26%的成年人至少有一种残疾。提高可及性可以对你的用户群产生实质性的影响。
自动化的可及性测试作为第一线的QA,可以捕捉到明显的可及性违规。虽然自动化并不能自动使你的用户界面变得无障碍,但它确实通过让你在开发过程中发现问题而缩短了反馈循环。
故事书可及性插件会审核你的故事,并强调违规的DOM节点。一旦你准备好合并,使用Storybook测试运行器对你的所有组件进行检查,以捕捉回归。