cypress-io / cypress

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

Cypress scrollTo() & scrollIntoView() doesn't work properly #29921

Open jan-surincik opened 1 month ago

jan-surincik commented 1 month ago

Current behavior

I am trying to test the scroll lock service in our application, test scenario: The user opens the nav-bar, after that, the body is locked and the user is not able to scroll through the body

so this service adds style to the body overflow: hidden and height: 100vh, so the body is not scrollable after clicking on the nav item

Basic test:

 it('should test if the body is scrollable', () => {
      cy.get('body').scrollTo('bottom') // doesn't work element is not scrollable but it should work
}

I also tried invoking CSS to the body element to make sure the body is scrollable

 it('should test if body is scrollable', () => {
      cy.get('body').invoke('css', 'overflow', 'auto');
      cy.get('body').scrollTo('bottom'); // should be scrollable but cypress is not able to scroll
}

I have to note, that changing the viewport also doesn't help and also I tried to solve this with scrollToView(), but this method totally ignores overflow: 'hidden'or overflow: 'clip' and it always scrolls no matter if the body is locked. Our scroll-lock works correctly and it was manually tested.

Errors:

Timed out retrying after 4000ms: cy.scrollTo() failed because this element is not scrollable:
<body style="overflow: auto;">...</body>

If someone has some workaround to this I will be happy if you share it, hopefully, I described my problem understandably.

Desired behavior

If the element has overflow: 'auto' or is scrollable Cypress should be able to use scrollTo in this element.

example: cy.get('body').scrollTo('bottom') - should work on the scrollable element

and if the element is not scrollable scrollIntoView() should fail the test

example: cy.get('body').scrollIntoView({offset: {top: 500, left: 0}}); - should not work on non-scrollable element

Test code to reproduce

scrollTo():

 it('should test if the body is scrollable', () => {
      cy.get('body').scrollTo('bottom') // doesn't work element is not scrollable but it should work
}
 it('should test if body is scrollable', () => {
      cy.get('body').invoke('css', 'overflow', 'auto');
      cy.get('body').scrollTo('bottom'); // should be scrollable but cypress is not able to scroll
}

scrollIntoView()

// this test should fail
it('should test if body is not scrollable', () => {
      cy.get('body').invoke('css', 'overflow', 'clip');
      cy.get('body').scrollIntoView({offset: {top: 500, left: 0}}); 
}

Cypress Version

v12.17.4

Node version

v18.20.1

Operating System

macOs 14.5

jennifer-shehane commented 1 month ago

@jan-surincik It would be helpful if you could provide an example HTML file that shows the styles / elements being used to demonstrate the problem.

Usually when I run into this problem its because I'm trying to scroll the wrong element. Like I think the body has the scroll, but it's really some inner element, but I couldn't tell if this is the case without an example.