You can use the Chrome Debugger Protocol as described in this article When Can The Test Click
The example given is
it('clicks on the button when there is an event handler', () => {
cy.visit('public/index.html')
const selector = 'button#one'
cy.CDP('Runtime.evaluate', {
expression: 'frames[0].document.querySelector("' + selector + '")',
})
.should((v) => {
expect(v.result).to.have.property('objectId')
})
.its('result.objectId')
.then(cy.log)
.then((objectId) => {
cy.CDP('DOMDebugger.getEventListeners', {
objectId,
depth: -1,
pierce: true,
}).should((v) => {
expect(v.listeners).to.have.length.greaterThan(0)
})
})
// now we can click that button
cy.get(selector).click()
})
where cy.CDP is installed from this package cypress-cdp
Retrying the click
Another approach might be to retry the click until it has an effect.
The exact code would be app dependent, but the pattern would be
const clickUntilChanged = (linkSelector, changeSelector, attempt = 0) => {
if (attempt > 10) throw 'Something went wrong'
cy.get(changeSelector).invoke('text')
.then(initial => {
cy.get(linkSelector).click() // attempt a click
cy.get(changeSelector).invoke('text')
.then(next => {
if (initial === next) { // no change
cy.wait(50) // wait a bit then try again
clickUntilChanged(linkSelector, changeSelector, ++attempt)
}
// else click was effective, just exit
})
})
})
clickUntilChanged('menu-item', 'page-header')
Test retries
Another approach is to make use of a small initial test with retries set
it('tests the link click', {retries: {runMode: 10, openMode: 0}}, () => {
cy.get('menu-item').click()
cy.get('page-header')
.should('have.text', 'new-page-header') // fails and retries
// if click had no effect
})
Just wait
Looking at Gleb's latest article Solve The First Click, right in the middle he just adds a hard wait to allow the event listeners to hook up.
This is probably my preferred approach given the simplicity, and who would notice an extra 1 second in a CI run.
cy.visit(...)
if (!Cypress.config('isInteractive')) { // run mode
cy.wait(1000)
}
cy.get('menu-item').click() // should now be functioning