-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Assertion failure in async test case does not fail test overall #4742
Comments
@MadLittleMods The example above is missing information to run successfully, notably the Please provide a completely reproducible example that we can run that shows this bug and we will reopen the issue. |
…verall Made to reproduce problem from cypress-io/cypress#4742
@jennifer-shehane Here is a barebones test case that demonstrates the problem, https://github.com/MadLittleMods/cypress-test-tiny/pull/1/files |
…verall Made to reproduce problem from cypress-io/cypress#4742
Thanks for providing a reproducible example! |
Not sure if related but this test is also failling with native promises mixed with cypress promises with this code: it('It fails on promise but it passes', () => {
new Cypress.Promise((resolve, reject) => {
Promise.reject(new Error('Error from native promise')).catch(err => {
reject(err);
expect(true).to.be.false;
});
});
}); it also passes while failing on: it('It fails on promise but it passes', () => {
new Cypress.Promise((resolve, reject) => {
Promise.reject(new Error('Error from native promise')).catch(err => {
reject(err);
});
}).catch(err => {
expect(true).to.be.false;
});
}); |
Temperorary workaround for me is to wrap the promise in a Cypress command. Note that errors in catch will just time out the test that calls this command. In my case, in my commands js: Cypress.Commands.add('resetSomeData', function() {
return new Cypress.Promise((resolve, reject) => {
graphqlFetchObject
.request("mutation { doSomething }")
.catch(function(err) {
let didDeleteData = false;
expect(didDeleteData).to.be.true;
reject(err);
})
.then(function(resp) {
resolve(resp);
});
}).then((resp) => {
expect(resp.didItHappen).to.be.true;
});
}) |
Hi, |
So this issue is due a bug where Cypress doesn't support |
@ryan-snyder its a cypress issue. Mocha supports this, but we do some nasty hacks on top of mocha and likely didn't wire something up properly, such as awaiting a promise if it's returned. |
I'll likely spike into fixing this, possibly it will be simple. If not I'll work on getting it prioritized. |
@bkucera and I have been over this a bunch of times before and it's something on our end that we need to fix. It has to do with the interop between promises being returned to the test, and Cypress also knowing that commands were enqueued. We can generally always figure out how to do the right thing, but it will involve doing things like adding a We need to do things like intelligently throw if you've enqueued cypress commands inside of a native promise |
This comment has been minimized.
This comment has been minimized.
What is the point of having testing tool that doesn't even assert properly? This should have P1 Can someone guide me to related code? |
Is there a workaround / solution for this issue yet? Experiencing the same problem. |
@ryan-snyder Was able to solve my problem with a cy.wrap(
AWS.listAttachedRolePolicies('Admin').then((list) => {
expect(5).to.be.null;
})
); |
Could issue #1417 be related ? |
This comment has been minimized.
This comment has been minimized.
@jennifer-shehane @brian-mann I am getting the same issue.. assertion fails but test shows as PASSED. |
Hello I have the same problem with a test that compare 2 array content with deep equal. |
Any update on this issue? My test assertion is failed but test status is still green. |
Please refrain from commenting asking for updates 🙏 This issue is still in the 'ready for work' stage, which means no work has been done on this issue as of today, so we do not have an estimate on when this will be delivered. If there are any updates the |
The same story here. @jennifer-shehane btw why we should not ping you guys? This is a major issue inside Cypress, caused a lot of people. So that's the only way to say you "Hey, we're still here and need help". As a result, make some impact on reordering among your roadmap prioritizations. Based on how much folks ask for. :( Otherwise, it stuck in your backlog for a while... Thanks. |
Hello |
Guys, I faced same issue, BDD assertions fails but test passes. For example: I used jquery inside BDD assertions assert fails not matching [1,2,1] but test was passing. No success with try and catch. I tried with await like below and finally test fails. it.only("Sample Test", async () => {
... line of codes ...
await cy.get(".ag-header-container .ag-header-row").then((element) => {
{few assertions}
.....
cy.wrap(element).find(".ag-cell-label-container").each(elem => {
expect([
Cypress.$(elem).find(".ag-sort-ascending-icon").length,
Cypress.$(elem).find(".ag-sort-descending-icon").length,
Cypress.$(elem).find(".ag-sort-none-icon").length
]).to.deep.equal([1,2,1])
})
})
}) |
I didn't think that the |
This is still behaving incorrectly in 5.0.0 Reproconst getBar = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve('bar')
}, 1000)
});
};
it('test', async () => {
cy.contains(await getBar())
}) |
After spending lot of time in Cypress, I came out with solutions which helped me in writing good testcases and hope same would be for others too.
Always stick to : it("sample test", () {
})
(not)
it("sample test", async() {
})
Async & Sync function in customFunctions.js file export class customFunctions {
Asynchronous function: (iter is for terminating infinite loop if text does not exist)
async scrollhztnlAndGetAllElements(exp_value, webElement, elemlist = [], iter = 0) {
iter++
if (iter == 100)
return cy.wrap([], { log: false })
let vlist = await cy.get(webElement, { timeout: 10000, log: false }).text({ log: false }).promisify()
elemlist = elemlist.concat(vlist)
if (elemlist.includes(elemlist.find((value) => value.includes(exp_value)))) {
return cy.wrap(Cypress._.uniq(elemlist), { log: false })
} else {
cy.get(webElement, { log: false }).last({ log: false }).click({ waitForAnimations: false, log: false })
return customFunct.scrollhztnlAndGetAllElements(exp_value, webElement, elemlist, iter)
}
}
Synchronous function:
replaceCharInArray(exp_array, emp_arr = []) {
exp_array.forEach(evalue => {
let value = evalue.replace("(mm)", "").replace("(000s)", "").trim()
emp_arr.push(value)
})
return emp_arr
}
}
export const customFunct = new customFunctions() And in testcase, I import class file and called both async function (scrollhztnlAndGetAllElements) and sync functions (replaceCharInArray) as below shown. Synchronous function doesn't need to be wrapped and only async function need to be wrapped as in below sample code. In testcase file:
import { customFunct } from '../../support/customFunction'
it("Column Header Test", () => {
cy.wrap(customFunct.scrollhztnlAndGetAllElements(Cypress._.last(expectedHeaders), locator.tableColumnHeader))
.then(actualHeaders => {
expect(customFunct.replaceCharInArray(actualHeaders)).to.deep.equal(expectedHeaders)
expect(Cypress._.join(actualHeaders)).to.not.include("undefined")
})
})
(OR) If it is single assertion, i would have done like this for values from async function:
it("Column Header Test", () => {
cy.wrap(customFunct.scrollhztnlAndGetAllElements(Cypress._.last(expectedHeaders), locator.tableColumnHeader))
.should("to.deep.equal", expectedHeaders)
}) If you want to get single element value, then use Jquery inside thenable or each: cy.get(locator.tablerowlist).each((elem, indx) => {
let nameColumnValue = Cypress.$(elem[indx]).text()
....
....
rest lines of codes
})
sortCheckElements(elements, len = 0) {
for (var i = 0; i < Cypress.$(elements).length; i++) {
if (Cypress.$(elements[i]).has(locator.sortAscIcon).length > 0 &&
Cypress.$(elements[i]).has(locator.sortDescIcon).length > 0 &&
Cypress.$(elements[i]).has(locator.sortNoneIcon).length > 0) {
len = len + 1
}
}
if (len === Cypress.$(elements).length)
return true
else
return false
}
hgHeaderCssPropertyValidation(elements, len = 0) {
for (var i = 0; i < Cypress.$(elements).length; i++) {
if (Cypress.$(elements[i]).css("font-size") === "11.5px" &&
Cypress.$(elements[i]).css("font-weight") === "700" &&
Cypress.$(elements[i]).css("color") === "rgb(255, 255, 255)" &&
Cypress.$(elements[i]).css("text-overflow") === "clip" &&
Cypress.$(elements[i]).css("white-space") === "normal" &&
Cypress.$(elements[i]).css("text-align") === "center") {
len = len + 1
}
}
if (len === Cypress.$(elements).length)
return true
else
return false
} In testcase, use: cy.get(locator).then(elem => { expect(customFunct.sortCheckElements(elem)).to.be.true })
cy.get(locator).then(elem => { expect(customFunct.hgHeaderCssPropertyValidation(elem)).to.be.true })
cy.get(locator.tableColumnHeader).text().to("array")
.should("to.deep.equal", ["Time", "Legacy (mm)", "Standard Origin (mm)"])
In testcase file:
const drillData = require('../../fixtures/drillData.json')
it("some test" () => {
cy.server()
cy.route("POST", APIEndPoint, drillData).as("dataDrill")
})
In UserInfo json file:
{
"expectedCusInfo": [{"Region", "Time Period", "XYZ", "ABC"],
"expectedMessage": "User has been added successfully"
}
In testcase file:
const userData= require('../../fixtures/UserInfo.json')
it("some test" () => {
cy.get(locator).text().to("array").should("be.deep.equal", userData.expectedCusInfo)
cy.get(locator).should("have.text", userData.expectedMessage)
})
it("some test", () => {
cy.server()
cy.route("GET", ApiEndPoint).as("customerData")
cy.visit("/customerpage")
cy.wait("@customerData")
}) Hope, this would be helpful. Object chaining better than using async in testcase to get reliable results all time. |
This is still a bug in 8.6.0 |
I can confirm. I'm using version 8.7.0 |
I've just confirmed that this is an issue in version 9.5.0. I accidentally left an We are fairly new to Cypress but the fact that this issue has been open for 3.5 years is making me reconsider whether Cypress is reliable enough for us to be using. |
I was able to set up a rough eslint error for this using the eslint-plugin-regex package as follows for anyone else who needs it:
But it's very important for a testing framework to correctly fail when its assertions aren't met; relying on developers to fully follow Cypress's issue tracker, set up custom lint errors, follow blog posts, etc. to be aware of this issues and its workarounds will inevitably mean a lot of developers won't understand this and will write defective tests, leading to defective products shipping. Is there a way this can be treated as a P1, or are there any blockers/resourcing problems that we could help with? |
@swinejelly you can use the official Cypress ESLint plugin to catch this already https://github.com/cypress-io/eslint-plugin-cypress#rules |
@bahmutov Thank you, I wound up installing the Cypress ESLint plugin instead. Do you mind looking at this issue I filed in the Cypress ESLint repo please? |
I probably won’t have time to look at that issue unfortunately
…Sent from my iPhone
On Mar 8, 2022, at 15:22, swinejelly ***@***.***> wrote:
@bahmutov Thank you, I wound up installing the Cypress ESLint plugin instead.
Do you mind looking at this issue I filed in the Cypress ESLint repo please?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.
|
Any updates on this one? Have the same issue. |
@agugut Could u please share the example? |
I wrote a plugin https://github.com/bahmutov/cypress-catch-async-tests that catches this, for anyone interested. |
I am sure that this won't be helpful to everyone but I found a work around for my use case which is conditionally running tests depending on the results of an asynchronous query of a remote database. My solution was to remove any asynchronous stuff from the tests and instead move it into the before() function which runs before all of the tests for that specific spec file.
|
I'm looking into a fix for this issue; it's required work on the way to #1417. An example to demonstrate the most basic case:
The promise resolves immediately, but there are still items in the Cypress command queue. We should clearly be waiting for both the test function to resolve and the command queue to be empty. Notably, it works if you wrap it in
meaning that Cypress has already 'solved the hard part' - we know how to do the right thing (because the right thing happens when we wrap our original function, unchanged, in |
Related issues
async
/await
with the Cypress API,cy.xxx
)Current behavior:
The assertion fails(in red) but the overall test still passes,
Desired behavior:
Asserts with
cy
work inasync
test caseSteps to reproduce: (app code and test code)
Use the following testing code with
async
and notice the test succeeds.https://github.com/MadLittleMods/cypress-test-tiny/pull/1/files
Versions
The text was updated successfully, but these errors were encountered: