cy.then Callback With Retries Inside

The cy.thenopen in new window command does not retry its callback function, but the code inside the callback can still use normal Cypress commands with retries. Here is an example.

📺 Watch this recipe explained in the video cy.then Callback With Retries Insideopen in new window

button.initial {
  color: orange;
  background-color: green;
}
<button id="clickme" class="initial">Click me</button>
<script>
  const btn = document.getElementById('clickme')
  btn.addEventListener('click', () => {
    setTimeout(() => {
      btn.className = ''
    }, 1700)
  })
</script>

Let's confirm that clicking on the button removes the initial class names.

cy.get('button#clickme').then(($btn) => {
  // get the class names once
  const classes = $btn.attr('class')
  cy.wrap($btn)
    .click()
    // the assertion will retry until the application code
    // removes the class names
    .should('not.have.class', classes)
})

Refactored test 1

We can refactor the test a little to get the button inside the cy.then callback and pass the initial class names.

button.initial {
  color: orange;
  background-color: green;
}
<button id="clickme" class="initial">Click me</button>
<script>
  const btn = document.getElementById('clickme')
  btn.addEventListener('click', () => {
    setTimeout(() => {
      btn.className = ''
    }, 1700)
  })
</script>
cy.get('button#clickme')
  .invoke('attr', 'class')
  // this way the class name is written to the Command Log
  .should('be.a', 'string')
  .then((classes) => {
    cy.get('button#clickme')
      .click()
      .should('not.have.class', classes)
  })

Refactored test 2

I would try to make the test "know" the class name that should not be present after the click. Then the same test can written very shortly.

button.initial {
  color: orange;
  background-color: green;
}
<button id="clickme" class="initial">Click me</button>
<script>
  const btn = document.getElementById('clickme')
  btn.addEventListener('click', () => {
    setTimeout(() => {
      btn.className = ''
    }, 1700)
  })
</script>
cy.get('button#clickme')
  .should('have.class', 'initial')
  .click()
  .should('not.have.class', 'initial')