pontilicious
pontilicious

Reputation: 299

Cypress: fetching new reloaded elements

I have a problem with reloading elements. On our site there are 10 elements on each pagination page. If you delete an element the next element slides in and so on. The problem I have is that initially the 10 elements are found. If I delete now all 10 elements my function is finished although further elements were reloaded which must also be deleted. How can I catch the reloaded elements in the function as well?

deleteDeliveryAddresses() {
    const deleteRow = (selector, rowsToDelete) => {

        if (rowsToDelete === 0) return

        cy.get('foerch-delivery-addresses-item .row:contains("automated address name")').eq(0)
          .as('rowDeleted')
          .find('button:nth-child(2)').click({force:true})
        cy.xpath("//button[normalize-space()='Bestätigen']").should('be.visible').click()
        cy.xpath("//button[normalize-space()='Bestätigen']").should('not.exist')
        cy.wait(1000)     

        deleteRow(selector, --rowsToDelete)
    }

    const selector = 'foerch-delivery-addresses-item .row:contains("automated address name")'

    cy.get(selector).then($rows => {
        const rowsToDelete = $rows.length
        deleteRow(selector, rowsToDelete)
    })
}

Upvotes: 2

Views: 537

Answers (2)

Paolo
Paolo

Reputation: 5441

Ideally, you would know how many rows are in the data that your test has to deal with. Then your tests works simply and perfectly.

Assuming that's not so, try refreshing the count at the exit point of the recursive function.

It's a 2nd-best choice, because the page may not be stable when the re-count is performed.

Updated

  • Added a pageCount limit to avoid "Maximum call stack size exceeded", for example if something is wrong with delete button selector and rows are not actually deleted.

  • Moved recursion call inside .then() after cy.wait(1000) to ensure steady rate of row deletion (i.e allows delete action to complete)

deleteDeliveryAddresses() {

  const selector = 'foerch-delivery-addresses-item .row:contains("automated address name")'

  const deleteRow = (rowsToDelete, pageCount = 0) => {

    // Set a page limit to avoid "Maximum call stack size exceeded"
    // if something goes wrong, for example rows are not deleted
   
    if (pageCount > 10) throw 'Too many pages processed'

    if (rowsToDelete === 0) {

      pageCount++   // track how many pages

      // refresh row count, using jQuery expression instead of .get()
      // so that if truly no more rows, test will exit gracefully
      // Table must be stable at this point
      rowsToDelete = Cypress.$(selector).length  

      if (rowsToDelete === 0) return
    }

    cy.get(selector).eq(0)
      .find('button:nth-child(2)').click({force:true})

    cy.xpath("//button[normalize-space()='Bestätigen']")
      .should('be.visible').click()
    cy.xpath("//button[normalize-space()='Bestätigen']")
      .should('not.exist')

    cy.wait(1000).then(() => {
      deleteRow(--rowsToDelete, pageCount)   // delay next delete until wait is complete
    })
  }

  cy.get(selector).then($rows => {
    const rowsToDelete = $rows.length
    deleteRow(rowsToDelete)
  })
}

Otherwise, this is a possible pattern for using the page-count

deleteDeliveryAddresses() {

  const rowSelector = 'foerch-delivery-addresses-item .row:contains("automated address name")'
  const pageCountSelector = '...something that indicate to the user the total page count'
  const rowsPerPage = 10

  const deleteRow = (rowsToDelete) => {

    if (rowsToDelete === 0) return

    cy.get(rowSelector).eq(0)
      .find('button:nth-child(2)').click({force:true})

    cy.xpath("//button[normalize-space()='Bestätigen']")
      .should('be.visible').click()
    cy.xpath("//button[normalize-space()='Bestätigen']")
      .should('not.exist')

    cy.wait(1000).then(() => {
      deleteRow(--rowsToDelete)   // delay next until wait is complete
    })
  }

  cy.get(pageCountSelector).then($pageCounter => {
    const pageCount = +$pageCounter.text()  // numeric from element text
    if (pageCount > 1) {
      deleteRow((pageCount -1) * rowsPerPage) // all but last page
    }

    // last page might be partial (less than 10)
    cy.get(rowSelector).then($rows => deleteRow($rows.length)
  })
}

Upvotes: 2

Zaista
Zaista

Reputation: 1422

Take a look at this pagination example that uses a recursive function to go through all the pages, the idea is pretty much the same and can be applied to your example: https://stackoverflow.com/a/69493081/1757737

Upvotes: 0

Related Questions