Skip to content

Keep clicking Refresh button until data appears

I have one page for uploading a file which will be processed by the server in the background. I then have a second page where it shows only files that have been processed, which can take anything up to 5 seconds.

At the moment the code I have does this

        cy.visit('/')
        cy.get('.busy-spinner').should('not.exist', { timeout: 10000 })
        cy.contains('Submit file').click()
        cy.get('[id="requestinputFile"]').attachFile('test-file.txt');
        cy.contains('Upload').click()
        cy.contains('.notifications', 'Your file has been uploaded', { timeout: 10000 })
        cy.wait(5000)
        cy.visit('/processed-files')
        cy.get('[data-render-row-index="1"] > [data-col-index="1"]').contains(filename)

Sometimes the wait is far too long, sometimes it is not long enough. What I want to do is to go to /processed-files immediately and check if the row with my filename exists.

If it does then continue. Otherwise

  1. Pause for 1 second
  2. Click a specific button (to reload the data on the page)
  3. Wait until .busy-spinner does not exist (the data has been reloaded)
  4. Check if the row exists

If it does then pass, otherwise loop – but for a maximum of 30 seconds.

This pattern will be repeated in many places, what is the best way to achieve this?

Answer

Can you just wait on the filename?

cy.contains('[data-render-row-index="1"] > [data-col-index="1"]', filename, 
  { timeout: 30_000 }
)

If the reload is needed to get the correct row entry, a repeating function is a possibility

function refreshForData(filename, attempt = 0) {

  if (attempt > 30 ) {            // 30 seconds with a 1s wait below
    throw 'File did not appear'
  }

  // Synchronous check so as not to fail
  const found = Cypress.$(`[data-render-row-index="1"] > [data-col-index="1"]:contains('${filename}')`)

  if (!found) {
    cy.wait(1_000)
    cy.get('Reload button').click()
    cy.get('Spinner').should('not.be.visible')
    refreshForData(filename, ++attempt)
  }
}

refreshForData(filename)  // pass in filename, function can be globalized
                          // maybe also pass in selector?