I have a cart preview button on the top right of the screen. If I click this button, a div appears. This div lists items in the cart, and below each item there is a "remove" button.
I need to click on every "remove" button of this div, and remove all the items one by one.
The problem is that after I click "remove" a spinner appears for some seconds. When the spinner disappears, appear the rest of the items and the rest of the "remove" buttons.
cy.get('.cart-toggle-btn').click()
cy.contains('.remove.btn', 'Remove').each(aaa => {
aaa.click()
})
If I use the code above, it only removes the first item, and then the test passes. But there are still other items in the cart.
How can I "tell" cypress to wait for the redux dispatch action to complete (spinner to disappear) and then retry to find the next remove buttons?
Thanks
CodePudding user response:
Factoring in the spinner is a good way to see when the "internal" process is complete and you can proceed with the next remove action.
But you should wait for the spinner to appear, then disappear. In the test, Cypress will check the spinner very quickly, even before it has appeared.
cy.get('.cart-toggle-btn').click()
cy.contains('.remove.btn', 'Remove').each($item => {
cy.wrap($item).click()
cy.get('spinner').should('be.visible') // check visible rather than exists
cy.get('spinner').should('not.be.visible')
})
With list counter
If you have trouble with the spinner (and don't care about it), check the length of list
If the list re-renders between remove actions, and you get detached from DOM errors, re-query the elements inside the loop
cy.contains('.remove.btn', 'Remove').each($item => {
// get fresh count each time
cy.contains('.remove.btn', 'Remove').then($currentList => {
const count = $currentList.length
cy.contains('.remove.btn', 'Remove').first().click() // remove one
// wait for smaller list (when it's not yet empty)
if (count > 1) {
cy.contains('.remove.btn', 'Remove').should('have.length', count -1)
} else
cy.contains('.remove.btn', 'Remove').should('not.exist')
}
})
})
With conventional Javascript for-loop
This is shorter, using a conventional loop and executing the last remove action outside the loop.
cy.get('.remove.btn').its('length').then(count => {
for (let index = 1; index < count; index ) {
cy.get('.remove.btn').first().click()
cy.get('.remove.btn').should('have.length', count -index)
}
cy.get('.remove.btn').first().click()
cy.get('.remove.btn').should('not.exist')
})
CodePudding user response:
You can do an assertion on the spinner not existing, and that should tell your test to wait after each .click()
.
cy.get('.cart-toggle-btn').click()
cy.contains('.remove.btn', 'Remove').each(aaa => {
aaa.click().get('spinner').should('not.exist')
})