Here it's going to the new page by clicking the next button again and again. One of the page has text 'abc' that I'm trying to find.
for(let n = 0; n < 150; n ++) {
cy.get('.Next-Button').click();
// some test code..
cy.get('.selector').then($body => {
if ($body.find('abc').length > 0) {
return false; //used this to break the loop
}
});
}
The logic behind below code might not be clear but I basically want it to get out of loop when some value say 'abc' shows up on screen and continue with the code outside the for loop. But here it just keeps running the loop even after the value is found.
Here it's going to the new page by clicking the next button again and again. One of the page has text 'abc' that I'm trying to find.
for(let n = 0; n < 150; n ++) {
cy.get('.Next-Button').click();
// some test code..
cy.get('.selector').then($body => {
if ($body.find('abc').length > 0) {
return false; //used this to break the loop
}
});
}
The logic behind below code might not be clear but I basically want it to get out of loop when some value say 'abc' shows up on screen and continue with the code outside the for loop. But here it just keeps running the loop even after the value is found.
Share Improve this question asked Mar 8, 2023 at 19:45 LearnerLearner 532 silver badges9 bronze badges 2-
1
To break out of a loop, use
break;
. You'rereturn
ing within yourthen
callback. – mykaf Commented Mar 8, 2023 at 19:52 -
@mykaf I tried using
break;
but got this: Jump target cannot cross function boundary. Looked it up and it was suggested to usereturn
– Learner Commented Mar 8, 2023 at 21:34
2 Answers
Reset to default 4The basic answer is no you cannot use a for-loop and break out.
That's because the loop is putting 150 mands into the test queue before any evaluation of the DOM like $body.find('abc')
takes place.
The correct way to "loop" in Cypress is shown here Cypress test for element existence conditionally with retry.
But you need an additional step which is cy.get('.Next-Button').click()
.
Here are the changes I would make
function elementExists(selector, callback, attempt = 0) {
const interval = 100; // 100ms between tries
if (attempt * interval > Cypress.config('defaultCommandTimeout')) {
cy.log(selector, 'not found')
return cy.wrap(false, {log:false})
}
return cy.get('body', {log:false}).then(($body) => {
const element = $body.find(selector)
if (element.length) {
cy.log(selector, 'found')
return cy.wrap(true, {log:false})
} else {
callback()
cy.wait(interval, {log:false})
return elementExists(selector, ++attempt)
}
})
}
elementExists(selector, () => {
cy.get('.Next-Button').click();
// some test code..
})
.should(...)
The correct way to use a for-loop is to have a found
variable to control the execution inside the loop.
Here is a runnable test using example.
and testing for the <h1>
which is present from the start, so the loop should break on first iteration
it('breaks the loop', () => {
cy.visit('http://example.')
let found = false
for (let n = 0; n < 150; n ++) {
cy.then(() => {
if (!found) {
cy.log(index)
cy.get('body').then($body => {
if ($body.find('h1').length > 0) {
cy.log('found')
found = true
}
})
} else {
// cy.get('.Next-Button').click(); // do this on else branch
// some test code..
}
})
})
})
Using cy.then() wrapper
This is crucial, since Cypress code runs on a queue system.
If I ment out the cy.then()
it fails to break the loop
it('breaks the loop', () => {
cy.visit('http://example.')
let found = false
for (let n = 0; n < 150; n ++) {
// cy.then(() => {
if (!found) {
cy.log(index)
cy.get('body').then($body => {
if ($body.find('h1').length > 0) {
cy.log('found')
found = true
}
})
} else {
// cy.get('.Next-Button').click(); // do this on else branch
// some test code..
}
// })
})
})
Result: