短短几周内,我们的网站连续两次陷入同样的怪状:页面能正常加载,设计完好,控制台没有任何报错,可所有链接都点击无效。严格来说,这并不是一段“错误代码”引发的故障,而是浏览器忠实执行了某个设计本意,只是它作用在了远比预期更大的范围上。更令人后怕的是,自动化测试在这两次事故中都顺利通过了。

第一次事故的源头是一款智能助手组件。我们开启了一个设置:访客一进入页面,聊天窗口就自动弹出。结果,整个页面仿佛被“冻住”了——链接无法点开,按钮毫无反应,搜索框也输入不了文字。该组件遵循了模态对话框的常见做法:打开窗口时,给其他所有元素加上`inert`属性,让焦点只在对话框内移动。这在普通弹窗中是正确且必要的,但“自动打开”让这种模态状态变成了每次访问的默认状态,页面里大约70个元素因此全部被标记为`inert`,直到访客手动关掉那个本不想看到的窗口。

// 组件打开时的典型操作document.querySelectorAll('body > *:not(.assistant-root)')  .forEach((el) => el.setAttribute('inert', ''));

`inert`并不是一条普通的样式规则。我们用常规手段检查一个主按钮:它在DOM中,可见,`offsetParent`不为`null`,`pointer-events`为`auto`,`getBoundingClientRect().width`返回180,`disabled`为false——所有“正常指标”都通过了。直到最后一项`closest('[inert]')`意外返回了`true`,真相才暴露。`inert`是在另一层发挥作用:它把元素及其所有子节点移出辅助功能树,同时取消鼠标和键盘事件,却在计算样式上不留任何痕迹。

自动化测试之所以失效,是因为它问的问题都太常规了:DOM里有没有?可见不可见?文本对不对?答案全是“有、有、对”。最终让人发现问题的是人眼看到一张截图后,手动点击了一次。程序眼中的“完好页面”,在访客面前就是一座不可交互的雕塑。

如果你正在使用任何会应用`inert`的组件,建议在测试中加入一条硬性断言:除非用户明确打开对话框,否则页面主体绝不能出现`inert`属性。浏览器按规则运行不一定是“安全的运行”,有时候,规则本身才是那个隐藏的连环陷阱。