下面是我用 Cypress 开发的端到端测试。click 调用里的 force:true 参数是我后来加上去的。
![](https://img.haomeiwen.com/i2085791/1be63bd223a6d21b.png)
如果不添加,会遇到错误消息:
![](https://img.haomeiwen.com/i2085791/87680242e09602ec.png)
在方法 $Cy.ensureAttached 里面跑出来的,这个方法位于 runner/cypress_runner.js 下面。
我想知道这个 cypress_runner.js 的本地位置:
![](https://img.haomeiwen.com/i2085791/761e56f431323cd3.png)
本地请求的 url:http://localhost:4200/__cypress/runner/cypress_runner.js
远端端口:59701?
![](https://img.haomeiwen.com/i2085791/be4fcf1fcac3fd63.png)
重定向到 __?
![](https://img.haomeiwen.com/i2085791/6cad5da78e6a65f6.png)
这个文件有20万行代码:
![](https://img.haomeiwen.com/i2085791/9f5c0d117a129316.png)
怀疑这个庞大的文件是 merge 起来的:
![](https://img.haomeiwen.com/i2085791/4f59b4d3130b0b0a.png)
这里能看到所有的 ensure 检查:
![](https://img.haomeiwen.com/i2085791/30853951282f2726.png)
断点触发时,从 callstack 是很难发现到底是哪一行 e2e spec 代码触发的这个 ensureAttached 检查:
![](https://img.haomeiwen.com/i2085791/6011ae775eaff847.png)
但是可以通过输入参数里指定的 select,到 e2e 代码里搜索:
![](https://img.haomeiwen.com/i2085791/e39477ddb632b3c3.png)
cx-hamburger-menu [aria-label="Menu"]
通过参数说明,点击了 cx-hamburge 的 button 元素:
![](https://img.haomeiwen.com/i2085791/dc0f79de55b2f1f6.png)
很容易就找到了:
![](https://img.haomeiwen.com/i2085791/4c8250766e86acd9.png)
具体逻辑就是,检查元素的 ownerDocument 属性:
![](https://img.haomeiwen.com/i2085791/beba78179d5b53df.png)
这是 Web API 里 Node 元素的标准属性,见官网。
接口的只读 ownerDocument 属性: 返回节点的顶级文档对象。
使用例子:
// Given a node "p", get the top-level HTML
// child of the document object
const d = p.ownerDocument;
const html = d.documentElement;
然后再判断这个 document 对象,是否有 activeWindow:
return nodes.every(node => {
const doc = _document__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].getDocumentFromElement(node);
if (!_document__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].hasActiveWindow(doc)) {
return false;
}
return node.isConnected;
});
};
这里 Cypress 还针对 firefox 进行了不同的处理:
![](https://img.haomeiwen.com/i2085791/55a3652d3b18d44c.png)
因为在 firefox 里,即使 detached document, 也还保留了一个指向 window 的 reference.
const hasActiveWindow = doc => {
// in firefox, detached documents still have a reference to their window
// but document.location is null
if (Cypress.isBrowser('firefox') && !doc.location) {
return false;
}
return !!doc.defaultView;
};
defaultView 是 Web API 另一个标准的接口。
In browsers, document.defaultView returns the window object associated with a document, or null if none is available.
这个也是只读属性,返回 document 关联的 window 对象。如果元素所在的 document 对象已经 detach from DOM,则 defaultView 指向 null.
node.isConnected:
![](https://img.haomeiwen.com/i2085791/c01643b1baf1e38b.png)
接口 的只读isConnected属性 返回一个布尔值,指示节点是否(直接或间接)连接到上下文对象,例如Document(普通 DOM 情况下的对象),或ShadowRoot 影子 DOM 情况下的对象。
更多Jerry的原创文章,尽在:"汪子熙":
![](https://img.haomeiwen.com/i2085791/97c4752c0e619c44.png)
网友评论