直接测html片段会漏掉真实交互逻辑,因为html本身无行为,可测组件必须是html+css+js组合体,需验证点击弹窗、禁用态拦截、键盘导航等动态行为;jsdom不触发:focus、不执行布局、不支持intersectionobserver,仅适合字符串渲染测试,无法覆盖用户操作链路。

为什么直接测 HTML 片段会漏掉真实交互逻辑
HTML 本身没有“组件”概念,所谓可测试的模块化组件,必须是 HTML + CSS + JS 组合体,能响应用户操作、更新状态、同步属性。只拿 <div class="card"> 做快照断言,等于在测字符串,而不是测行为——比如点击后是否弹窗、禁用态是否阻止点击、键盘 Tab 是否落到正确位置。
<p>常见错误是用 Jest + jsdom 跑一遍渲染结果就认为“组件通过测试”,但 jsdom 不触发 <code>:focus 样式、不执行 CSS 布局、不模拟 IntersectionObserver,offsetHeight 永远是 0,img.naturalWidth 恒为 0。它适合验证「数据 → 字符串」映射,不适合验证「用户一按回车,按钮变色并提交表单」这个完整链路。
用 Playwright 定位和断言真实行为
Playwright 是目前最贴近真实浏览器行为的轻量级选择,它能在 Chromium/Firefox/WebKit 中运行,支持 Shadow DOM、焦点管理、网络拦截和可访问性树检查。
- 优先用
getByRole()定位,而不是querySelector():比如page.getByRole('button', { name: '提交' })能自动匹配aria-label、title或可见文本,比靠 class 名稳定得多 - 禁用态不能只查
disabled属性:有些组件用class="disabled"或aria-disabled="true",得统一断言await expect(button).toBeDisabled() - 点击后必须等真实反馈:比如
await page.getByRole('dialog').waitFor({ state: 'visible' }),而不是只写await button.click() - 进 Shadow DOM 要显式处理:如果组件用了
attachShadow({ mode: 'open' }),得先取根节点const host = await page.locator('my-card'),再用host.shadowRoot().locator('button')
让组件天生可测:从结构设计开始
测试难,往往是因为组件没预留可测入口。真正可测的 HTML 组件,不是写完再补测试,而是在定义时就注入可观测性。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 每个交互元素必须有明确的
role和可识别的name:按钮要有aria-label或包裹文本;开关控件必须带aria-checked - 避免用纯 class 控制状态:比如
is-loading类名无法被自动化工具感知,改用aria-busy="true"或自定义属性data-state="loading" - 动态内容要留占位或 fallback:比如异步加载的卡片区域,初始状态写
<div data-testid="card-list"><slot></slot></div>,测试时可直接定位该容器 - Web Components 的属性变更必须响应:若组件接受
title属性,需实现static get observedAttributes()并在attributeChangedCallback中同步更新 DOM,否则await component.evaluate(el => el.title)拿到的还是旧值
本地开发时快速验证可访问性与语义完整性
可访问性不是上线前补的 checklist,而是从第一个 <button></button> 就该验证的事。Chrome DevTools 的 Accessibility 面板能当场暴露硬伤,比写测试用例更快发现问题。
- 右键组件 → “Inspect Accessibility Properties”,确认
role、name、state是否完整(例如开关控件缺aria-checked就会被标红) - 用键盘 Tab 导航,观察焦点是否落到预期元素、是否有可见焦点环、是否跳过不可交互内容(比如
div没加tabindex就不该被捕获) - 在 DevTools 中禁用所有样式(Command Menu → “Disable styles”),检查语义结构是否仍清晰:
<h2></h2>不能靠字号区分层级,<nav></nav>里不能混着<button></button> - Shadow DOM 内部的
slot内容若未透传aria-*属性,屏幕阅读器就读不到——得在组件内手动做透传逻辑
真正难的不是写测试代码,而是让组件在无测试框架时也能被人工快速验证:一个 Tab 键、一次鼠标悬停、一次禁用样式,就能看出结构是否健壮。这才是模块化组件落地的关键门槛。










