如何使自定义子命令自动重试

How to make a custom child command automatically retry

我正在尝试使用以下双重命令作为查找 dom 个元素的快捷方式。

Cypress.Commands.add "el", prevSubject: "optional", (subject, id) =>
  if subject?
    subject.find("[data-cy=#{id}]")
  else
    cy.get("[data-cy=#{id}]")

问题是如果我正在寻找的元素需要一段时间才能出现,该命令不会重试。

以下所有方法都有效

cy.wait(1000)                           # wait for element to appear
cy.get("parent").el("mark")

cy.get("parent").find("[data-cy=mark]") # or type out what the command does

cy.el("mark")                           # or use the command as parent command

但只是 cy.get("parent").el("mark") 没有等待元素出现并失败。

如果我像这样将命令定义为子命令,我会遇到同样的问题

Cypress.Commands.add "el", prevSubject: true, (subject, id) =>
    subject.find("[data-cy=#{id}]")

有没有办法让我的自定义命令的行为方式与 find 相同?

这很令人惊讶,但我能够验证你的结果。

我想到的最简单的解决方法(有点 hack)是在自定义命令中重新获取主题。

Cypress.Commands.add('el_with_ReGet', {prevSubject: true}, (subject, id) => {
  const selector = subject.selector || subject.prevObject.selector;
  return cy.get(selector).find(`[data-cy=${id}]`)
})

另一种选择是使用第 3 方 Cypress Pipe 而不是自定义命令。

cy.pipe can be used as a simpler replacement for Cypress Custom Commands - you just write functions.

cy.pipe works very similarly to cy.then except for a few key differences:

  • pipe will try to document the function name in the Command log (only works on named functions)
  • pipe will create DOM snapshots to aid in debugging If the function passed to pipe resolves synchronously (doesn't contain Cypress commands)
    • AND returns a jQuery element, pipe will retry until the jQuery element list is not empty (most Cypress commands do this)
    • AND is followed by a cy.should, the function will be retried until the assertion passes or times out (most Cypress commands do this)


import 'cypress-pipe';

it('should find child by id by pipe (replacing custom command)', () => {

  const elFn = (id) => (subject) => subject.find(`[data-cy=${id}]`)

  cy.visit(...)

  cy.get('parent')
    .pipe(elFn('mark'))
    .then(result => {
      console.log('find result', result)
      expect(result.length).to.eq(1)
    })

})

这里有一个讨论 Cypress.Commands.add needs option to force retry on that command #2670 有一个来自 Gleb Bahmutov 的例子使用 cy.verifyUpcomingAssertions() 但它看起来很复杂。

当测试(最终)成功时,此模式工作正常,但当测试失败时我无法让它停止重试(它应该超时,但我不知道如何超时)。

改为这样做

咖啡脚本:

cy.wrap(subject).find("[data-cy=#{id}]")

javascript:

cy.wrap(subject).find(`[data-cy=${id}]`)