Peter Morris
Peter Morris

Reputation: 23224

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?

Upvotes: 0

Views: 343

Answers (2)

user16003578
user16003578

Reputation:

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?

Upvotes: 2

Alapan Das
Alapan Das

Reputation: 18650

You can create a recursive function in which you can check the presence of the file name by reloading the page for a maximum of 30 seconds. In case you find the file name you exit the function.

let retry = 0

function isElementVisible() {
    if (retry < 15 && Cypress.$('[data-render-row-index="1"] > [data-col-index="1"]'):not(:contains('filename'))) {

        //Increment retry
        retry++

        //wait 2 seconds
        cy.wait(2000)

        //Reload Page by clicking button
        cy.click('button')

        //Check busy spinner is first visible and then not visible
        cy.get('.busy-spinner').should('be.visible')
        cy.get('.busy-spinner').should('not.be.visible')

        //Call the recursive function again
        isElementVisible()

    } else if (retry < 15 && Cypress.$('[data-render-row-index="1"] > [data-col-index="1"]'):contains('filename')) {
        //Row found Do something
        return

    } else {
        //It exceeded the required no. of retries and a max of 30 seconds wait
        return
    }
}

//Trigger the recursive function
isElementVisible()

Upvotes: 2

Related Questions