Reputation: 4743
I am using Cypress to test a data export page which takes several minutes to generate an export. The page does not dynamically update, so I'd need to get Cypress to reload the page until the status shows as completed. I've looked through the Cypress docs and can't see a way to check if an element exists without throwing an exception if it doesn't.
I tried using jQuery but this resulted in an infinite loop:
describe('test reloading', function () {
it('testSelector reload', function () {
cy.visit('https://docs.cypress.io/api/utilities/$.html#Usage');
let found = false;
while (!found) {
const nonExistent = Cypress.$('.fake-selector');
if (!nonExistent.length) {
cy.reload();
} else {
found = true;
}
}
});
});
Upvotes: 5
Views: 11223
Reputation: 33384
You can try this code. Your element is not available, thus resulting in an infinite loop. You need to jump out from loop after a certain time.
describe('test reloading', function() {
it('testSelector reload', function() {
cy.visit('https://docs.cypress.io/api/utilities/$.html#Usage');
let found = false;
let count = 0;
while (!found) {
const nonExistent = Cypress.$('.fake-selector');
if (!nonExistent.length) {
cy.reload();
found = false;
count = count + 1;
cy.wait(1000);
if (count == 30) {
found = true;
cy.log('Element not found after 30 seconds..Exit from loop!!!');
}
} else {
found = true;
}
}
});
});
Upvotes: 5
Reputation: 1222
I cannot recommend while loops in Cypress, because you mix synchronous statements such as Cypress.$()
and asynchronous statements such as cy.reload()
.
For Cypress.$()
to pick up new elements, it needs a new context, such as within .then()
or .should()
.
I recommend using recursion to implement the repeating reload cycles. Here is an example:
it('testSelector reload', function() {
let remainingAttempts = 30;
function waitUntilSelectorExists() {
let $el = Cypress.$('.fake-selector');
if ($el.length) {
// At least one tag was found.
// Return a jQuery object.
return $el;
}
if (--remainingAttempts) {
cy.log('Selector not found yet. Remaining attempts: ' +
remainingAttempts);
// Requesting the page to reload (F5)
cy.reload();
// Wait a second for the server to respond and the DOM to be updated.
return cy.wait(1000).then(() => {
return waitUntilSelectorExists();
});
}
throw Error('Selector was not found.');
}
waitUntilSelectorExists().then($el => {
cy.log('$el contains this text: ' + $el.text());
});
});
To avoid throwing an error for an element that might not exists now (but later), the solution is to get()
a parent and try to find()
the child:
cy.get('#parent_of_sometimesMissing').then($element => {
if ($element.find('#sometimesMissing').length > 0) {
....
}
});
Upvotes: 1