Search code examples
integration-testingcypress

Cypress click() failed because this element is detached from the DOM in iteration


I try to test my Single Page Application with cypress.
The first page has multiple buttons as anchor tags which direct you to the second site(Angular routing).
On the second site i have a "back" button.
So i want my test to click on a button, wait for the second site to appear, click on the back and repeat this for all remaining buttons.

This is my cypress test:

describe('Select products', function () {
    before(() => {
        cy.visit('http://localhost:4200/')
    })
    it('Clicking through products', function () {
    
        // getting each anchor to click 
        cy.get('a[data-cy=submit]').each(
            ($el) => {
            
                // click to get on next site
                cy.wrap($el).click()
                
                // click to go back
                cy.contains('go back').click()
            }
        )
    })
})

It works fine for the first run(get all buttons => click the first => go back)
but after getting back on the start site before clicking the next button cypress throws an error:

enter image description here

Can someone help me with this? Thanks for any help!


Solution

  • cy.get('a[data-cy=submit]') must get a list of the buttons and store them to iterate via .each(), but the code within .each() navigates away from the first page - I guess that Angular destroys the original elements that .each() is trying to iterate over.

    This is similar to iterating over a list and altering the list within the iteration, the loop fouls up because the list changes.

    If you know how many buttons there are, this would be a better way

    const buttonCount = 4;
    
    for (let i = 0; i < buttonCount; i++) {
      cy.get('a[data-cy=submit]').eq(i).click();
      cy.contains('go back').click();
    }
    

    If the buttons are dynamic (you don't know the count), use

    cy.get('a[data-cy=submit]').then($buttons => {
    
      const buttonCount = $buttons.length;
    
      for (let i = 0; i < buttonCount; i++) {
        cy.get('a[data-cy=submit]').eq(i).click();
        cy.contains('go back').click();
      }
    }