-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
cy.click() failed because element is effective width and height of 0x0, even though it is not. #695
Comments
Much of the algorithm used to determine visibility is documented here: https://docs.cypress.io/guides/core-concepts/interacting-with-elements.html#Actionability Your issue is very clear which is helpful, thank you. I'm a bit confused when you say flaky though. Flake generally refers to situations where a test sometimes passes or sometimes fails. It seems that you're saying the test always fails which would not indicate a flaky test - you've just found a bug in our visibility algorithm :-P While you've done an excellent job giving us a ton of great information, the problem is that there is more than just the styles of this Is there any way you would be able to remove all of the excess HTML (or maybe even just do a File -> Save Page As) so you can export the entire DOM including the styles. From there we should be able to internally reproduce this and get it resolved. Also if this is a public site (or even a private site we could log into) we'd be happy to take a look at this. We've had a few users complain about this exact scenario - where Cypress considers an element hidden because its effective width and height is 0, but we've been unable to reproduce any situation to trigger that. We have several hundred tests around visibility (and they all pass) so we're going to need help creating the scenario where this happens. |
Thanks for responding, I haven't been clear about that, sorry. The test does indeed sometimes passes, and sometimes not. Locally it passes roughly 95% of the time, on our CI environment it passes roughly 10% of the time. I've done some testing and I'm pretty certain it has nothing to do with the styling of the Our app currently does a lot of api calls on page load (something we should improve upon :)), and I managed to get the tests more stable by doing the following: cy.route('/api/order/retailer-orders**').as('getRetailerOrders');
cy.route('api/connection/connections').as('getConnections');
cy.route('/api/connection/relations').as('getRelations');
cy.route('/api/order/basket').as('getBasket');
cy.route('/api/order/retailer-orders/*').as('getRetailerOrder');
cy.route('/api/brand/brands/*').as('getBrand');
// .. some other checks ..
cy
.wait('@getRetailerOrders')
.wait('@getConnections')
.wait('@getRelations')
.wait('@getBasket')
.wait('@getRetailerOrder')
.wait('@getBrand');
cy.get('a[href="/styles"]').click(); // <--- This is where it sometimes fails. Now it's a bit early to call the test "stable" but it at least a lot more stable. About your other question, I'm going to try and isolate this issue by making a simpler app, but that will take some time. |
Could any of those XHR's affect the re-rendering of the |
Not to my knowledge, the Interestingly, if I use |
I believe the problem here is that it's finding the I can manually recreate this situation and opened a new issue here: #696 There is something causing the Likely what you'll need to do is add more guards prior to interacting with the element.
So what ends up happening is that by forcing the click event to happen, Cypress issues it, but it's being issued to a detached element, which does nothing. |
As per your suggestion - you will need to come up with some mechanism to 'guard' Cypress from executing its commands too soon until you know your application has completely initialized. You could directly communicate with your react app and register an event listener, or you could search for some content on the page that you know becomes available. For instance your react app could add an attribute to the or to know its completely done. You could also individually wait for all the XHR's although react is going to process them asynchronously so there will still be a small gap even after waiting on them. Once you establish that it will solve all of your flake. I would likely wrap this up into a custom command or just override There are no events in JS that will help you do this, it's completely application specific. |
I have the same issue. We are using angular. Some times the click registers and the other times does not. |
@puneet0191 and @chathuraa did you read my comments above in this thread? I believe both of your situations are caused by the element becoming detached as Cypress begins to type. Can you verify nothing on your end is re-rendering the element. @puneet0191 in your case you are highlighting the element in dev tools which is not necessarily the element that cypress found because it could have been replaced by being rerendered. |
@brian-mann, thanks for the quick response. I believe the page render several times. Unfortunately reducing rerender is all the way at the bottom of our backlog. Sorry for my ignorance, is there a work around? |
@chathuraa I worked around it by making sure the re-renders are done before executing the assertions which in my case is when all backend calls are done. See this comment |
In my case, I was trying to click on a link (after waiting for the API result) that was being mounted and unmounted when API results came in. Switching it to a React pure component and making sure it wasn't unnecessarily unmounted fixed the problem. FWIW, I'm also using React Router 4 and this was trying to click on a |
This has also been a real issue for us. We're using React and I'm still struggling to find the right combo of xhr waits for each page to get our tests reliable. But this thread has been helpful to understand the cause 👍 |
Timeouts because of zero-width elements happens all the time to us; I'm guessing it's because the element is only partially rendered. It would be great if there was a way to wait for an element of non-zero width; then I'd replace get() with a version that checked for both visibility and non-zero size. But I haven't found a way to do this. You can do an assertion on the css width, but that's not the same thing. Also {force: true} doesn't work in this case. The only solution currently I've found is to add wait()s. |
@peternye You should be able to write an assertion that checks on non-zero width where the tests will not move forward until it is greater than non-zero: // these assertions below are the same
cy.get('#query-btn').invoke('width').should('be.gt', 0)
cy.get('#query-btn').invoke('width').should('be.greaterThan', 0) You could basically assert against any property of an element, like See Assertions |
Thanks, @jennifer-shehane! Exactly what I was looking for. |
@jennifer-shehane this is exactly what we needed as well. we are going to implement a custom command to handle these assertions. Cheers! |
@jennifer-shehane thank you for the suggestion! Can you clarify, why |
I have the same problem with a flaky behaviour. With those tests : cy.get('#candidatsList > li:nth-child(1) > span').should("contain", "Créer RDV");
cy.get('#candidatsList > li:nth-child(1) > span').invoke('width').should('be.gt', 0);
cy.get('#candidatsList > li:nth-child(1) > span').click(); First two "get" succeeds, but not the third one. I don't think that there is a "scroll end" event i could hook to, so i don't know how i could guard this step without using cy.wait |
I agree with @vjau , no matter what we are doing to guard the click, the click fails though the element is clearly visible. |
@bkucera and I have been reworking the visibility algorithms and are also in the process of adding native events. These bugs will be fixed. I don't have a timeline yet, but as we fix the visibility stuff we will release patches. At the moment you can try setting the input's value programmatically and then manually trigger the
Just take programmatic shortcuts which will avoid the checking layers |
Didn't work for me. I tried to programmatically make them visible, but to
no avail.
…On Thu, Jun 14, 2018 at 7:10 PM, Brian Mann ***@***.***> wrote:
@bkucera <https://github.com/Bkucera> and I have been reworking the
visibility algorithms and are also in the process of adding native events.
These bugs will be fixed. I don't have a timeline yet, but as we fix the
visibility stuff we will release patches.
At the moment you can try setting the input's value programmatically and
then manually trigger the change events (or other stuff) so that your
application binds to them correctly.
cy.get('input').invoke('val, 'asdf').trigger('change', { force: true }) //
something like this
Just take programmatic shortcuts which will avoid the checking layers
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#695 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AIJ3zabjO0hR7dK3-Gt0IW_TF7QjUkyRks5t8pj3gaJpZM4Poclb>
.
|
I would just like to say I'm experiencing this same problem, am able to verify the the existence of the element via height and width but getting the same "element not visible" when trying the click. I do believe it has to do with timing, if I hardcode a wait it passes fine. This is especially weird because the |
Try |
Tried that to no avail.
…On Thu, Jun 21, 2018, 22:21 Brian Mann ***@***.***> wrote:
Try cy.get(...).click({ force: true })
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#695 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AIJ3zUeHjuniqd4kB8tbN5mpAaJCCzOpks5t_AA5gaJpZM4Poclb>
.
|
thanks @hdavidzhu, you are correct. Should have thrown a comment on here. |
Any update on this issue? It's still reproducible in Cypress v3.6.1 |
I am experiencing exactly the same in 3.6.1 |
There were improvements as part of 3.5.0 release #4945 that should have improved this error message for many instances where one was asserting on a detached DOM element. Now users will see a message saying that the DOM element is attached. If you're still experiencing this in 3.6.1 - Please provide a fully reproducible example of the bug. I cannot stress this enough. If we cannot write a failing test in Cypress - then we cannot begin work on the issue. |
After trying several approaches I'm getting good results with cy.get("#id")
.should("be.visible")
.then($btn => {
$btn.click();
}); |
@khayrat version? |
cypress/included:3.2.0 and cypress/included:3.6.1 - I'm running it in ci/docker. Natively I got stable results either with |
@khayrat Thanks! works for me! |
I have the similar issue. |
Being subscribed to this thread is funny. People come up with workarounds that probably break X% of the time instead of someone resolving the root cause. Does anyone know why this is a problem in the first place and how it could be addressed? <3 |
The root cause is the app you are testing is changing the dom underneath - so cypress gets an element but before it can click it, the app has removed it from the dom and re rendered. Sometimes this can be solved by asserting state before the click to ensure no more dom changes will occur and the app is stable. |
@lukeapage have a very good description of this problem. I have been trying to adress something similar; When opening an edit page my application displays cached data while it queries the server for the latest version and then re-renders. Depending on system-load Cypress will manage to start clicking before the re-rendering is complete and I get the above problem or something similar. Of-course this is unusual on my own machine and very frequent on the build-server. The worst part is that the re-rendering in respons to loading from the server causes the effect of the previous clicks to be removed, thus adding a "force" will simply delay the error. I need a way to make Cypress synchronise with Vue rendering and nothing I have tried have been dependable. I have tried making our "Is loading"-flag we show to the user (that the tests waits for to not be visible) display longer but the race is still there some way. |
I proposed a solution at #695 (comment) but it didn't get any feedback. The idea is that That said, the fact that the DOM node is getting recreated could be a sign of flakiness in the application (if the component loses its state when the DOM node gets removed). But I think in many cases (especially legacy applications) it's not practically possible to fix these type of issues. |
@saas2813 Is the correct approach here not to alias that call to the backend, then wait for that server request to provide a response...and then proceed accordingly? Perhaps I'm missing something regarding the implementation, but we do this frequently without issue (in a React-based app). |
At Airbnb we have a React app that uses the Progressive Hydration technique discussed in this presentation: https://www.youtube.com/watch?v=k-A2VfuUROg As such, we have chunks of our DOM that become hydrated in idle callbacks after the page load event has fired. Due to the way that Cypress works, this has caused quite a bit of flake in our tests because elements often end up getting swapped out between the The naive approach to work around this is to add To make this better, we've developed a custom Cypress command called https://gist.github.com/lencioni/7ba04e0f92558f49454c19c44cf3bc5c We are currently only testing in browsers that support requestIdleCallback, so it is possible that when we roll this out to other browsers where we have to polyfill that, we will need to adjust this some--e.g. maybe we should wait for a couple of consecutive non-mutated DOM checks before moving forward. I hope this helps anyone else running into these types of issues. In the future, it might be nice if Cypress was enhanced to do this style of waiting when visiting routes, so we could avoid dropping these |
Are people still regularly seeing this error in the latest version of Cypress? There have been a lot fewer comments in here since January. My theory is that people are now more regularly seeing the error:
which is a more accurate error message than the effective width and height one when the element is no longer in the DOM. We have an issue to address this here: #7306 |
Sadly i have not been able to upgrade because of performance problems with the latest versions of Cypress that will probably never be fixed, so i'm considering switching to another solution. |
Closing this issue and referring to #7306 since there have been no comments on this issue since 4.4.1 of Cypress was released, where we implemented a clearer error message in this case that used to show as the 0x0 error message:
If you're experiencing a bug similar to this in Cypress, please open a new issue with a fully reproducible example that we can run. There may be a specific edge case with the issue that we need more detail to fix. |
I was also having troubles with this with a specific case so i tried chaining the two assertions: |
Hi there,
I'm encountering some flaky tests due to an element not being considered visible by Cypress, I don't understand what makes an element visible or not visible by Cypress and was hoping someone could clarify it for me.
Since version 0.20 tests randomly decide to fail with this message:
This element '<a.sc-cqpYsc.cmkxre>' is not visible because it has an effective width and height of: '0 x 0' pixels.
.However, when I inspect it is definitely has a size bigger then 0 by 0, as you can see in the screenshots.
Failing test due to click timeout:

Item highlighted by Cypress:

Chrome inspect of the element:

Now, I can "fix" this by adding
{ force: true }
to the click, but I would like to understand why this results in flaky behaviour (both headless and using the cypress UI).locally: OSX 10.12.6
CI: Debian Stretch (Docker container node:6.11.3-stretch)
0.20.0 & 0.20.1
Version 61.0.3163.100 (Official Build) (64-bit) (locally)
Is this a Feature or Bug?
Bug?
Current behavior:
cy.click() failed because element is not visible
The text was updated successfully, but these errors were encountered: