Cypress: Enable users to change the scrolling strategy

Created on 3 Nov 2017  路  50Comments  路  Source: cypress-io/cypress

Users have expressed a desire to modify how Cypress internally scrolls elements.

Related to:

Currently we pin elements to the topmost coordinate after scrolling.

Users should be able to change this strategy to be one of:

  • top
  • bottom
  • middle (don't scroll if already within screen)
  • disable (turn off all automatic scrolling)

By default, scroll element into center

  • [ ] Scrolling strategy make element cannot click #2302
proposal 馃挕 scrolling 鈫曪笍 feature

Most helpful comment

I found myself with the same issue using the latest version of cypress (as of today 3.4.0) and I ended up changing the scroll behavior before each test:

Cypress.on('scrolled', $el => {
  $el.get(0).scrollIntoView({
      block: 'center',
      inline: 'center'
  });
});

All 50 comments

Just expressing another usecase where disabling scrolling would be useful.

I am currently writing tests for mobile viewport, which in real life is never supposed to be able to scroll itself, and because of how cypress scrolls elements into view a lot of the times they end up being hidden and are not asserted correctly by .should('be.visible').

On the other hand some other elements which are normally positioned offscreen for animations become visible, and are also incorrectly asserted using visibility checks.

I think my problem touches the same area:
https://github.com/cypress-io/cypress/issues/2418

Out of curiosity, do we have an ETA on this?
Our team is having an issue with the auto-scroll behavior because it places our buttons under our sticky header, and we have to force most clicks. 馃槶

There has been no work done for this issue as of today.

We're currently working on adding customizable scroll behavior, as well as changing the default scroll behavior to scroll the element into the center of the viewport

Hey @Bkucera, will the changes here affect this proposal about reflecting scroll behavior + snapshots? https://github.com/cypress-io/cypress/issues/483

Yes

We also have issues with auto scrolling because our elements are hidden because of the navigation with position:fixed. It would be nice to add some option on click() so we can turn off just the scroll and not the other checks for example.

Same issue as @Naadaa --- fixed-positioned navbar covering clickable elements when commands automatically scroll them on top (below the navbar).

surely it can't be that hard to at least add an option to disable scrolling entirely when clicking on elements.. it would be nice to have the other options as well but at least give us a way to disable it.. this issue has been open for almost 18 months now!

if anyone else is running into this issue.. I made it go away with this hack (depends on jQuery):

    if (window.Cypress) {
      $(window).scroll(() => {
        $(window).scrollTop(0);
      });
    }

Hello everyone,

I am quite new to cypress and github and I need help.
I am trying to test the responsive design for a particular application, but I am facing the problem that also Denis Tuzhik described in his comment:

Just expressing another usecase where disabling scrolling would be useful.

I am currently writing tests for mobile viewport, which in real life is never supposed to be able to scroll itself, and because of how cypress scrolls elements into view a lot of the times they end up being hidden and are not asserted correctly by .should('be.visible').

Is there a solution or a workaround for the undesired scrolling behaviour when testing a responsive design?
I tried the option {force:true} within the get() method, but it didn't work.
I also tried an example with Cypress.dom.isHidden() that I found. But this didn't work either.
Can someone help me with this topic?

Thx a lot in advance!

@elena-george check my comment right above yours, this hack will disable the possibility of scrolling altogether. If you don't have jquery loaded then you'll have to write a vanilla-js version of my hack

Hi C-Bass, thx for the quick answer!
However I cannot understand the hack. Where should I use the if-construct:

 if (window.Cypress) {
      $(window).scroll(() => {
        $(window).scrollTop(0);
      });
    }

And what do you mean with: "have to write a vanilla-js version"? As I said, I am quite new to cypress and coding itself that's why I have to ask stupid questions :). Sorry for that!

you would add this code directly in your application. So it would be outside Cypress, in your application code..

It depends on jQuery so you can't use it without jQuery, or else you'd have to rewrite the javascript above to work without jQuery but I can't help you there.

Basically the above javascript does this: everytime the page is scrolled, it auto-scrolls back to the very top of the page. The end result is that the page cannot be scrolled and always remains scrolled to the very top. This behaviour is only active when window.Cypress is true.. in other words.. only when Cypress is running its tests so it won't affect your application outside of Cypress tests.

It is a hacky workaround but it does the job since there is currently no other way of disabling the jumpiness during tests.

Hi C-Bass,
thank you very much for the detailed answer!
I am afraid that this workaround won't do for me because on the one hand I do only the testing. Our frontend developers write the application code. On the other hand to I don't like the idea to have a hack in application code only because I want to test the responsive design in cypress.
I will explore other options like working with the chai-inViewport assertions or to use another test framework like QF Test for testing the responsive design.

Thanks again for your explanations!

I found myself with the same issue using the latest version of cypress (as of today 3.4.0) and I ended up changing the scroll behavior before each test:

Cypress.on('scrolled', $el => {
  $el.get(0).scrollIntoView({
      block: 'center',
      inline: 'center'
  });
});

Another sticky header here under which perfectly visible elements are being scrolled before trying to click them. It'd be nice for this proposal to get worked on and released. Otherwise a great experience with Cypress so far. Thanks for all the effort.

@bakjos' trick in the comment right preceding this comment is working. Not sure if it has any downsides, but things are looking better now. No need to abuse .click({ force: true }).

@brian-mann @jennifer-shehane

This issue has been alive for quite a while, has quite a few upvotes and mostly is filled with workarounds are there updates on the roadmap on when is this going to be addressed? Is there some public dashboard like https://canny.io where somebody could track position to this issue relatively to others?

Thank you!

I am also facing the same issue.
For now I found a workaround to bypass this issue.
I don't click directly. I use jquery click after getting element like this:

cy.get('#myButton').then((el)=>{ Cypress.$(el).click(); });

But I really want it the @Cypress team to resolve this issue as soon as possible.

Would this strange scrolling where I'm trying to click a context menu (that is already in view btw) also be due to the forced scroll or is something else going on?

scrollbug

I was really loving Cypress until I hit this! Seems like such a trivial and predictable issue: it's becoming more common to visually change things like banner navigation on scroll. Whilst useful in some contexts scrolling before click can lead to changes in the DOM; so it makes sense to provide an optional param to disable scroll when it is invoked.

edit: it would be useful to add a hint to the error message shown on the failed click. That currently tells me the element isn't visible which is a start; but a prompt to check if scroll might affect visibility of the clicked element would help a lot.

For me @ayyazzafar 's suggestion isn't working; but this does:

cy.get('aSelector').contains('some text').then(el => el.get(0).click());

Two years now... any plans to sort this out? It's making my tests flaky as hell and I'm having to disable a whole load of useful checks using { force: true } just to ensure Cypress doesn't scroll my element to a place where it isn't clickable when it was visible and clickable in the first instance.

@davidcole1977 the workaround we're using which works all the time is: https://github.com/cypress-io/cypress/issues/871#issuecomment-509392310

Any updates on this? This is a huge pain.

This worked for me (web-app with electron setup). Creating a custom click:

Cypress.Commands.add('clk', { prevSubject: 'element'}, (subject, options) => {
  subject.click();
  return subject;
});

and then calling it with:

cy.get('.mybutton').clk();

Clicks with no scrolling.

Seems like your beautiful scrolled event-based workaround (cf. https://github.com/cypress-io/cypress/issues/871#issuecomment-509392310) stoped working anymore in 3.6.0 馃槙 Are you seeing in the same thing @bakjos ?

@jraoult I haven't had the chance to review it on 3.6.0 but I just tested it on 3.6.1 and it seems like is working again, can you confirm?

I can confirm, the workaround is working like a charm 馃挴

I have this issue even on 3.8.2, infact with cy.get() and even cy.contains()!, I am testing a reactJs app and I have verified(By using cy.pause()) the auto-scrolling actually happens on cy.get()/contains(). Very annoying.

@bakjos 's solution doesn't work for me. I would like to be able to see the focused element (say, text field) when hovering around in the Cypress log. Sadly, every hover on a GET or TYPE causes the element in question to get forcibly scrolled to the top of the screen -- right underneath a header, totally obscured from view, just like many others have complained about in this github issue.

+1 ; please fix.

@jraoult I haven't had the chance to review it on 3.6.0 but I just tested it on 3.6.1 and it seems like is working again, can you confirm?

I still face the issue, the solution doesn't work for me. I am using [email protected] Any update of hacks for this issue???

I am facing the same issue, _get_ API is unnecessarily scrolling the page. I am using [email protected]. So clearly it's not yet been fixed.

Here is the code snippet
cy.get('.classname').screenshot('screenshot-name');

This causes the wrong screenshot when the element is getting hidden under the floating elements.
Please help me here. If there is any workaround for it, please tell me.

So, I have a navigation, that scrolls in more slowly than popping up. It's also not the expected implementation, where a top navigation has first a normal DOM flow, but when scrolling down it becomes fixed. No. It's a second navigation moving in slowly.
That's why the current Cypress implementation is detecting, that there is no navigation overlapping the current button to be visible and clicked. And as you can see, my colleagues have put a red button on the upper right corner, to let us know, that we are in QA mode, which sometimes also hides elements, that I like to click.

In fact, in a different case, I totally ignore testing the functionality of this fixed navigation, as it is quite tricky and difficult to test. I just assume it's working, because its elements are in the top of the page. I would scroll here individually per test.

As a user, I don't scroll my element to the most top corner of the window in order to click them.
In order to reflect user's behaviour, we should be able to set the default scroll behaviour to what we think, the user is doing. In my case, I think it's somewhere in the center.
Screenshot 2020-03-28 at 18 12 26

Screenshot 2020-03-28 at 18 12 27

I really wonder how web games are e2e testing their interfaces.

The workaround isn't working for me in 4.1.0. Elements keep scrolling behind my sticky header and disappearing.

This issue is still in the 'proposal' stage, some initial proof of concept work as well as background architecture work has been done, but the issue itself has no work done on it as of today, we do not have an estimate on when this will be delivered.

@jennifer-shehane wondering what it will take to move this out of proposal?

The web is built on scrolling viewports. Yet cypress resets scroll position every time you .get() an element, which is hugely problematic for testing any element interaction that might exist below the fold or within a scrolling container.

Using force: true defeats the purpose of all the built in checks that make cypress so great!
This should be a top priority for the team to address.

I'd like to also throw in my support for this fix. I'm seeing the unwanted scroll occur on the get(), and I'm sure it's the get because I removed anything else after it in the test case. Our analytics verify that the view is being cut off by the fixed nav-bar as we see in the test runner. The workaround doesn't seem to be working for us either on 4.0.2.

@JohnMCrooks Today I have made a new test using the 4.4.1 version and the workaround is working well for me

I had an issue with the workaround @bakjos posted in a specific scenario, though it worked with the majority of cases. When an element was not virtualized but was slightly off screen - it would get into an infinite loop, scrolling would trigger the scrolled event, which would run that workaround, which would scroll, triggering the workaround, and on and on. Then because react-virtualized sets pointer-events to none for 150ms after scrolling the element would never become clickable, so .click() would time out. I could work around this with click({force: true}) but hate using that because it opens you up to other problems. I made a slight tweak so it will only scroll an element once and now I don't have to use force. Hopefully this helps someone else.

let $lastEl: JQuery<HTMLElement>;
let hasScrolled = false;

Cypress.on('scrolled', ($el) => {
  if ($el.is($lastEl)) {
    if (hasScrolled) {
      return;
    }

    hasScrolled = true;
  } else {
    $lastEl = $el;
    hasScrolled = false;
  }

  $el.get(0).scrollIntoView({
    block: 'center',
    inline: 'center',
  });
});

Any updates on this?

Sorry, no updates here. We are prioritizing other work over this at the moment.

I did review the comments here and am finding a lot of people saying they need to control the scroll behavior because they have to pass force: true to a click or similar action because their element is not being regarded as visible - due to how we scroll.

We're only aware of a couple of issues where this happens in the current 4.12.1 version now - many of these issues have been resolved since this was opened.

Scrolling causes visibility error


Please open an issue

If you're having a situation where Cypress is incorrectly determining the visibility of an element because of scrolling, and it doesn't fall under the issues above, then we are not aware of it.

We suggest opening a new issue with a fully reproducible example so that we can fix the core visibility algorithm and you won't need the scrolling workaround in the first place. This will likely get your issue fixed quicker than waiting for this scrolling strategy feature.

Hey @jennifer-shehane ,

I am also facing issues with ScrollTo and ScrollIntoView methods. I wanted to scroll down the Application Under test window while running tests,to test lazy loaded ads. Scroll works fine when I am viewing the tests. But once I Minimize the test window, scroll do not work, also I do not get any kind of error.

cy.scrollTo('bottom')`
cy.window.scrollTo('bottom')`
cy.get('.container-main > .header > .title').scrollIntoView({force:true}).should('be.visible')

Try this code :

it('Scrolling',function() {
  cy.visit("https://css-tricks.com/snippets/javascript/lazy-loading-images/")
  cy.scrollTo('0%','25%')
  cy.wait(5000)
  cy.get('.fem-learning-partner').should('be.visible').and('contain.text','Our Learning Partner')
})

All this works, when I just open Cypress test window and looking on behavior of my tests doing nothing else. :(

Why scrolling fails when I am not viewing/minimizing the cypress test window ?
No issues on headless chrome, but login fails due to cross domain redirection, so I have to check on chrome headed.

Is this an open issue with Cypress ? I am not able to complete many tests cases of my project due to this issue,my application is on vue-js. Can you please suggest something. It will be a big help.
Thanks !

@Sakshi3110 There are some issues covering this here: https://github.com/cypress-io/cypress/issues/5023 But they may not all be caused by the same situation.

@jennifer-shehane Thanks! I checked #5023 , May be I also need something in my code, which keeps Test Runner/Application under test browser in ACTIVE mode. So, that focus remains active even after minimizing windows.

How long do we wait for solution?

Please provide workaround if you are not going to fix it.

Currently, this is just a proposal without any work planned in the nearest future.

Any suggestion how to test components which close itself when page is scrolled? E.g. fluent-ui contextual menu components here https://developer.microsoft.com/en-us/fluentui#/controls/web/contextualmenu#IContextualMenuProps - try to click on button and then scroll the page ... I am working on Cypress tests where I am unable to click on menu item because once menu is opened and I try to click on menu item, page is scrolled, menu closes and Cypress fails because menu item element does not exists in the DOM.

Edit:
I found workaround for this by using jQuery to click which does not autoscroll:

cy.get('.menuitem').then(el => el.trigger('click'));
Was this page helpful?
0 / 5 - 0 ratings