cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.73k stars 3.16k forks source link

Cypress click() inconsistent results with Vuetify button #7404

Closed ivelin closed 4 years ago

ivelin commented 4 years ago

Current behavior:

The following cypress e2e tests should pass always, but sometimes fail. https://github.com/ambianic/ambianic-ui/blob/77e5b54ea12cacf6695f2edc629dea9601a43992/cypress/integration/ambianic-tests/about.spec.js

The error is the same on my local environment and github action script:

1) AboutPage Loads settings button:
     CypressError: Timed out retrying: `cy.click()` failed because this element:

`<span class="v-btn__content">Settings</span>`

is being covered by another element:

`<div class="v-overlay__scrim" style="opacity: 0.46; background-color: rgb(33, 33, 33); border-color: rgb(33, 33, 33);"></div>`

Fix this problem, or use {force: true} to disable error checking.

https://on.cypress.io/element-cannot-be-interacted-with
      at cypressErr (http://localhost:8080/__cypress/runner/cypress_runner.js:146180:16)
      at cypressErrByPath (http://localhost:8080/__cypress/runner/cypress_runner.js:146189:10)
      at Object.throwErrByPath (http://localhost:8080/__cypress/runner/cypress_runner.js:146152:11)
      at Object.ensureDescendents (http://localhost:8080/__cypress/runner/cypress_runner.js:137317:26)
      at ensureDescendents (http://localhost:8080/__cypress/runner/cypress_runner.js:127254:8)
      at ensureDescendentsAndScroll (http://localhost:8080/__cypress/runner/cypress_runner.js:127261:14)
      at ensureElIsNotCovered (http://localhost:8080/__cypress/runner/cypress_runner.js:127390:5)
      at runAllChecks (http://localhost:8080/__cypress/runner/cypress_runner.js:127527:52)
      at retryActionability (http://localhost:8080/__cypress/runner/cypress_runner.js:127542:16)
      at tryCatcher (http://localhost:8080/__cypress/runner/cypress_runner.js:9059:23)
      at Function.Promise.attempt.Promise.try (http://localhost:8080/__cypress/runner/cypress_runner.js:6333:29)
      at tryFn (http://localhost:8080/__cypress/runner/cypress_runner.js:140268:21)
      at whenStable (http://localhost:8080/__cypress/runner/cypress_runner.js:140303:12)

Desired behavior:

These tests should always pass.

Test code to reproduce

Source of test provided about. All app source code is on a this public repo branch.

Versions

Cypress 4.3.0 , Chrome, Ubuntu

jennifer-shehane commented 4 years ago

@ivelin Have you reviewed the video or screenshots of the failure? Is the element covered when you review these? It may be a situation where if there is some timing differences, the element is not visible within the 4 sec timeout sometimes.

jennifer-shehane commented 4 years ago

This is failing because the element you are trying to click is sometimes covered by an opacity element. You can see it when you run locally sometimes.

I don't exactly knows what controls whether this opacity element is shown in your app, but you'll want to make sure that that is gone before attempting to click.

Screen Shot 2020-05-19 at 6 05 42 PM
ivelin commented 4 years ago

Thank you for the investigation. I do see that there is an element covering the button during cypress testing, but the question is why doesn't this ever happen to real users. There is something between the cypress and vuetify interaction that needs to be documented.

jennifer-shehane commented 4 years ago

It could be some timing issue, but I'd have to dig in to be sure. Cypress clicks and moves faster than regular users most times.

ivelin commented 4 years ago

Yes, it feels like Vuetify protects input until the whole page is rendered and buttons are ready to do what they are expected. It is tough to track down because its seamless to the human eye.

WhatFreshHellIsThis commented 4 years ago

I've been battling Cypress and Vuetify in a non-trivial application off and on for months just to implement a simple smoke test so I know if changes made have broken something. Literally one single form with every input control type represented to do a simple create update remove cycle. Tests that work one minute fail the next inexplicably, there is no consistency and many of the Vuetify components are almost untestable such as the datetime selectors etc. One out of 3 runs the tests just fail inexplicably, I keep needing to add more {force:true} parameters everywhere and still failing. I seriously doubt Cypress and Vuetify are a viable combination at all.

jennifer-shehane commented 4 years ago

@WhatFreshHellIsThis Please open a new issue with a fully reproducible example, we'd be happy to take a look at the issue.

WhatFreshHellIsThis commented 4 years ago

Unfortunately there are just too many issues and I don't have the time at the moment; I really do think it's likely a lost cause, they just likely can't be compatible in any stable way due to the highly dynamic nature of Vue/Vuetify, the constant dom rewriting and the sheer number of changes that would need to be made to components to have a stable way to hook into them from Cypress. I've already made a case for making the components more testable on the Vuetify side of things some time ago but I'm really doubting there would be any stable common ground possible between the two projects.

ivelin commented 4 years ago

Thank you for your response. It is unfortunate that two great frontend tools like Vue(Vuetify) and Cypress can't come to common ground. Hope the teams reconcile in the near future. There is an open related issue in the Vuetify repo: vuetifyjs/vuetify/issues/11436

gtrrz-victor commented 4 years ago

I'm using protractor as a framework and I faced the same problem. The way that I found was to wait till all transitions ends. In order to identify when a transition is active is looking for elements with that classes (.dialog-transition-enter-active or .dialog-transition-leave-active), so when these elements have been vanished, we can say that the transition has ended.

My solution looks like:

  await browser.wait(
        EC.and(
          EC.stalenessOf($(".dialog-transition-enter-active"),
            EC.stalenessOf($(".dialog-transition-leave-active"))
          )
        ),
        timeout
      );
jiangao1 commented 3 years ago

I'm having the same issue. It's the inconsistency kills. This is a bad user experience and have no solution for it.