Cypress Uncaught Assertion Error despite cy.on('uncaught:exception') - cypress

In relation to the following error:
Uncaught Error: Script error.
Cypress detected that an uncaught error was thrown from a cross origin script.
We cannot provide you the stack trace, line number, or file where this error occurred.
Referencing https://docs.cypress.io/api/events/catalog-of-events.html#To-catch-a-single-uncaught-exception
I am trying to run a test that fills out a form and clicks the button to submit:
it('adds biological sample with maximal input', function(){
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('of undefined')
done()
return false
});
cy.get('a').contains('Add biological sample').click();
. . .
cy.contains('Action results');
});
I get an error despite my spec containing the following:
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('of undefined')
done()
return false
});
Here's an image of the test failing .
The error in the bottom left reads,
Error: Uncaught AssertionError: expected '$f is not defined\n\nThis
error originated from your application code, not from Cypress.
\n\nWhen Cypress detects uncaught errors originating from your
application it will automatically fail the current test.\n\nThis
behavior is configurable, and you can choose to turn this off by
listening to the \'uncaught:exception\'
event.\n\nhttps://on.cypress.io/uncaught-exception-from-application'
to include 'of undefined'
(https://www.flukebook.org/_cypress/runner/cypress_runner.js:49186)
It seems that I am taking Cypress's advice and not getting the desired result. Any suggestions? Has this happened to anyone else?

Can you please remove expect(err.message).to.include('of undefined') and done() from the cypress exception block and add the below piece of code inside the test & run the test again
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})

The easiest way to fix this is to add the following to the top of your spec:
Cypress.on('uncaught:exception', (err, runnable) => {
return false;
});
This gets the same indentation level as your "it" blocks, nested directly under "describe". It will cause cypress to ignore all uncaught JS exceptions.
In the question, Atticus29 expects "of undefined" to be present in the error message, but the error doesn't actually contain that string. He could change
expect(err.message).to.include('of undefined')
to
expect(err.message).to.include('is not defined')
then it will pass.
To turn off all uncaught exception handling in a spec (recommended)
https://docs.cypress.io/api/events/catalog-of-events.html#To-turn-off-all-uncaught-exception-handling
To catch a single uncaught exception and assert that it contains a string
https://docs.cypress.io/api/events/catalog-of-events.html#To-catch-a-single-uncaught-exception

Although the fix of suppressing Cypress.on sometimes fix the problem, it doesn't really reveal the root problem. It's still better to figure out why you are having an unhandled error in your code (even in the test).
In my case, my form submission forward the page to another page (or current page), which causes re-render. To fix it, I need to call preventDefault.
const onSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
};
Every problem is a bit different, the above is only one example. Try to think about what your test actually does in the real site.

Official docs suggest that the cypress.on method is placed in "cypress/suport/e2e.js"
Docs 👉 https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests#Support-file
CMD + F "Support File"
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false prevents Cypress from failing the test
if (err.message.includes('Navigation cancelled from')) {
console.log('🚀 TO INFINITY AND BEYOND 🚀')
return false
}
})

Add these lines Before your Test Suit.
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
});

Related

Allow cy.wait to fail

After reading a lot of docs and try to find a solution to my problem I didn't find anything, so here we go.
I have the following problem testing my end to end flow, the flow I'm testing does launch requests continuously but in one case I expect these requests to stop. In other words, I want to throw an error if the request is made and continue with errors when hits the timeout without any request.
cy.wait('#my-request', { timeout: 20000 })
I expect this to timeout if the app works fine so I tried to do this.
cy.wait('#my-request', { timeout: 20000 })
.its('status').should('not.eq', 404)
.its('status').should('not.eq', 200);
I expected to execute the chained tasks but this only happens when the request is made, as well as tried to use a .then but I have the same problem.
Adding a global on fail event can help us but also limits to not execute additional code when this test is failing and we force it to be marked as done.
In the test definition we can add the done callback like in the example.
it('Description', (done) => {
// other test stuff
cy.on('fail', (err) => {
if (err.name === 'CypressError' && err.message.includes('routeAlias') && err.message.includes('Timed out')) {
done();
return true;
}
throw err;
});
cy.wait('#routeAlias', { timeout: 20000 })
.then(() => {
throw new Error('Error request found.');
});
});
// Any remaining code won't be executed if you need to reset something you need to create a new step, like in my case I did a new step to click a cancel button and prepare the app for the next test.
Now our test passes when this specific error is caught but any other error will lead to a test error.
This kind of workarounds are not recommended by cypress but unless cypress adds a catch to manage some errors it's the only way to fix my problem.

Cypress test failing due to error in Application Code

Cypress tests are failing due to application code error and not my code error. I have tried to bypass the error by using below code, but still it does not work. I can see similar bug is open in Github by Cypress team but someone can please provide a workaround, if any?
on('uncaught:exception', (err, runnable) => {
return false
})
From https://github.com/cypress-io/cypress/issues/987:
[Cypress doesn't] have a handler on top.onerror, only on the spec iframe and app iframe, and some errors will bubble straight to top.
As a workaround, you can add this to the top of your spec file or support/index.js:
// ignore uncaught exceptions
Cypress.on('uncaught:exception', (err) => {
return false
})
// patch Cypress top.onerror
Object.defineProperty(top, 'onerror', {
value: window.onerror,
})

Cypress visit uncaught reference

I'm trying to load "https://www.easports.com/fifa/ultimate-team/web-app/".
When the URL is loaded, I see Uncaught ReferenceError: data is not defined".
Is there some configuration I need to set?
my code is:
describe('My firts cypress', () =>{
it ('navegate to FUT web app', () =>{
cy.visit('https://www.easports.com/fifa/ultimate-team/web-app/')
})
})
after add uncaught:exception to return false...
As the error says it is not from Cypress but from your applcation. When you open console you should be able to look into the details. To bypass this error you can
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})
to your index.js under support folder.
This will stop failing your test if there is uncaught exception. See cypress doc.

Error handling using the catch block in cypress

I'm trying to handle an error in Cypress but the Cypress app is throwing error
cy.get('button[name="continue"]',{timeout: 30000})
.catch((err) => {
cy.console.log("error caught");
})
The error I get:
TypeError: cy.get(...).catch is not a function
tl;dr
Cypress has no .catch command the error message clearly states that.
Exception handling in Cypress
The documentation on error recovery clearly states:
The following code is not valid, you cannot add error handling to Cypress commands. The code is just for demonstration purposes.
cy.get('button').contains('hello')
.catch((err) => {
// oh no the button wasn't found
// (or something else failed)
cy.get('somethingElse').click()
})
They deliberately left this out and in the docs they explain it in great length why you shouldn't be able to do it.
If you really want, you can catch uncaught exceptions, just try the suggestions of the Catalog of Events on this matter:
it('is doing something very important', function (done) {
// this event will automatically be unbound when this
// test ends because it's attached to 'cy'
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('something about the error')
// using mocha's async done callback to finish
// this test so we prove that an uncaught exception
// was thrown
done()
// return false to prevent the error from
// failing this test
return false
})
// assume this causes an error
cy.get('button').click()
})

How can I catch unexpected error messages during Cypress test execution?

I am using Cypress and iziToast (http://izitoast.marcelodolce.com/) to run some tests on a web application.
I spotted an unexpected error message whilst running it locally.
I was able to catch it by adding the following cy.toast statement to my code:
cy.get(tabbedPanelControlsTitle)
.should('have.value', 'Teams')
.click();
// this is causing the following unexpected error
cy.toast({
type: 'Error',
code: 'E1527360562',
});
I was able to get it to fail here using the following:
cy.wrap({ toast: 'Error' })
.its('toast')
.should('eq', 'Success');
What I would like to know is there any way of catching these unexpected errors?
Toast Message:
Failing that, can I get the Network response to my click() command?
You can try the below code. This snippet will help you to catch the exception in the cypress test flow.
Cypress.on('uncaught:exception', (err, runnable) => {
console.log("err :" + err)
console.log("runnable :" + runnable)
return false
})

Resources