I'm trying to build an overwrite for cy.click()
to add an additional assertion that must be true before an element is clicked. I know I could do this with a custom command, but I'd rather do it by overriding the built in one so that our existing tests all get the fix without having to be updated, and so we don't need to remember to use a different click method in the future.
My current code is:
Cypress.Commands.overwrite('click', (originalFn, subject, options) => {
cy.wrap(subject).should('not.have.attr', 'disabled').then(() => {
return originalFn(subject,options);
})
});
Basically, it should check one extra assertion (waiting for it to become true, since using should
) then do the built-in click. My reasoning behind this is that the built in click assertions don't recognize the disabled attribute on certain elements (e.g. <a>
is always considered enabled even if it has the disabled attribute, https://github.com/cypress-io/cypress/issues/5903). This works on tests that just click, but fails with the following message when cy.type
or cy.select
are called, possibly because those use click internally?
cypress_runner.js:199855 CypressError: Timed out retrying: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.
The command that returned the promise was:
> `cy.type()`
The cy command you invoked inside the promise was:
> `cy.wrap()`
Because Cypress commands are already promise-like, you don't need to wrap them or return your own promise.
Cypress will resolve your command with whatever the final Cypress command yields.
The reason this is an error instead of a warning is because Cypress internally queues commands serially whereas Promises execute as soon as they are invoked. Attempting to reconcile this would prevent Cypress from ever resolving.
I found https://github.com/cypress-io/cypress/issues/3838, but it got closed without actually giving a solution to this issue. What is the proper way to overwrite click without causing issues with other methods that seem to call it internally?
<input type="button"
. The reference tocy.type()
in the error is suspicious. – Ackroyddcy.type()
orcy.select()
with this overwrite, since they seem to callcy.click()
initially. Adding the overwrite to the kitchen sink example (github.com/cypress-io/cypress-example-kitchensink) and running tests thatselect
ortype
reproduces the issue. – Travisexpect
doesn't wait for the condition to become true likecy.should()
does. In my case the element is disabled at first and becomes enabled later (by JS code that is loaded asynchronously), so expect fails immediately. – Travis