How force a reload on every visit in Cypress?

Viewed 32

I'd like to write a plugin that will hook onto every visit call, and it'll make sure something exists in the DOM. If not, then reload.

We're using a 3rd party library on dev that we cannot eliminate. It causes a race condition in rare cases, and it makes our React render fail, leaving an empty root behind. This causes random failures during our CI, making E2E tests fail.

I want Cypress to reload always until the root element is not empty.

I went through the Plugin documentation, but couldn't really find anything helpful at first glance.

2 Answers

Wrapping the visit and retry in a recursive function could be the way to do it


const reloadUntilRoot (url, attempts = 0) => {
  
  if (attempts === 10) throw 'Too many attempts'

  return cy.visit(url).then(() => {
    cy.wait(300)
    return cy.get('body').then($body => {
      const $root = $body.find('#root')
      if (!$root.length) {
        return reloadUntilRoot(url, ++attempts)
      }
    })
  })
} 

reloadUntilRoot(baseUrl).then(() => {
  // loaded
})

Or maybe just add retries to the test

it('loads page', {retries: 10}, () => {
  cy.visit(baseUrl)
  cy.get('#root')     // fails and retries up to 10 times
})

As Fody already mentioned above, you can override built-in commands, or wrap them in new custom commands with additional logic and keep default behavior:

Cypress.Commands.add('visitUrl', (url) => {
    function winReload() {
        return cy.reload()
    }
    cy.visit(url).then((window) => {
        const root = window.document.getElementById('root');

        // childNodes property returns a NodeList of the element's child nodes, 
        // including elements, text nodes and comments. 
        // If the property returns a value of 0, then the div is empty. 

        if (root.childNodes.length === 0) {
            console.log('⭕ Element is empty');
            winReload();
        }
    });
});

and inside your test, you just call cy.visitUrl('your_url')

Related