https://cypress.io logo
How to implement "on error resume next" in a loop
# i-need-help
g
Hi Cypress experts, I'm struggling with how to create a basic error catch (especially on error resume next) in Cypress when using a loop. Is it possible? I'm looking for something like this: for (const index of indexes) { try { cy.findByTestId("footer1") .find("span", {name: /Enter/i}) .should("be.visible") .click({force: true}); } catch (err) { // if any error continue with the loop continue } } I also tried but no luck. This cy.on works only for individual "it" test run cy.on('fail', (e)=>{ console.log (e) return false } Thank you !
d
I don't think you can use try catch with cypress
h
What are you trying to accomplish with this error handling? Conditional testing is generally an anti-pattern in Cypress - the test should be doing something predictable, so either that footer should always be there and there would not be any errors, or one of those commands should always fail, in which case you should be making assertions about that as the expected state.
l
cy
commands are queued up to run later, not immediately, so I suspect when it runs through that
try
there is no error reported. So instead you'll want to use some JavaScript or jQuery syntax to get at the element, then use an `expect`; no
cy
commands.
g
Thanks for the response. Here's an example: Let's say I have an array of URLs I want to verify. The fact is, some URLs (or locators inside) might fail for ANY reason, so I do not want to interrupt my loop and want continue with the next visit.
h
What is it testing though, in that case? Either it works or it doesn't, and in either case, the test passes?
Of the "ANY reason" a URL might not pass the assertions, what is one where the test should still pass?
g
"Kind of. The goal is to determine which URLs have failed and which have passed, finally.
Inside those URLs, I have some assertions and actions with locators. Let's say I have to visit 400 pages, and for sure, some of them will fail for flaky reasons or due to DOM issues.
it's just simple error catch logic "on any error resume to the next step"
like try and catch in JS or try and except in Python
h
Right, but in that case, should the test not fail?
g
yeah, exactly. I want to continue!
h
But when would the test actually fail, if that's not a failure?
g
in my case I dont care a lot which of them will fail I will note it and go ahead
h
Ok, so my recommendation is two-fold
One, just ask yourself if what you are doing is frontend test automation, or more general browser automation. It very well may be test automation, in which case I have a concrete suggestion for what you do about this, but just know that Cypress is quite opinionated in a way that is great for straight-line test automation, but not for general browser automation. https://docs.cypress.io/guides/references/trade-offs#Automation-restrictions
Supposing that you still want to go this route though, my suggestion would be that you do the loop outside a test to generate the test cases. I'm writing up a short example of what I mean.
g
Thank you! I'm experimeting with something like this: for (let i =1; i<10; i++) { it ('try loop outside it', ()=>{ //console.log(urls); //console.log('here is I ' + i) cy.on('fail', (e)=>{ console.log (e) return false } }) }
h
Copy code
const STARTER_POKEMON_IDS = ["001", "004", "007", "invalid-id"]
describe("Gen 1 starters", () => {
  STARTER_POKEMON_IDS.forEach(id => {
    const url = `https://www.serebii.net/pokedex/${id}.shtml`;

    it(`Loads Pokemon id ${id}`, () => {
      cy.visit(url);

      // The Pokemon id number should be on the page
      cy.contains(`#${id}`);
    })
  })
});
I don't think you should prevent the tests from failing at all
You will end up with individual tests like this:
You can choose to ignore those failures, or not block your CI pipeline on them, but they are still failures
g
Great @high-holiday-75305 ! Thank you so much for the help and assistance! This is what I'm looking for!
h
Great! Just to kind of close the loop - the reason you will find people around Cypress being weird about basic exception handling is that Cypress's execution model doesn't really mesh with them.
Your entire .cy.js file executes first, which queues up all of the commands and all of the tests, which is why even with dynamically generated tests like this, you get individual tests in the UI.
Then the "commands" for each test are executed by Cypress, even though the body of the test function has already executed. The .cy.js files are just describing what Cypress should do, not actually doing it in real-time like you would find with pretty much any other automation tool.
I have seen legitimate uses of
on('fail')
though. The one time I've used it is when authoring a Cypress plugin, I want to make sure I know what my plugin does in the context of a failing test, or know that my plugin would cause a test to fail in a certain situation.
Outside of plugin development though, you probably don't want to use it.
g
Yeah, thanks again for the clarification, an asynchronous model is still very confusing for me after Selenium 🙂
h
Here's a tiny snippet of code, basically checking that my custom command fails the test if you pass it a negative number. This is not normal for application tests, just plugin tests. ``` it('fails when cy.testStep is called on a negative number', (done) => { cy.on('fail', (error) => { expect(error.message).to.contain( 'Cannot start test step number -1 - the expected step number was 1', ); done(); }); cy.testStep(-1, () => {}); });
Hope that helps!
g
Thank you!
h
np, good luck!
l
@gray-crayon-29691, also consider Gleb's approach to testing multiple elements at once:

https://www.youtube.com/watch?v=l6_OXPiqkxQ&t=5sâ–¾

g
thanks!
3 Views