拓冰建站拓冰建站
首页 / 资讯中心 / 正文

在 Storybook Test Runner 中配置无障碍(a11y)测试:基于 axe-playwright 的完整指南

在 Storybook Test Runner 中配置无障碍a11y测试基于 axe-playwright 的完整指南【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook导读本文围绕 Storybook 官方文档中 Test Runner 的无障碍测试配置片段docs/_snippets/test-runner-a11y-configure.md展开讲解如何通过.storybook/test-runner.js|ts配置文件在 Test Runner 的preVisit/postVisit钩子中注入 axe 引擎、读取 story 级parameters.a11y配置并执行 WCAG 规则检查。读完本文你将掌握在终端与 CI 中自动运行无障碍测试的完整配置方案并能按 story 粒度定制检查规则与检查范围。前置条件Test Runner 与 axe-playwright该配置片段依赖两个关键依赖包storybook/test-runnerStorybook 官方测试运行器基于 Jest 与 Playwright将每个 story 渲染成可执行测试并提供 Test Hook APIprepare、setup、preVisit、postVisit以及getStoryContext等辅助函数。axe-playwright将 Deque 的 axe-core 引擎桥接到 Playwright 页面的工具库提供injectAxe把 axe 注入页面、configureAxe按 axe-core 的axe.configure()语义配置规则、checkA11y在指定元素上执行检查并返回结果三个核心 API。官方文档说明只要安装了 Accessibility 插件并且parameters.a11y.test未设置为offTest Runner 就会在运行交互测试的同时自动纳入无障碍测试参见 Run accessibility tests。本配置片段正是将这一默认行为显式化、精细化的实现模板。配置文件逐行拆解片段提供了 JavaScript 与 TypeScript 两种等价写法目标文件均为 Storybook 目录下的test-runner.js或test-runner.ts。其核心思路是在访问 story 之前注入 axe在 story 渲染完成后读取该 story 的 a11y 参数并执行检查。CommonJS 写法.storybook/test-runner.jsconst { injectAxe, checkA11y, configureAxe } require(axe-playwright); const { getStoryContext } require(storybook/test-runner); module.exports { async preVisit(page) { await injectAxe(page); }, async postVisit(page, context) { // Get the entire context of a story, including parameters, args, argTypes, etc. const storyContext await getStoryContext(page, context); // Apply story-level a11y rules await configureAxe(page, { rules: storyContext.parameters?.a11y?.config?.rules, }); const element storyContext.parameters?.a11y?.element ?? body; await checkA11y(page, element, { detailedReport: true, detailedReportOptions: { html: true, }, }); }, };TypeScript 写法.storybook/test-runner.tsimport type { TestRunnerConfig } from storybook/test-runner; import { getStoryContext } from storybook/test-runner; import { injectAxe, checkA11y, configureAxe } from axe-playwright; const config: TestRunnerConfig { async preVisit(page) { await injectAxe(page); }, async postVisit(page, context) { // Get the entire context of a story, including parameters, args, argTypes, etc. const storyContext await getStoryContext(page, context); // Apply story-level a11y rules await configureAxe(page, { rules: storyContext.parameters?.a11y?.config?.rules, }); const element storyContext.parameters?.a11y?.element ?? body; await checkA11y(page, element, { detailedReport: true, detailedReportOptions: { html: true, }, }); }, }; export default config;两个版本功能完全等价JS 版本导出对象字面量TS 版本通过TestRunnerConfig类型获得类型检查与自动补全。核心逻辑可分为四个步骤步骤钩子/API作用注入引擎preVisit(page)injectAxe(page)在 story 页面访问前把 axe-core 注入浏览器环境读取上下文postVisit(page, context)getStoryContext(page, context)获取完整 story 上下文parameters、args、argTypes 等应用规则configureAxe(page, { rules })把 story 级parameters.a11y.config.rules应用到 axe 配置执行检查checkA11y(page, element, { detailedReport })在指定元素上运行检查并输出详细报告钩子生命周期preVisit 与 postVisit本配置充分利用了 Test Runner 的 Test Hook API。根据 官方文档preVisit与postVisit是异步钩子均接收两个参数Playwright 的page对象以及包含id、title、name的 story context 对象。一次测试的完整执行顺序为setup函数在所有测试前执行一次生成包含所需信息的 context 对象Playwright 导航到 story 页面preVisit函数执行此处注入 axestory 渲染完成并执行 story 中已有的play函数postVisit函数执行此处读取配置并检查无障碍。把injectAxe放在preVisit、把checkA11y放在postVisit的意义在于postVisit执行时 story 已经完整渲染包括异步的play函数已跑完此时审计渲染后的真实 DOM 才能获得最高准确率——这正是浏览器级无障碍测试优于 linter 级检查的原因参见 FAQ。getStoryContext把 story 参数带给 Node 侧getStoryContext(page, context)是storybook/test-runner导出的辅助函数它把浏览器中该 story 的完整上下文parameters、args、argTypes等带回 Node 进程使钩子能够按 story 定制行为。除了本场景官方文档还演示了用它读取 viewport 参数来设置 Playwright 页面尺寸等用途见 Accessing story information with the test-runner。本配置中它解决了规则漂移问题如果只写死一份 axe 配置则所有 story 共享同一套规则无法享受parameters.a11y提供的 story 级粒度。通过getStoryContext读取storyContext.parameters?.a11y?.config?.rules每个 story 定义的个性化规则都能在 Test Runner 中生效。参数溯源parameters.a11y 的完整结构配置中出现的a11y.config与a11y.element均来自 Storybook 的 a11y 参数体系。在仓库源码 code/addons/a11y/src/params.ts 中可以看到A11yParameters接口的完整定义字段类型含义contextaxe-core 的ContextSpec不支持直接传 Node/NodeList传给axe.run的 context决定对哪些元素执行检查默认bodyoptionsaxe-core 的RunOptions传给axe.run的选项如runOnly规则集configaxe-core 的Spec传给axe.configure()的配置最常用于启用/禁用单条规则disableboolean是否禁用无障碍测试testoff \| todo \| error定义违规的处理方式对照 accessibility-testing.mdx 的配置表 可知默认值context默认body、options默认{}、test默认undefined。因此配置片段中的?? body回退与官方默认语义完全一致。config.rulesstory 级规则如何生效在 Story 或 meta 中可为单个 story 定义parameters.a11y.config.rules例如启用或关闭特定规则// 在某个 story 中 export const MyStory { parameters: { a11y: { config: { rules: [ { id: color-contrast, enabled: true }, { id: region, enabled: false }, ], }, }, }, };configureAxe(page, { rules })把这些规则透传给 axe-core 的axe.configure()从而实现每个 story 检查自己的规则集。注意这是按 story 叠加到默认规则之上而非整体替换——测试运行时 Storybook 会把默认禁用的规则见下文与 story 提供的规则合并。element自定义检查范围checkA11y的第二个参数是 axe 的 context 选择器。配置片段将其绑定到parameters.a11y?.element默认回退为body即整页检查。若某个 story 只想检查特定容器可在 story 参数中指定parameters: { a11y: { element: #my-component-root, }, },这与 addon 面板中parameters.a11y.context的语义一脉相承见 Excluded elements例如可通过{ exclude: [.no-a11y-check] }排除无需检查的元素。源码佐证默认规则与上下文合并机制仓库中 a11y 插件的运行实现code/addons/a11y/src/a11yRunner.ts揭示了configureAxe背后 axe 配置的合并逻辑axe.reset(); const configWithDefault { ...config, rules: [...DISABLED_RULES.map((id) ({ id, enabled: false })), ...(config?.rules ?? [])], }; axe.configure(configWithDefault);两点关键信息存在内置禁用规则集合DISABLED_RULESStorybook 默认会关闭部分不适用于 story 场景的规则其中就包括region规则官方文档在 Defaultparameters.a11y.config中说明region规则不适用于 story 中的组件会导致误报因此默认enabled: false。上下文合并在 a11yRunner.ts 中用户提供的context.include会覆盖默认 include而context.exclude会与默认排除项.sb-wrapper、#storybook-docs等 Storybook 内部元素合并。这意味着在 Test Runner 中通过configureAxe传入的规则是追加式覆盖无法撤销默认禁用的规则如需调整规则集例如切换为 WCAG 2.2 AA 或 AAA 规则集应使用options.runOnlyaxe-core 的RunOptions见 Rulesets。这一点在 a11y 插件的测试用例中也有印证code/addons/a11y/src/a11yRunner.test.ts验证了当runOnly存在时被配置禁用的规则仍会传递给axe.run避免被规则集重新启用。运行与验证配置文件就绪后在终端执行yarn test-storybookTest Runner 会遍历所有 story按上述生命周期执行无障碍检查。checkA11y中的detailedReport: true与detailedReportOptions: { html: true }会让失败输出包含违规详情及对应 HTML 片段便于定位问题元素。需要注意的行为边界若parameters.a11y.test设为off该 story 不会执行无障碍检查但 addon 面板仍可手动验证在 CI 中只有test设为error时违规才会导致测试失败设为todo时 CI 不产生错误输出详见 Automate with CI进阶的可选方案是改用 Vitest addon 在 Storybook UI 中运行 a11y 测试两者共享parameters.a11y.test语义off/todo/error参见 Test behavior。推荐工作流渐进式引入无障碍测试结合 官方推荐工作流可在 Test Runner 配置之上设计渐进式策略在.storybook/preview.*中设置parameters.a11y.test error让所有新 story 的无障碍违规直接导致 CI 失败对暂时无法修复的组件在 meta 级别临时标记parameters.a11y.test todo把违规降级为 UI 警告不阻塞开发从 Button 等基础组件开始逐个修复并移除todo标记直到全部 story 通过。这套工作流与本文的配置片段天然互补规则与检查范围由parameters.a11y按 story 定制是否阻断由test字段控制而执行引擎正是本文配置的 Test Runner axe-playwright 组合从而在终端与 CI 中建立可持续的无障碍质量防线。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门