Cypress while loop
Asked Answered
E

1

5

I have an API that returns times in a day and if those times are all taken then it won't return any. I want to move to the next day and try and check for times there but my test gets stuck and will crash.

So if there are no times go to the next day and wait for the response and check again for times. If there are times return we can exit the loop. Anyone see where this is going wrong?

Thanks

cy.get('body').then(($body) => {
  while (true) {
    if ($body.find('.time').length) {
      break
    } else {
      cy.get('.day').eq(4).click()
      cy.wait('@apiCheck2')
      cy.wait(500)
    }
  }
})
Emmieemmit answered 3/12, 2020 at 23:47 Comment(7)
You can't use a while loop as cypress uses promisses in each call. You have to use wrap and eachHiggle
@Higgle I think you are mistaken, there is an API call in the loop which changes the DOM. How would you do that with .each() since the DOM changes each iteration.Lizalizabeth
I'm under the impression that cy.wrap(selector).each((index) => { allows you to iterate the cypress promises but I have no way of testing this so I could totally be wrongHiggle
Well I'm doubtful - I mean cy.wrap(selector) is not valid syntax, you need cy.get(selector) . In the linked answer they wrap an array not a selector, and the .each() sees a fixed range of values - nothing changes in the iteration.Lizalizabeth
Thanks for the help. The for loop is working but it never finds .time even though i know for a fact it should. Any thoughts?Emmieemmit
I think that $body isn't varying in the loop, even though the DOM has changed.Lizalizabeth
Loops won't work given the async nature of cypress. For the proper solution, take a look at this: #62794174Sanburn
H
14

You have a selector you want to conditionally test, and a set of actions to perform if not found.

A generic custom command should be able do this. Using jQuery to test for the element(s) based on a selector and a function to call in between attempts.

Something like:

Cypress.Command.add('findWithRetry', (selector, retryAction) {
  const $el = Cypress.$(selector)
  if ($el.length) {
    return cy.wrap($el)
  }
  retryAction()
  return cy.findWithRetry(selector, action)
})

cy.intercept(url).as('@apiCheck')

const retryAction = () => {
  cy.get('.day').eq(4).click()
  cy.wait('@apiCheck')
}

cy.findWithRetry('.time', retryAction)
  .then($timeslots => {
    // use your timeslots
  })
Healthy answered 5/1, 2024 at 8:12 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.