jquery - cy.get 返回无效的 jquery 元素

标签 jquery chai cypress

这是我的测试代码的片段:

cy.get('div[data-component-data-id=301602] h2:first')
  .should(($el) => {
    expect($el).to.have.text('dress')
  })

Cypress 提示这个断言:

CypressError: Timed out retrying: You attempted to make a chai-jQuery assertion on an object that is neither a DOM object or a jQuery object.

The chai-jQuery assertion you used was:

  > text

The invalid subject you asserted on was:

  > Object{3}

To use chai-jQuery assertions your subject must be valid.

This can sometimes happen if a previous assertion changed the subject.

所以我必须改变expect($el).to.have.text('dress')expect($el[0]).to.have.text('dress') ,然后投诉被驳回并且测试通过。

我对断言进行了一些调试,结果是 $el[0]也是一个 jquery 元素。

这是关于 $el 的快照和$el[0] :

enter image description here

所以我的问题是:不是 cy.get相当于jquery $ ?为什么我必须从 $el 获取第一个元素?为什么$el[0] is also a jquery element?

提前致谢。

编辑:

事实证明,当应用程序代码包含 zepto 库时,此错误与应用程序代码有关。我已经提出了issue在 Cypress Github 存储库中,您可以跟踪进度。

最佳答案

我不太确定您现阶段要寻找什么,但已经找到了一种重置 zepto 库效果的方法。

总结一下,

  • zepto 是一个与 jquery 兼容的库,它接管应用程序窗口上的 $ 全局 ref

    $ = function(selector, context) {
    return zepto.init(selector, context)
    }

  • 结果是像 .get().wrap() 这样的 cy 命令会产生 jquery 结果的 zepto 包装形式,与chai expect() 无需进行一些解构。

使用 Cypress.$ 进行实验,例如,我发现这仍然引用 jquery propper

const h2 = Cypress.$('h2')

返回一个 jquery 对象而不是 zepto 对象,因此我们可以从 Cypress.$ 重置应用程序全局 $

it('title display', () => {

  cy.visit('index.html')  // zepto takes effect here

  // Reset $
  const win = cy.state('window');
  win.$ = Cypress.$;

  cy.get('h2')
    .should($el => {
      expect($el).to.have.text('dress')  // passes
    })
})

重置代码可以合并到 cy.visit() 命令的覆盖中,以使其不那么普遍。

Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
  return originalFn(url, options).then(_ => {
    const win = cy.state('window')
    win.$ = Cypress.$
  })
})
...

it('title display', () => {

  cy.visit('index.html')

  cy.get('h2')
    .should($el => {
      expect($el).to.have.text('dress')  // passes
    })
})

注意这会影响 zepto 在应用中的工作方式。

<小时/>

解决办法让 Zepto 正常运行

此版本的 cy.visit() 覆盖将使 Zepto 库正常运行,但允许 Cypress .should() 接收正确的 jQuery 对象。

本质上,我们添加自己的代理(在 zepto 的代理之上)并在每次调用时检查选择器的类型。

Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
  return originalFn(url, options).then(_ => {
    const win = cy.state('window')
    const zepto_$ = win.$;
    win.$ = function(selector, context) {
      return typeof selector === 'string' 
        ? zepto_$(selector, context) 
        : Cypress.$(selector, context);
    }
  })
})

使用这个 html 片段来测试它。如果两个日志相同,zepto 不受影响。

<body>
  <h2>dress</h2>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>

  <script>
    console.log('from app, call #1', $('h2'))
    setTimeout(() => {
      console.log('from app, call #2', $('h2'))
    }, 1000)
  </script>

</body>

关于jquery - cy.get 返回无效的 jquery 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60336499/

相关文章:

javascript - 使用 While 循环时显示隐藏内容

javascript - 在 DOM 元素上触发点击事件

jquery - 谷歌分析和 pinterest 事件跟踪

javascript - Mocha 中的 ES6 promise

javascript - Cypress :cy.get ("a").find ("b") 和 cy.get ("a b") 之间的任何区别

javascript - 如何选择 Javascript 选择器的参数?

javascript - 如何测试在浏览器中发送需要身份验证的请求的函数?

javascript - 使用 Chai 监视/测试事件处理程序上的触发器是否有效

testing - headless 运行 cypress.io

javascript - Cypress:从 API 获取 token ,然后保存在本地存储中并在另一个 API 的 header 中使用,然后返回第二个 API 的响应正文