We've seen users overwriting built in commands, but then not returning anything.
In these cases the originalFn promise will be untracked and lost - therefore not being properly awaited.
In this case, the user is unaware of this because they are subsequently enqueuing more commands downstream that get awaited. However, this could lead to all kinds of unexpected errors.
Here's the problematic code:
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
originalFn(url, options)
cy.wait('@alias')
cy.anotherCommand()
})
What happens here is that originalFn is invoked (and returns a promise). That promise begins its work, and then two more cypress commands are enqueued.
Cypress thinks the visit command has now completed (since it returned nothing) and begins processing the cy.wait. In this specific scenario, the code running in cy.wait does not conflict with the state of cy.visit, so nothing is apparently wrong. Additionally, the cy.wait has a longer timeout than a regular command, which is why it's able to resolve 'just fast enough' to beat out the timeout. Had the cy.visit taken longer to resolve, then the cy.wait would time out.
Users need to restructure their code to handle real promises.
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
// must correctly handle real promise chains
return originalFn(url)
.then(() => {
cy.wait('@alias')
cy.anotherCommand()
})
})
We need to warn users (in the console) that they invoked originalFn without returning it.
I attempted to do something akin to the "correct" overwrite, and it threw an exception:
CypressError: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.
Most helpful comment
I attempted to do something akin to the "correct" overwrite, and it threw an exception: