Cypress 里的 ensureAttached 检测原理

举报
汪子熙 发表于 2022/10/02 09:40:16 2022/10/02
【摘要】 下面是我用 Cypress 开发的端到端测试。click 调用里的 force:true 参数是我后来加上去的。如果不添加,会遇到错误消息:在方法 $Cy.ensureAttached 里面跑出来的,这个方法位于 runner/cypress_runner.js 下面。我想知道这个 cypress_runner.js 的本地位置:本地请求的 url:http://localhost:4200...

下面是我用 Cypress 开发的端到端测试。click 调用里的 force:true 参数是我后来加上去的。

如果不添加,会遇到错误消息:

在方法 $Cy.ensureAttached 里面跑出来的,这个方法位于 runner/cypress_runner.js 下面。

我想知道这个 cypress_runner.js 的本地位置:

本地请求的 url:http://localhost:4200/__cypress/runner/cypress_runner.js

远端端口:59701?

重定向到 __?

这个文件有20万行代码:

怀疑这个庞大的文件是 merge 起来的:

这里能看到所有的 ensure 检查:

断点触发时,从 callstack 是很难发现到底是哪一行 e2e spec 代码触发的这个 ensureAttached 检查:

但是可以通过输入参数里指定的 select,到 e2e 代码里搜索:

cx-hamburger-menu [aria-label=“Menu”]

通过参数说明,点击了 cx-hamburge 的 button 元素:

很容易就找到了:

具体逻辑就是,检查元素的 ownerDocument 属性:

这是 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 进行了不同的处理:

因为在 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:

接口 的只读isConnected属性 返回一个布尔值,指示节点是否(直接或间接)连接到上下文对象,例如Document(普通 DOM 情况下的对象),或ShadowRoot 影子 DOM 情况下的对象。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。