I'm trying to do something very similar to this post: https://stackoverflow.com/questions/56145926/how-to-check-if-element-exists-using-cypress-io
I'm using typsecript. Here's my code:
cy.get("body").then($body => {
if ($body.find(this.timerLocator).length > 0) {
return cy.get(this.timerLocator);
}
else {
return cy.contains('No Match Found');
}
});
The problem is that "this.timerLocator" can take up to 60s before appearing. The documentation for find commands mentions that we can pass an option 'timeout'. But when adding a timeout, I receive the following error message:
cy.get("body").then($body => {
if ($body.find(this.timerLocator, {timeout: 60000}).length > 0) {
return cy.get(this.timerLocator);
}
else {
return cy.contains('No Match Found');
}
});
Expected 1 arguments, but got 2.ts(2554)
I also tried something much easier, like:
try {
cy.get(this.timerLocator, { timeout: 60000 });
} catch (error) {
cy.contains('No Match Found');
}
But this is not working. I never reach the catch bracket.
Can anyone please help me on this one?
CodePudding user response:
I would avoid defining timeouts and time-based wait(number)
at all cost. In the long run they aren't a solution, because they will slow down your tests.
e.g. Most often, you need to wait for a certain API to be called. And in that case, you should define an http interceptor with an alias.
cy.intercept("GET", "/customers*").as("getCustomers");
and then wait for that alias instead.
cy.wait('@getCustomers');
If you're waiting for something else (which is quite exceptional), e.g. some kind of other promise or timeout to be finalized, then find a way to define an alias for that long-running function. e.g. stub it and define an alias for it.
const stub = cy.stub(someServiceToWaitFor, 'functionToWaitFor').as('alias')
You can't stub global functions though. You can only stub functions which are defined on an object. So, that may (or may not) require you to move some code around. (e.g. organize your code in services)
And secondly, it can be challenging to get hold of that service object in your cypress-test code. But you can actually pass variables by defining them on the window
object.
if (window['Cypress']) {
window['SomeServiceToWaitFor'] = someServiceToWaitFor;
}
You can then get hold of that object using cy.window...
from your test.
CodePudding user response:
You can't really do conditional $body.find(...)
with a timeout.
You can write your own timeout with a polling function, but it's a bit more complicated than you need.
Since you have either/or and it looks like they are mutually exclusive, you can use multiple selector
cy.get(this.timerLocator, 'contains("No Match Found")', {timeout:60000})
.then($el =>
cy.wrap($el).as('timerOrNoMatch'); // use alias not return
})
Note you should watch out for return cy.get()
- if you store that query result and the page changes, you can end up with and invalid element which is a difficult bug to track down.
If you use an alias as shown above, Cypress ensures the element reference is good or performs a re-query.
Further note - timeout error
$body.find()
is the jQuery version of find which has no timeout capability.
The Cypress cy.find()
is the jQuery one with the retry/timeout wrapped around it.