ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Local Deep Research 无障碍测试指南:WCAG 2.1 AA 与屏幕阅读器兼容性的工程化落地

Local Deep Research 无障碍测试指南:WCAG 2.1 AA 与屏幕阅读器兼容性的工程化落地 Local Deep Research 无障碍测试指南WCAG 2.1 AA 与屏幕阅读器兼容性的工程化落地【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research本指南以 Local Deep ResearchLDR仓库中的 无障碍测试文档 为骨架结合 后端测试、Playwright 合规测试、axe-core 辅助工具 等源码证据系统讲解如何通过自动化手段保障 Web 界面符合 WCAG 2.1 AA 标准、支持屏幕阅读器与纯键盘操作。读者学完后将能够独立运行整套无障碍测试、定位并修复典型的 ARIA/键盘导航缺陷并把无障碍检查无缝接入 CI 流水线。一、测试体系概览双层自动化结构LDR 的 Web 界面无障碍测试采用“JavaScript 端到端 Python 后端结构”双层设计位于 tests/accessibility_tests/ 目录目标是确保研究页、设置页、历史页等核心页面满足 WCAG 2.1 AA 与屏幕阅读器兼容性要求。层入口文件技术栈验证维度前端行为层wcag-compliance.spec.jsPlaywright axe-core/playwright真实浏览器中的 DOM 结构、键盘导航、动态内容 ARIA后端结构层test_accessibility_backend.pypytest BeautifulSoup服务端渲染 HTML 的语义结构、配置与样式两层各有分工Python 层在无浏览器环境下快速校验 HTML 骨架JavaScript 层则在真实浏览器中验证交互行为。辅助文件 axe-helper.js 封装了 axe-core 的公共配置auth-setup.js 负责测试前的登录态准备默认使用test_admin/testpass123测试凭据可通过环境变量覆盖。1.1 JavaScript 测试覆盖范围Playwright 测试重点覆盖四大类能力屏幕阅读器兼容研究模式选择使用真正的input typeradio结构而非 div 模拟校验 ARIA 属性与角色、.sr-only辅助元素、fieldset/legend分组键盘导航Tab 顺序与焦点管理、单选组的方向键Arrow 键切换、Enter/Space 激活、快捷键Enter 提交、ShiftEnter 换行、CtrlEnter 备选提交表单无障碍表单控件标签完整、键盘提示可见、纯键盘可完成表单提交、焦点指示器清晰WCAG 合规通过 axe-core 自动化扫描 color contrast、焦点可见性与语义标记校验。1.2 Python 测试覆盖范围Python 后端测试校验服务端 HTMLHTML 结构表单标签、语义化标记、标题层级、必填字段标记ARIA 实现单选组结构、ARIA 角色与属性、屏幕阅读器支持元素配置与样式html lang属性、viewport meta 标签、CSS 焦点样式、跳转链接skip link、错误提示容器。二、环境准备与运行命令2.1 安装依赖# Python 依赖后端结构测试 pip install pytest beautifulsoup4 requests # Node.js 依赖Playwright 前端测试 npm install playwright playwright/test npx playwright install测试目录 package.json 声明了axe-core/playwright ^4.13.0、playwright/test ^1.63.0与lhci/cli ^0.15.1要求 Node.js22.19并针对yauzl、tmp、lodash、ws等传递依赖配置了安全覆盖overrides。2.2 启动被测应用测试前必须先启动 Web 服务默认地址http://localhost:5000# 方式一仓库根目录启动 python app.py # 方式二以模块方式启动 python -m src.local_deep_research.web.appTEST_BASE_URL环境变量可覆盖被测地址默认http://localhost:5000例如export TEST_BASE_URLhttp://localhost:8080Playwright 测试则读取BASE_URL环境变量wcag-compliance.spec.js 默认同样为http://localhost:5000。2.3 运行 JavaScript 测试# 运行全部无障碍测试 npx playwright test test_accessibility.js # UI 模式调试可视化查看每一步 npx playwright test test_accessibility.js --ui # 按用例名称过滤运行 npx playwright test test_accessibility.js -g mode selection should have proper radio button structure注意README 中示例文件名为test_accessibility.js仓库实际实现为 wcag-compliance.spec.js运行时可替换为实际文件名。2.4 运行 Python 测试# 从 tests 目录运行 cd tests python -m pytest ui_tests/test_accessibility_backend.py -v # 带覆盖率运行 python -m pytest ui_tests/test_accessibility_backend.py --covsrc # 运行单个测试用例 python -m pytest ui_tests/test_accessibility_backend.py::TestHTMLAccessibility::test_radio_button_structure -vREADME 中路径为ui_tests/test_accessibility_backend.py仓库实际文件位于 tests/accessibility_tests/test_accessibility_backend.py按实际路径调整即可。2.5 CI 快速命令# 快速无障碍检查 npm run test:accessibility:quick # 完整无障碍套件 npm run test:accessibility:full # Python 无障碍测试 python -m pytest tests/ui_tests/test_accessibility_backend.py三、axe-core 扫描与 WCAG 合规测试源码级剖析3.1 axe 配置封装axe-helper.js 提供了统一入口import AxeBuilder from axe-core/playwright; // 默认启用 WCAG 2.1/2.2 的 A/AA 标签 const WCAG_TAGS [wcag2a, wcag2aa, wcag21a, wcag21aa, wcag22aa]; export function createAxeBuilder(page, options {}) { const { tags WCAG_TAGS, exclude [], disableRules [] } options; let builder new AxeBuilder({ page }).withTags(tags); exclude.forEach(selector { builder builder.exclude(selector); }); if (disableRules.length 0) { builder builder.disableRules(disableRules); } return builder; }配套提供两个工具函数getCriticalViolations(violations)只筛选critical与serious两个等级的问题axe-helper.js避免被 minor 问题淹没formatViolations(violations)把违规详情影响等级、规则 ID、帮助链接、受影响元素选择器格式化为可读的控制台输出。3.2 全页面扫描用例wcag-compliance.spec.js 对研究页/、历史页/history、设置页/settings三个页面做全量 WCAG 2.1 AA 扫描以串行模式运行const results await createAxeBuilder(page, { disableRules: AXE_DISABLE_RULES }).analyze(); const criticalViolations getCriticalViolations(results.violations); expect(criticalViolations).toHaveLength(0);扫描结果通过test.info().annotations以accessibility-summary类型写入测试输出violations 数量与 passes 数量便于 CI 报表归档。3.3 color-contrast 规则的工程取舍源码中有一条值得注意的工程决策全局禁用了color-contrast规则wcag-compliance.spec.js// Color-contrast is excluded because the default theme (sepia/solarized-light) // has text colors that dont meet WCAG AA 4.5:1 contrast ratios. // This is a systemic theme design issue tracked separately. const AXE_DISABLE_RULES [color-contrast];注释明确说明默认主题sepia/solarized-light的文字颜色未达到 WCAG AA 4.5:1 对比度属于系统性的主题设计问题需单独跟踪而非页面级的局部缺陷。因此测试策略是先在自动化扫描中排除该规则以保证流水线可运行同时将其作为独立议题跟踪修复。这一做法体现了自动化兜底 人工跟进系统性问题的务实分层。3.4 单页面重点断言除全量扫描外研究页还有 7 个细粒度用例wcag-compliance.spec.js标题结构main内恰好 1 个h1标题层级不允许向上跳级如h1后直接h3页面地标landmark至少 1 个main或rolemain至少 1 个nav或rolenavigation表单标签每个非 hidden 的 input/select/textarea 必须有label[for]、包裹型label、aria-label或aria-labelledby之一图片 alt所有img必须有alt或aria-label按钮可访问名称必须有aria-label、aria-labelledby、文本内容或title链接可辨别文本文本、ARIA 名称或内嵌带 alt 的图片至少占其一设置页表单分组每个.form-group/.ldr-form-group内必须包含label或legend。四、键盘导航与动态内容测试4.1 Tab 顺序与焦点可见性导航测试wcag-compliance.spec.js连续按下 10 次 Tab记录每次聚焦元素的 tag/id/class断言焦点至少移动过 2 个不同元素验证 Tab 顺序存在且推进。随后检查聚焦元素的outline、outlineWidth、boxShadow计算样式确认存在可见焦点指示器。这一断言与后端 CSS 相印证仓库的 custom_dropdown.css 为.ldr-mode-option定义了:focus与:focus-visible的outline: 2px solid var(--accent-primary, #6e4ff6); outline-offset: 2px;保证键盘聚焦有清晰可见的视觉反馈。4.2 动态内容的 ARIA 规范警报容器wcag-compliance.spec.js[rolealert]、.alert-container、.ldr-settings-alert-container必须具有rolealert、rolestatus或aria-live之一且aria-live属性可来自祖先元素。这与研究页模板 research.html 中的div idresearch-alert classldr-settings-alert-container rolealert aria-atomictrue一一对应进度条[roleprogressbar]必须同时具备aria-valuenow、aria-valuemin、aria-valuemax三个属性无进度条时用例自动 skip。4.3 自定义下拉框 combobox 结构组件测试wcag-compliance.spec.js验证所有[rolecombobox]必须通过aria-controls指向一个rolelistbox的元素。若目标元素存在则校验其角色不存在时虽不失败但缺失aria-controls本身即视为违规。这正是 ARIA 组合组件combobox → listbox → option的推荐实践。五、Python 后端测试HTML 结构与 ARIA 实现逐用例解析5.1 通用测试夹具test_accessibility_backend.py 通过authenticated_clientfixture 请求/将响应 HTML 交给 BeautifulSoup 解析后供各用例复用。5.2 表单标签与单选组结构test_form_has_proper_labels遍历所有非 hidden/submit/button、非csrf_token的 input/textarea/select凡带id的必须存在对应的label[for]test_radio_button_structure若页面存在typeradio断言其必有name属性且带id时必须有对应labeltest_fieldset_and_legend若存在fieldset每个都必须含legend或aria-label/aria-labelledby若没有 fieldset则要求存在 form-group 类分组或form作为现代 UI 的替代分组方案。这些断言与前端模板 research.html 的实现严格吻合——研究模式选择使用fieldsetlegend 三个带sr-only类的原生 radiofieldset legendResearch Mode/legend input typeradio idmode-quick nameresearch_mode valuequick checked classsr-only ... input typeradio idmode-detailed nameresearch_mode valuedetailed classsr-only ... input typeradio idmode-chat nameresearch_mode valuechat classsr-only ... /fieldset这正是 README 中 Issue #75屏幕阅读器兼容的核心修复用原生 radio 取代 div 模拟的选择器使屏幕阅读器能正确播报选中状态同时保留自定义视觉样式原生控件用.sr-only视觉隐藏。5.3 ARIA 属性与必填字段test_aria_attributes所有 button/a 必须有文本、aria-label或title保证可访问名称test_required_fields_marked带required属性的输入其标签文本须含*或 required 字样或具备 required 类或元素本身带aria-requiredtrue。研究页文本域 research.html 使用aria-requiredtrue即为此规范。5.4 语义化与标题层级test_semantic_markup要求页面至少出现 header/nav/main/footer/section/article 中的一个test_heading_hierarchy要求至少有 1 个h1且标题级别不得跳级h1 → h2 → h3…。后者与前端用例中main 内恰好一个 h1、向上不跳级的规则形成前后端双重校验。5.5 配置与样式类测试TestAccessibilityConfigurationtest_accessibility_backend.py验证CSS 焦点样式请求/static/css/style.css若返回 200 则必须包含:focus、focus-visible或outline无法访问时自动 skip响应式 viewportmeta nameviewport的 content 必须含widthdevice-widthlang 属性html lang必须为en/en-US/en-GB之一——仓库 base.html 使用html langen>queryInput.addEventListener(keydown, function(event) { if (event.key Enter) { if (event.shiftKey) { // ShiftEnter允许默认行为插入换行不做拦截 } else if (event.ctrlKey || event.metaKey) { // CtrlEnter / CmdEnter备选提交方式通用习惯 event.preventDefault(); handleResearchSubmit(new Event(submit)); } else { // 单独 Enter直接提交表单既有行为 event.preventDefault(); handleResearchSubmit(new Event(submit)); } } });对应的键盘提示以.sr-only文本形式渲染在 research.html屏幕阅读器可读出提示视觉用户不受干扰。模式切换的方向键导航README 中Arrow key navigation for radio button groups同样在 research.js 实现监听keydownArrowLeft/ArrowUp选中上一个模式ArrowRight/ArrowDown选中下一个模式并调用selectMode()同步视觉状态与 ARIA 状态。七、浏览器兼容矩阵与测试前置JavaScript 测试在ChromiumChrome/Edge、Firefox、WebKitSafari三种浏览器引擎上运行。不同浏览器对屏幕阅读器 API 的行为存在差异尤其涉及 ARIA 动态播报因此多引擎矩阵是必要的验证手段。wcag-compliance.spec.js 还配置了test.use({ baseURL: BASE_URL, trace: on-first-retry, // 首次失败重试时记录 trace screenshot: only-on-failure, // 仅在失败时截图 });便于 CI 排障。登录态处理auth-setup.js由于多数页面需要登录auth-setup.js 在测试前通过 project setup 任务完成一次登录并把storageState保存到.auth/user.json后续用例直接复用登录态避免重复登录拖慢套件。脚本中值得注意的细节登录超时放宽到 180 秒setup.setTimeout(180_000)注释解释原因冷启动 Docker 时首次登录会创建加密 SQLCipher 数据库、从密码派生密钥并导入 500 默认设置实际等待由内部page.waitForURL(/, { timeout: 120_000 })兜底登录后断言.ldr-user-info可见确保真正进入已登录状态再保存会话。八、常见测试失败与修复方案8.1 单选组结构问题症状找不到 radio 或标签不正确。修复确保模板使用原生input typeradio并配对应label for。参考 research.html 的 fieldset/legend 结构避免用 div 模拟选择器。8.2 ARIA 属性不同步症状aria-checked与实际选中状态不一致。修复检查 research.js 的selectMode()函数——它必须同时更新视觉样式active class与 ARIA 状态aria-checked/checked 属性。8.3 键盘导航失效症状方向键无法切换模式。修复确认事件监听器正确绑定在 research.js 的 mode 元素上且preventDefault()未被遗漏导致页面滚动干扰焦点。8.4 焦点可见性缺失症状Tab 聚焦后看不到焦点指示。修复确认 custom_dropdown.css 中:focus/:focus-visible的outline样式存在且未被outline: none覆盖注意.ldr-custom-dropdown-input:focus { outline: none; }这类局部重置需在组件级别单独补充可见焦点样式。九、手动测试补充建议自动化无法完全替代真实用户感知README 建议至少覆盖以下场景屏幕阅读器实测NVDAWindows、JAWSWindows、VoiceOvermacOS各跑一遍核心流程纯键盘导航断开鼠标仅用 Tab、方向键、Enter/Space 完成一次完整的输入问题 → 选择模式 → 提交研究流程高对比模式Windows 高对比模式下验证焦点指示器仍然可见200% 缩放下验证所有内容在 200% 缩放下仍可访问、不丢功能。十、为新增 UI 功能贡献无障碍测试在添加新 UI 功能时应遵循以下验收清单为功能补充对应的无障碍测试用例正确实现 ARIA 属性角色、状态、labelledby 关联测试键盘导航路径Tab 顺序、方向键、快捷键验证屏幕阅读器兼容性可访问名称、播报内容提交 PR 前完整运行整套无障碍测试套件。后端断言如 test_accessibility_backend.py 中的语义化、标题层级、必填标记可作为新页面模板的结构红线前端 axe 扫描与键盘用例则是行为红线。两层同时通过才能保障新功能不回归 WCAG 2.1 AA 合规状态。十一、最佳实践总结原生优先能用button、input typeradio等原生控件就不用 div 模拟原生控件自带键盘与屏幕阅读器语义自动化分两级后端结构断言负责快速反馈axe-core 扫描负责行为级兜底二者互补系统性问题单独跟踪像 color-contrast 这类主题级的合规缺口应在排除规则的同时登记独立议题避免掩盖问题登录态复用用 storageState 复用会话显著缩短多页面测试耗时多浏览器矩阵屏幕阅读器与键盘行为存在引擎差异Chromium/Firefox/WebKit 三端都必须跑失败可观测开启 trace 与失败截图让 CI 中的无障碍失败可快速定位。通过上述双层测试体系Local Deep Research 得以在持续迭代中守住 WCAG 2.1 AA 与屏幕阅读器兼容性的底线——这正是 无障碍测试文档 及其配套 前端合规测试、后端结构测试 为项目提供的核心价值。【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表