Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught (in promise) TypeError doesn't cause test to fail #4998

Closed
westhomas opened this issue Aug 16, 2019 · 8 comments
Closed

Uncaught (in promise) TypeError doesn't cause test to fail #4998

westhomas opened this issue Aug 16, 2019 · 8 comments

Comments

@westhomas
Copy link

westhomas commented Aug 16, 2019

Steps to reproduce:

describe('how to fail', function () {
    it.only('should fail', function () {
        cy.visit("http://google.com")

        const doTheThing = () => {
            return new Promise((resolve) => {
                resolve({done: true})
            })
        }

        doTheThing().then((obj) => {
            const test = obj.badAttribute.reallyBad
            console.log(test)
            cy.log(test)
        })
    })  
})

This will throw this exception:

Uncaught (in promise) TypeError: Cannot read property 'reallyBad' of undefined

The problem is this is considered a pass in cypress:

Screenshot 2019-08-16 14 19 18

Current behavior:

Cypress tests don't fail when there's an exception within Promise

Desired behavior:

Cypress test should fail if there's an unhandled exception in my test code. Right?

Versions

cypress==3.4.1

Note: I've added these in my support file and the debugger never breaks at these events for the above test:

Cypress.on('uncaught:exception', (err, runnable) => {
    debugger
    console.log('uncaught:exception', err)
    // returning false here prevents Cypress from
    // failing the test
    return true
})

Cypress.on('fail', (err) => {
    debugger
})
@uweku
Copy link

uweku commented Aug 19, 2019

I confirm that behaviour.
My fail routine looks similar to the one above. But it still won't fail. This seems to have changed since the most current release, as the Tests broke reliably in the past:

Cypress.on('fail', (error, runnable) => {
skipAllTests = true;
throw error;
})
function deleteElements(name, deleteFunc) {
  isContain(name).then(el => {
    for (let i = 0; i < el.length; i++) {
      isContain(name)
        .eq(0)
        .click({ force: true });
      deleteFunc();
      cy.wait(1000);
    }
  });
}

cy.route({
method: 'DELETE', url: '/master/locations/*',
onResponse: (xhr) => {
expect(xhr.status).to.eq(expectedHttpStatus);
}
}).as('deleteLocations');

deleteElements('TestBla', () => {
cy.wait('@getLocationsDetails');
cy.wait(500);
cy.getElementByDataCypress('btnDeleteLocation').click({ force: true });
cy.get("button:contains('Ja'),button:contains('Yes')").click({ force: true });
cy.wait('@deleteLocations');
})

It does not work in visual test runner and also does not work in Background mode.
Cypress Version is 3.4.1

@westhomas
Copy link
Author

I went all the way back to cypress@2.1.0 and observed the same behavior: test still passes and events do not get triggered.

@westhomas
Copy link
Author

@jennifer-shehane Could you confirm this behavior as intended or a defect? It makes for some scary false positives and I need to figure out how to mitigate that.

@westhomas
Copy link
Author

@brian-mann Any thoughts on this? I basically can't use the promise pattern in my own support code currently because if there are exceptions in the support code, they don't fail the test. Is that desired? What am I doing wrong?

@mpahuja
Copy link

mpahuja commented Aug 30, 2019

might wanna try using the Cypress promise which wraps bluebird promises but should be chained off cy.
https://docs.cypress.io/api/utilities/promise.html#Syntax

@trejjam
Copy link

trejjam commented Jan 16, 2020

The correct way how to write this is:

describe('how to fail', function () {
    it.only('should fail', function () {
        cy.visit("http://google.com")

        const doTheThing = () => {
            return new Promise((resolve) => {
                resolve({done: true})
            })
        }

       // see the cy.wrap here
        cy.wrap(doTheThing()).then((obj) => {

            const test = obj.badAttribute.reallyBad
            console.log(test)
            cy.log(test)
        })
    })
})

Otherwise, your test ends before Cannot read property 'reallyBad' of undefined

@JohnnyFun
Copy link

Is this a duplicate of #2487?

@jennifer-shehane
Copy link
Member

Cypress only waits for it's own enqueued commands to finish before passing the tests. So after the visit succeeds, there are no more Cypress commands enqueued - so it passes. As mentioned by @trejjam, you'll want to put your promise in a cy.wrap() so we know to wait for the Promise code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants