直接用 document.queryselectorall 测结构会失败,因浏览器对非法或省略标签的容错策略不同,导致同一 html 在 chrome、firefox、safari 中解析出的 dom 树结构不一致,使单元测试断言必然失败。

为什么直接用 document.querySelectorAll 测结构会失败
浏览器对非法或省略标签的容错策略不同,导致同一段 HTML 字符串在 Chrome、Firefox、Safari 中解析出的 DOM 树结构可能不一致。比如 <div><p>text</p></div>(<p></p> 没闭合且被 截断),Chrome 会自动补全
<div>,Safari 可能直接丢弃后续节点,Firefox 甚至拒绝插入。此时 <code>document.querySelectorAll('p') 返回长度在各引擎中不等——单元测试断言必然失败。
- 所有测试必须基于验证通过的 HTML:跑一次
https://validator.w3.org/,修复 “End tag for element X implied” 类警告 - 禁止依赖自动闭合:显式写出
<li>、<tr></tr>、<tbody></tbody>,哪怕规范允许省略 - 语义标签如
<main></main>、<section></section>必须有明确块级上下文,别直接塞进<p></p>或<span></span>里
如何用 template 元素做跨引擎结构快照比对
<template></template> 是唯一能绕过浏览器实时解析差异的原生机制:它不渲染、不执行脚本、不加载资源,只存原始字符串结构。把待测 HTML 写进 <template></template>,再用 content.cloneNode(true) 获取纯净副本,就能在所有引擎中得到完全一致的初始 DOM 节点树。
- 测试时不要用
innerHTML = htmlStr注入,改用template.innerHTML = htmlStr→document.importNode(template.content, true) - 对表格结构,必须确保
<template></template>内已含<tbody></tbody>,JS 渲染逻辑只操作该节点,不碰<table> 直接子节点 <li>比对前调用 <code>el.normalize()合并相邻文本节点,避免因换行/空格处理差异导致textContent不一致 - 结构测试只比对节点类型、属性、层级、文本内容,不读取 layout 相关属性(
offsetWidth、clientHeight等) - 若需验证样式生效,用
window.getComputedStyle(el).minWidth,而不是依赖 JS 动态设置el.style.minWidth = '0'—— Safari 可能在计算前就完成了错误布局 - 对 Flex 子项,把
min-width: 0、flex-shrink: 1等 fix 写死在<template></template>的内联 style 里,而非靠测试脚本 patch - 共用测试用例的 HTML 必须剔除
<script></script>、<style></style>、<link>和事件属性(onclick、oninput等) - 用小程序支持的内联样式替代 CSS 类:所有样式写进
style=""属性,避免依赖外部样式表或 class 名映射 - 测试前先用正则或 DOMParser 预处理 HTML 字符串,移除小程序不识别的标签和属性,再注入
<template></template>
Flexbox 布局在 Safari 14–15 的结构测试陷阱
Safari 14–15 对 display: flex 子项的默认 min-width 计算有 bug,但这个 bug 发生在布局阶段,不影响 DOM 结构本身——所以结构单元测试不会暴露它。但如果你在测试中顺带检查 getBoundingClientRect() 或 offsetWidth,就会在 Safari 上拿到错误值,误判为“结构异常”。
微信小程序与 H5 共用 HTML 单元测试的关键约束
小程序 WebView 引擎(X5)和 H5 浏览器(Blink/WebKit)对 HTML 解析规则基本一致,但小程序运行时会过滤掉部分标签(如 <script></script>、<style></style>)和属性(如 onload)。直接拿 H5 的 HTML 字符串跑小程序测试,可能因标签被静默移除导致结构不匹配。
data-* 属性访问限制,都得靠独立的视觉回归或行为测试覆盖。











