Как сделать пользовательскую дочернюю команду автоматически повторной

Я пытаюсь использовать следующую двойную команду в качестве ярлыка, чтобы найти элементы 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 делает?

2 ответа

Решение

Это довольно удивительно, но я смог проверить ваши результаты.

Самая простая работа, которую я придумал (что-то вроде хака), состоит в том, чтобы заново получить предмет в пользовательской команде.

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}]`)
})

Другой вариант - использовать стороннюю Cypress Pipe вместо пользовательской команды.

cy.pipe может использоваться как более простая замена Cypress Custom Commands - вы просто пишете функции.

cy.pipe работает очень похоже на cy.then, за исключением нескольких ключевых отличий:

  • pipe попытается документировать имя функции в журнале команд (работает только с именованными функциями)
  • pipe создаст моментальные снимки DOM, чтобы помочь в отладке, если функция, переданная в pipe, разрешается синхронно (не содержит команд Cypress)
    • AND возвращает элемент jQuery, pipe будет повторяться до тех пор, пока список элементов jQuery не станет пустым (большинство команд Cypress делают это)
    • И сопровождается cy.should, функция будет повторяться до тех пор, пока утверждение не пройдет или не истечет время ожидания (большинство команд Cypress делают это)


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 нужна опция для принудительного повтора этой команды #2670 на примере Глеба Бахмутова с использованием cy.verifyUpcomingAssertions() но это выглядит довольно сложно.

Этот шаблон работал нормально, когда тест (в конце концов) был успешным, но я не смог заставить его прекратить повторные попытки, когда тест не удался (должен истечь тайм-аут, но я не могу понять, как).

Сделай это вместо

cy.wrap(subject).find("[data-cy=#{id}]")
Другие вопросы по тегам