From 6c2f51fc1d1b550c2bdc646abb1137ba56da8e59 Mon Sep 17 00:00:00 2001 From: wehub-skill-sync Date: Mon, 13 Jul 2026 21:37:15 +0800 Subject: [PATCH] chore: import zh skill screen-reader-testing --- README.wehub.md | 9 + SKILL.md | 538 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 547 insertions(+) create mode 100644 README.wehub.md create mode 100644 SKILL.md diff --git a/README.wehub.md b/README.wehub.md new file mode 100644 index 0000000..6acd535 --- /dev/null +++ b/README.wehub.md @@ -0,0 +1,9 @@ +# WeHub 来源说明 + +- Skill 名称:`screen-reader-testing` +- 中文类目:屏幕阅读器与设计指南 +- 上游仓库:`wshobson__agents` +- 上游路径:`plugins/accessibility-compliance/skills/screen-reader-testing/SKILL.md` +- 上游链接:https://github.com/wshobson/agents/blob/HEAD/plugins/accessibility-compliance/skills/screen-reader-testing/SKILL.md +- 本仓库为 WeHub 中文 Skill 汉化包,基于 skill 市场筛选 Top200 清单整理 +- 原作者、版权和许可证信息以上游仓库为准 diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..8fc943d --- /dev/null +++ b/SKILL.md @@ -0,0 +1,538 @@ +--- +name: screen-reader-testing +description: 使用屏幕阅读器(包括 VoiceOver、NVDA 和 JAWS)测试 Web 应用程序。适用于验证屏幕阅读器兼容性、调试无障碍问题或确保辅助技术支持。 +--- + +# 屏幕阅读器测试 + +使用屏幕阅读器测试 Web 应用程序的实用指南,用于全面的无障碍验证。 + +## 何时使用本技能 + +- 验证屏幕阅读器兼容性 +- 测试 ARIA 实现 +- 调试辅助技术问题 +- 验证表单无障碍性 +- 测试动态内容播报 +- 确保导航无障碍性 + +## 核心概念 + +### 1. 主流屏幕阅读器 + +| 屏幕阅读器 | 平台 | 浏览器 | 使用占比 | +| -------------- | ---------- | ------------------- | -------- | +| **VoiceOver** | macOS/iOS | Safari | ~15% | +| **NVDA** | Windows | Firefox/Chrome | ~31% | +| **JAWS** | Windows | Chrome/IE | ~40% | +| **TalkBack** | Android | Chrome | ~10% | +| **Narrator** | Windows | Edge | ~4% | + +### 2. 测试优先级 + +``` +最低覆盖: +1. NVDA + Firefox(Windows) +2. VoiceOver + Safari(macOS) +3. VoiceOver + Safari(iOS) + +全面覆盖: ++ JAWS + Chrome(Windows) ++ TalkBack + Chrome(Android) ++ Narrator + Edge(Windows) +``` + +### 3. 屏幕阅读器模式 + +| 模式 | 用途 | 使用场景 | +| ---------------------- | -------------- | ------------------ | +| **浏览/虚拟** | 阅读内容 | 默认阅读 | +| **焦点/表单** | 与控件交互 | 填写表单 | +| **应用程序** | 自定义微件 | ARIA 应用程序 | + +## VoiceOver(macOS) + +### 设置 + +``` +启用:系统设置 → 辅助功能 → VoiceOver +开关:Cmd + F5 +快速开关:三按 Touch ID +``` + +### 常用命令 + +``` +导航: +VO = Ctrl + Option(VoiceOver 修饰键) + +VO + 右箭头键 下一个元素 +VO + 左箭头键 上一个元素 +VO + Shift + 下箭头键 进入群组 +VO + Shift + 上箭头键 退出群组 + +阅读: +VO + A 从光标处开始朗读所有内容 +Ctrl 停止朗读 +VO + B 朗读当前段落 + +交互: +VO + Space 激活元素 +VO + Shift + M 打开菜单 +Tab 下一个可聚焦元素 +Shift + Tab 上一个可聚焦元素 + +转子(VO + U): +按以下类别导航:标题、链接、表单、地标 +左/右箭头键 切换转子类别 +上/下箭头键 在类别内导航 +Enter 跳转到项目 + +网页专用: +VO + Cmd + H 下一个标题 +VO + Cmd + J 下一个表单控件 +VO + Cmd + L 下一个链接 +VO + Cmd + T 下一个表格 +``` + +### 测试清单 + +```markdown +## VoiceOver 测试清单 + +### 页面加载 + +- [ ] 页面标题已播报 +- [ ] 找到主要地标 +- [ ] 跳过链接可用 + +### 导航 + +- [ ] 所有标题可通过转子发现 +- [ ] 标题层级合理(H1 → H2 → H3) +- [ ] 地标已正确标注 +- [ ] 跳过链接功能正常 + +### 链接与按钮 + +- [ ] 链接用途清晰 +- [ ] 按钮操作已描述 +- [ ] 新窗口/标签页已播报 + +### 表单 + +- [ ] 所有标签随输入框一并朗读 +- [ ] 必填字段已播报 +- [ ] 错误信息已朗读 +- [ ] 操作指引可用 +- [ ] 焦点移至错误处 + +### 动态内容 + +- [ ] 弹窗立即播报 +- [ ] 加载状态已传达 +- [ ] 内容更新已播报 +- [ ] 模态框正确锁定焦点 + +### 表格 + +- [ ] 表头与单元格关联 +- [ ] 表格导航正常 +- [ ] 复杂表格有标题 +``` + +### 常见问题与修复 + +```html + + + + + + + +
新结果已加载
+ + +
新结果已加载
+ + + +无效的电子邮件 + + + +无效的电子邮件 +``` + +## NVDA(Windows) + +### 设置 + +``` +下载:nvaccess.org +启动:Ctrl + Alt + N +停止:Insert + Q +``` + +### 常用命令 + +``` +导航: +Insert = NVDA 修饰键 + +下箭头键 下一行 +上箭头键 上一行 +Tab 下一个可聚焦元素 +Shift + Tab 上一个可聚焦元素 + +阅读: +NVDA + 下箭头键 朗读全部 +Ctrl 停止语音 +NVDA + 上箭头键 当前行 + +标题: +H 下一个标题 +Shift + H 上一个标题 +1-6 标题级别 1-6 + +表单: +F 下一个表单字段 +B 下一个按钮 +E 下一个编辑框 +X 下一个复选框 +C 下一个组合框 + +链接: +K 下一个链接 +U 下一个未访问链接 +V 下一个已访问链接 + +地标: +D 下一个地标 +Shift + D 上一个地标 + +表格: +T 下一个表格 +Ctrl + Alt + 箭头键 导航单元格 + +元素列表(NVDA + F7): +显示所有链接、标题、表单字段、地标 +``` + +### 浏览模式与焦点模式 + +``` +NVDA 自动切换模式: +- 浏览模式:箭头键导航内容 +- 焦点模式:箭头键控制交互元素 + +手动切换:NVDA + Space + +注意观察: +- 导航时听到「浏览模式」提示 +- 进入表单字段时听到「焦点模式」 +- application 角色强制进入表单模式 +``` + +### 测试脚本 + +```markdown +## NVDA 测试脚本 + +### 初始加载 + +1. 导航到页面 +2. 等待页面加载完成 +3. 按 Insert + 下箭头键朗读全部内容 +4. 注意:页面标题、主要内容是否已识别? + +### 地标导航 + +1. 反复按 D +2. 检查:所有主要区域是否可达? +3. 检查:地标是否已正确标注? + +### 标题导航 + +1. 按 Insert + F7 → 标题 +2. 检查:标题结构是否合理? +3. 按 H 导航标题 +4. 检查:所有章节是否可发现? + +### 表单测试 + +1. 按 F 找到第一个表单字段 +2. 检查:标签是否朗读? +3. 输入无效数据 +4. 提交表单 +5. 检查:错误是否已播报? +6. 检查:焦点是否移至错误处? + +### 交互元素 + +1. 用 Tab 遍历所有交互元素 +2. 检查:每个元素是否播报角色和状态 +3. 用 Enter/Space 激活按钮 +4. 检查:结果是否已播报? + +### 动态内容 + +1. 触发内容更新 +2. 检查:变化是否已播报? +3. 打开模态框 +4. 检查:焦点是否锁定? +5. 关闭模态框 +6. 检查:焦点是否返回? +``` + +## JAWS(Windows) + +### 常用命令 + +``` +启动:桌面快捷方式或 Ctrl + Alt + J +虚拟光标:浏览器中自动启用 + +导航: +箭头键 导航内容 +Tab 下一个可聚焦元素 +Insert + 下箭头键 朗读全部 +Ctrl 停止语音 + +快速键: +H 下一个标题 +T 下一个表格 +F 下一个表单字段 +B 下一个按钮 +G 下一个图形 +L 下一个列表 +; 下一个地标 + +表单模式: +Enter 进入表单模式 +Numpad + 退出表单模式 +F5 列出表单字段 + +列表: +Insert + F7 链接列表 +Insert + F6 标题列表 +Insert + F5 表单字段列表 + +表格: +Ctrl + Alt + 箭头键 表格导航 +``` + +## TalkBack(Android) + +### 设置 + +``` +启用:设置 → 辅助功能 → TalkBack +开关:同时按住两个音量键 3 秒 +``` + +### 手势 + +``` +探索:在屏幕上拖动手指 +下一个:向右滑动 +上一个:向左滑动 +激活:双击 +滚动:双指滑动 + +阅读控制(向上滑动再向右): +- 标题 +- 链接 +- 控件 +- 字符 +- 单词 +- 行 +- 段落 +``` + +## 常见测试场景 + +### 1. 模态对话框 + +```html + +
+

确认删除

+

此操作不可撤销。

+ + +
+``` + +```javascript +// 焦点管理 +function openModal(modal) { + // 保存最后聚焦的元素 + lastFocus = document.activeElement; + + // 将焦点移到模态框 + modal.querySelector("h2").focus(); + + // 锁定焦点 + modal.addEventListener("keydown", trapFocus); +} + +function closeModal(modal) { + // 恢复焦点 + lastFocus.focus(); +} + +function trapFocus(e) { + if (e.key === "Tab") { + const focusable = modal.querySelectorAll( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])', + ); + const first = focusable[0]; + const last = focusable[focusable.length - 1]; + + if (e.shiftKey && document.activeElement === first) { + last.focus(); + e.preventDefault(); + } else if (!e.shiftKey && document.activeElement === last) { + first.focus(); + e.preventDefault(); + } + } + + if (e.key === "Escape") { + closeModal(modal); + } +} +``` + +### 2. 动态区域 + +```html + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+``` + +### 3. 标签页界面 + +```html +
+ + +
+ +
+ 产品描述内容... +
+ + +``` + +```javascript +// 标签页键盘导航 +tablist.addEventListener("keydown", (e) => { + const tabs = [...tablist.querySelectorAll('[role="tab"]')]; + const index = tabs.indexOf(document.activeElement); + + let newIndex; + switch (e.key) { + case "ArrowRight": + newIndex = (index + 1) % tabs.length; + break; + case "ArrowLeft": + newIndex = (index - 1 + tabs.length) % tabs.length; + break; + case "Home": + newIndex = 0; + break; + case "End": + newIndex = tabs.length - 1; + break; + default: + return; + } + + tabs[newIndex].focus(); + activateTab(tabs[newIndex]); + e.preventDefault(); +}); +``` + +## 调试技巧 + +```javascript +// 记录屏幕阅读器所看到的内容 +function logAccessibleName(element) { + const computed = window.getComputedStyle(element); + console.log({ + role: element.getAttribute("role") || element.tagName, + name: + element.getAttribute("aria-label") || + element.getAttribute("aria-labelledby") || + element.textContent, + state: { + expanded: element.getAttribute("aria-expanded"), + selected: element.getAttribute("aria-selected"), + checked: element.getAttribute("aria-checked"), + disabled: element.disabled, + }, + visible: computed.display !== "none" && computed.visibility !== "hidden", + }); +} +``` + +## 最佳实践 + +### 应做事项 + +- **使用真实的屏幕阅读器进行测试**——而不仅仅是模拟器 +- **优先使用语义化 HTML**——ARIA 是补充手段 +- **在浏览模式和焦点模式下分别测试**——体验不同 +- **验证焦点管理**——尤其是单页应用 +- **先测试纯键盘操作**——这是屏幕阅读器测试的基础 + +### 不应做事项 + +- **不要认为一个屏幕阅读器就够了**——请测试多个 +- **不要忽略移动端**——用户群体在持续增长 +- **不要只测试正常流程**——也要测试错误状态 +- **不要跳过动态内容**——这是最常见的问题来源 +- **不要依赖视觉测试**——用户体验完全不同