Search code examples
cypress

Cypress - Iterate over each element and perform some action before moving to next iteration / element


I have below issue in cypress:

  1. Get all table cells of a particular column containing a button.
  2. Iterate over each cell --> locate button within that cell.
  3. click on that button.
  4. wait for modal dialog to appear
  5. accept on modal and wait for it to disappear.
  6. wait for a notification to appear and then disappear.
  7. move to next cell element / iteration

Code that I have so far:

  cy.get("tr[some attribute]").each(($element, $index, $list) => {
    cy.wrap($element).find("button").click();
    cy.get(".modal-dialog").should('be.visible');
    cy.get(".modal-dialog button[type='submit']").should('be.visible').click();
    cy.get("toast").should('be.visible').as('@toast')
    cy.get('@toast').should('not.be.visible')
  })

Issues Here:

  1. The cypress doesn't waits for the first iteration to finish and runs all iteration. I can see multiple modal-dialogs opened up.
  2. Cypress asynchronously clicks on all the buttons without waiting for previous iteration to finish.
  3. cypress fails on step where it expects toast to disappear although i can see the toast message is not there.

Thanks in advance!


Solution

  • I ran a simple app with modal and toast. If you fix the toast part of the test it's possible to iterate the rows with .each()

    To fix the toast you need to drop the alias and cy.get('toast') a 2nd time.

    The alias value is stored internally and will not change when should() executes a retry. Remember, toast will stay on screen for some seconds so you must use retry to test it has gone. (You may need to increase timeout depending on toast duration).

    Minimal changes to fix:

    cy.get("tr[some attribute]").each(($row) => {
      cy.wrap($row).find("button").click();
      
      cy.get(".modal-dialog").should('be.visible');
      cy.get(".modal-dialog button[type='submit']").should('be.visible').click();
    
      cy.get("toast").should('be.visible')
      // timeout must exceed toast auto-close period
      // if you run the test in background or in CI, allow a few seconds extra
      cy.get('toast', {timeout:10000}).should('not.be.visible') 
    
    })
    

    I only get one toast on the screen at a time and the iteration waits for cy.get('toast', {timeout:10000}).should('not.be.visible') to complete.