0

I have a scenario that I'm having difficulty with - in 2 separate environments I have 2 expected outcomes due to multi factor authentication. In one environment I have a popup notification that needs to be closed before other actions can take place. This is how I'm currently interacting with the button(no great locators):

cy.contains("Skip").click();

what I'd like to do is create a statement or condition that skips this click when the element isn't there. Everything I have tried up to this point has failed. Here is one example(I would assume I wouldn't get placed into the if here):

If statement HTML: <p class="jss29">Enable Two Factor Authentication?</p>

if(cy.contains("Enable Two Factor Authentication?")){
      cy.contains("Skip").click();
    }else{
      assert.ok("All Good");
    }

Here is my error:

Timed out after retrying after 4000ms: Expected to find content: 'Skip' but never did.

1

2 Answers 2

3

Just like jonrsharpe said in the comments, cy.contains will not return true/false depending on whether the element is there. In fact, it won't return anything of interest, as Cypress commands are asynchronous.

What you are trying to do can be a bit complicated, because you forget to account for time, and you can't be sure when your test code will execute. For example, imagine that your page loads, your test code runs, but the pop-up takes a few milliseconds to appear. Your test code will notice that there is no popup, and will believe that it can continue, and then half a second later the pop-up appears and your test gets confused. What that means is that you can't really ask Cypress to "guess" for you whether the pop-up will be there "eventually".

What you want to do instead is have a deterministic conditional test. That means that instead of asking Cypress whether the pop-up is there, you need to make Cypress aware that the test will (or won't) have to take care of that pop-up in the current execution (for example, a variable that is set in cypress.env.json for one environment but not another, a way to control the popup with a param in the URL, a hidden information like a class name in the DOM of your page, ...)

Then, your test becomes easier:

const willHavePopup = ...
if (willHavePopup) {
    // wait for the popup to be shown (can't skip it before it is there!)
    cy.contains("Enable Two Factor Authentication?").should('be.visible')
    cy.contains("Skip").click()
}
// your test continues here

Since Cypress commands execute in the order they're queued, these two new instructions will execute before the ones that you'll queue after the if.

More information about this in the Cypress doc. Don't hesitate to re-read this page a few times if you need (I sure did!) to grasp the problem and the solutions.

1

The best solution I’ve found is the cypress-if plugin: https://github.com/bahmutov/cypress-if/ . With it, you can solve your case like so:

cy.contains(“Enable Two Factor Authentication?“)
  .if()
  .then(() => {
    cy.contains(“Skip”).click()  // You may want to look into using cy.within here though
  })
  .else()
  .log(“All good”)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.