cypress-io / cypress

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

Sticky elements within a fixed container are not properly taken into account when scrolling to an element #4233

Closed johanneslumpe closed 2 years ago

johanneslumpe commented 5 years ago

Current behavior:

This bug is related to #565 / #571

A typical use case for fixed containers are modals which fully overlay an application. In our case the fixed container is used to dim the application while displaying a modal or side panel within said container. The content within the dimmed overlay container is scrollable, but the container itself is not. I was able to break the test for #565 by making minimal adjustments to the fixture, which is included in the test repo.

As soon as a sticky element is nested within a fixed container, Cypress scrolls the element too far, so it ends up below the sticky header.

sticky elements -- additional example with side panel -- can click the first tr (failed) sticky elements -- issue 565571 with updated fixture -- can click the first tr (failed)

Desired behavior:

Cypress should take sticky headers into account when scrolling, even when they are within a fixed element and clicking on an element should succeed.

Steps to reproduce: (app code and test code)

A repo (based on https://github.com/cypress-io/cypress-test-tiny) containing two failing test cases can be found at https://github.com/johanneslumpe/cypress-sticky-header-bug

Versions

Cypress 3.3.0 Chrome 74 Mac OS

ShonP commented 5 years ago

+1

asam139 commented 4 years ago

I have the same problem with a sticky element. Please, I need to resolve this and any help all be helpful.

Moke96 commented 4 years ago

Still relevant in 3.8.2

tnrich commented 4 years ago

I'm definitely still seeing issues with cypress scrolling elements under a sticky header.

KatieMFritz commented 4 years ago

Related to #871 . Lots of people (including me) having trouble with elements getting scrolled under a sticky header and thus not visible.

jennifer-shehane commented 4 years ago

The first example provided here is actually not a bug. The container is not scrollable - there's no way to click on the 'a' element in the example outside of Cypress.

index.html: https://raw.githubusercontent.com/johanneslumpe/cypress-sticky-header-bug/5fd91e18000604c632556754b8c8a8f366ab79af/cypress/fixtures/issue-565-updated.html

it('can click the first tr', () => {
  cy.viewport(400, 400)
  cy.visit("index.html")
  cy.get("td:first").click()
})

No scrollbar available - the 'a' td is unclickable normally.

Screen Shot 2020-04-08 at 12 35 25 PM

The second example is the bug - you can scroll to the a td element normally and click the element.

Simplest code to reproduce

index.html

<!DOCTYPE html>
<html>
<body>
  <div class="overlay-background" style="position: fixed; width: 300px">
    <div class="sidepanel" style="position: absolute; height: 300px; overflow: auto;">
      <header class="sticky-header" style="position: sticky; top: 0; left: 0; height: 40px; background-color: blue;">
        sticky header
      </header>
      <div style="height: 500px">
        <p>content to scroll to</p>
      </div>
    </div>
  </div>
</body>
</html>
it('can click the p behind sticky header', () => {
  cy.viewport(400, 400)
  cy.visit('index.html')
  cy.get('p').click()
})

pedroAVS commented 4 years ago

Hi, is there any news regarding this issue? I think I'm having some related issue aswell. My front end is under react and the dev team is using a dropdown list that pops up from the top, once the dropdown menu is clicked. This list is a fixed element and it doesn't appear anywhere within the viewport. after some debugging i've found that the list is actually spawning outside the browser window, below or above the test runner.

2020-06-22_14h06_19 here it is found below

2020-06-22_14h21_45 here it is on top

those screenshots is after clicking the dropdown button, that should trigger the list to appear.

In both cases the element is not found by cypress, even though that after clicking on the dropdown menu, the list appears in the html document.

iozzyi commented 4 years ago

I have the same issue, but the frustrating thing is that the element is already visible in the page so scrolling was not necessary. Couldn't there be an option to turn off the auto-scrolling option? Or otherwise to set the fixed-height at the top when typing so that it doesn't scroll so much?

Also worth noting, in my case the scrollbar wouldn't have allowed the page to scroll as much as Cypress has scrolled it for the input box to be at 0px from the top.

image image

getulionm commented 4 years ago

Looking for updates or workarounds on this please 🙏 Any other tips for handling sticking elements?

kennyg1989 commented 3 years ago

Still a problem in 5.2.0

BernieCr commented 3 years ago

I ran into the same issue with a sticky header. As a workaround I set the default scroll behavior for the test to 'center'. Another option would be to set scrollBehavior to false for the test and do all scrolling manually.

it('should test something', { scrollBehavior: 'center' }, () => {
     cy.get('#myelemtent').click();
});
jennifer-shehane commented 3 years ago

Workaround

Since 6.1.0, you can pass the scrollBehavior option to .click() to prevent Cypress from scrolling on click or to scroll in a different position. This is a workaround for this issue.

it('can click the p behind sticky header', () => {
  cy.viewport(400, 400)
  cy.visit('index.html')
  cy.get('p').click({ scrollBehavior: false })
})
<html>
<body>
  <div class="overlay-background" style="position: fixed; width: 300px">
    <div class="sidepanel" style="position: absolute; height: 300px; overflow: auto;">
      <header class="sticky-header" style="position: sticky; top: 0; left: 0; height: 40px; background-color: blue;">
        sticky header
      </header>
      <div style="height: 500px">
        <p>content to scroll to</p>
      </div>
    </div>
  </div>
</body>
</html>
Screen Shot 2021-03-18 at 2 58 47 PM
ilovett commented 3 years ago

I would suggest a new ScreenShotOption

hideFixedElements: ['#appbar']
  1. First screen shot takes full screenshot (before hiding)
  2. Scroll to new position
  3. Hide all elements by selector in hideFixedElements
  4. Take Screenshot
  5. Scroll Down
  6. Repeat 4-5 until at bottom
  7. Restore hidden elements
gkatsanos commented 2 years ago

hey @jennifer-shehane , unfortunately The workaround does not work - we've been getting false negatives for months because of our sticky header, we're so desperate we're thinking of abandoning cypress at all. Tried all the scrollBehavior options, the element keeps getting hidden behind the sticky header.

test:

describe('Modal Dialogs', () => {
  describe('Contact form', () => {
    it('should succesfully be submitted if fields completed', () => {
      cy.visit('https://www.wlw.de/de/firma/qa-testing-sa-1927745')
      cy.get('[data-test=contact-button]').each(($el) => {
        cy.wrap($el).click({ scrollBehavior: 'bottom' }) // tried 'nearest', 'false', 'center' 
        cy.get('.modal__dialog').within(() => {
          cy.get('.pell-content').type('Test message') // Click on button
          cy.get('#full-name').type('Max Mustermann')
          cy.get('#email').focus().type('max.mustermann@musterfirma.de')
          cy.get('.form-terms').within(() => {
            cy.get('.checkbox').click()
          })
          cy.get('.contact-form__submit-button').click()
        })
        cy.get('.contact-form__feedback').should('be.visible')
        cy.get('.modal__close').click()
      })
    })
  })
})

(there are random fails on this test depending on the animation speed maybe)

davidmunechika commented 2 years ago

Hi @gkatsanos , thanks for bringing this up. I was able to reproduce your issue and it doesn't appear to be a problem with scrollBehavior at all. When running the tests, it appears the Cookies modal is covering up the form, which is preventing some of the commands from successfully executing. In fact, when the modal is present, it appears you cannot scroll the page in any direction, so changing the scrollBehavior option is not going to resolve this. If you look at the screenshots below, the test fails when the modal is present and the test succeeds if I specifically close the modal, allowing the form to be visible. I hope this helps you resolve this issue.

Screenshot 2021-11-01 at 11 01 38 AM Screenshot 2021-11-01 at 11 02 15 AM
gkatsanos commented 2 years ago

@davidmunechika thank you for checking this - I forgot to mention that we by-pass the cookie warning by hard-saving the value in our support/index.js file:

before(() => {
  cy.setCookie(
    'CookieConsent',
    // eslint-disable-next-line max-len
    '{stamp:%27vjpVJCpe9QeDb7Ba7mmn6GE5TtAmzBnDEVA8csu2OzT/ZGu6jV7YGw==%27%2Cnecessary:true%2Cpreferences:true%2Cstatistics:true%2Cmarketing:true%2Cver:4%2Cutc:1620824505756%2Cregion:%27gr%27}'
  )
})

so our fail is a different one. Thank you in advance for checking it!

gkatsanos commented 2 years ago

@chrisbreiding I guess it's about to be fixed/released in the next minor version upgrade?

davidmunechika commented 2 years ago

@gkatsanos I tested your issue after adding the support file to bypass the cookie warning and it should be fixed by this PR (https://github.com/cypress-io/cypress/pull/18441) which will go out in the next release. The test consistently passes for me now, but feel free to reach out again if you continue to have issues.

cypress-bot[bot] commented 2 years ago

Released in 9.0.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to Cypress v9.0.0, please open a new issue.