cypress-io / cypress

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

Question: Is scroll into view supposed to scroll container elements with overflow:scroll;? #1423

Closed marmite22 closed 6 years ago

marmite22 commented 6 years ago

Before I log a detailed issue, can someone tell me if the scrollIntoView() function supposed to scroll elements or does it only scroll the window?

I have a test that is failing because an element is inside a menu that scrolls.

cy.get('.blade1 .back-icon').scrollIntoView().click();
CypressError: Timed out retrying: cy.click() failed because this element is not visible:

<span class="back-icon coh-icon-angle-double-left" ng-click="cbm.back()" role="button" tabindex="0"></span>

This element '<span.back-icon.coh-icon-angle-double-left>' is not visible because its content is being clipped by one of its parent elements, which has a CSS property of overflow: 'hidden', 'scroll' or 'auto'

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

https://on.cypress.io/element-cannot-be-interacted-with

http://test-drupal.cohesion.dx/admin/cohesion/cohesion_custom_styles/add/layout
kuceb commented 6 years ago

Cypress should scroll to it, you shouldn't even need to use .scrollIntoView. My first thought would be that the element can't be revealed by just scrolling, potentially there's an event handler that's triggering some javascript that in turn reveals the element.

marmite22 commented 6 years ago

I don't think there is anything special. It's a div with

    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;

Its parent is absolutely positioned and it has a bunch of content.

This screenshot seems to show the issue. I'm trying to click the blue circular button at the top but the menu hasn't quite scrolled all the way to the top. I've tried telling the click to fire on the bottom left of the icon and that still gives the same error about it being clipped.

image

kuceb commented 6 years ago

@marmite22 Is it possible to minimally reproduce this in another repo? I haven't had luck reproducing it myself.

marmite22 commented 6 years ago

I will try and create something. Thank you for your help.

brian-mann commented 6 years ago

The root cause of this problem explained in other issues described here:

I don't have a simple solution today. This whole subsystem of Cypress is very complex.

marmite22 commented 6 years ago

Something similar to force: true that only bypassed the rules on scrolling would be super useful. Perhaps a way of configuring force: true to only ignore certain rules.

brian-mann commented 6 years ago

{ force: true } does avoid scrolling currently. There's no need for .scrollIntoView() if you're using force on an action command.

marmite22 commented 6 years ago

My issue with {force: true} is that it's a bit heavy handed because, as well as avoiding scrolling, it also bypasses a lot of other checks that I would like it to still make (ensure it is visible, ensure it is not readonly, ensure it is not disabled, ensure it is not covered etc).

marmite22 commented 6 years ago

Thank you for your help with this. I think the issue is caused because elements in the menu are rendered with AngularJS. Perhaps at the point I'm trying to click the render hasn't finished or something so it doesn't correctly scroll.

I have changed how my test is working and the issue seems to have gone but both my test and the code/markup I'm testing are pretty hard to break down into a minimal reproduction.

One thing I have added that seems to have made a lot of my tests less flakey when using AngularJs is a command that waits for Angular to announce that it's ready and has finished digesting:

Cypress.Commands.add('waitUntilAngularStable', () => {
        getAngular().then((angular) => {
            return new Cypress.Promise(resolve => {
                angular.getTestability('body').whenStable(() => {
                    resolve();
                });
            });
        });
});

I thought it might be helpful for others.

bahmutov commented 6 years ago

@marmite22 good point on waiting for Angular to update and rerender - I would like to include a short example showing this custom command to fight Angular flake. What's a good short Angular code that can demo the flake? Is it something that schedules an action to update GUI? Maybe something else?

marmite22 commented 6 years ago

I suspect it's caused when you have something in your view bound to data that is loaded asynchronously.

This is the article I found that lead me to the solution I wrote http://agibalov.io/2017/05/19/How-do-Protractor-and-Angular-synchronize/

This article discusses what seems like a similar issue (only with React) https://glebbahmutov.com/blog/cypress-tips-and-tricks/ (see section "Wait on the right thing")

jennifer-shehane commented 3 years ago

In Cypress 6.1.0, there’s a new scrollBehavior configuration option that controls the viewport position when an element is scrolled prior to action commands. Possible values are 'top', 'bottom', 'center', 'nearest', and false, with 'top' being the default. scrollBehavior: false disables scrolling altogether. scrollBehavior can be specified in global configuration, test configuration or individual action commands via options.

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.