cypress-io / cypress

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

cy.screenshot() function does not wait properly for the scrolling to be "done" on some sites, resulting in a only 1 pixel high screenshot on some sites #28674

Open mduivcap opened 9 months ago

mduivcap commented 9 months ago

Current behavior

Only on certain websites, I have issues with the screenshot functionality. After an investigation with a frontend engineer, we figured out that it seems like the screenshot is being taken while .scrollIntoView() is still busy. This results in a screenshot that is only 1 pixel high. Or if you fiddle around with cy.wait() and certain order of commands, you will also notice a screenshot with the full height, but, partially gray image.

Desired behavior

The screenshot() function to wait for the scroll to finish before taking a screenshot. (See first example in the test code below)

Test code to reproduce

Here two examples.

The first one is how I expect it to work.

cy.visit("https://www.nos.nl")
cy.get("footer").screenshot("nos-footer");

This will generate a screenshot of the footer, as expected.

Now the example where it fails

cy.visit("https://www.koninklijkhuis.nl")
cy.get(".site-footer").screenshot("koninklijkhuis-footer");

This will result in a screenshot of only 1 pixel high.

A workaround I found to still make a proper screenshot is the following (but I really don't want this fixed wait)

cy.visit("https://www.koninklijkhuis.nl")
cy.get(".site-footer").scrollIntoView({ duration: 750 });
cy.wait(1000);
cy.get(".site-footer").screenshot("koninklijkhuis-footer");

If you play around with the duration and the wait (make it half the time for example) you will notice you will also get the half gray screenshot.

Cypress Version

13.6.1

Node version

18.15.0

Operating System

Windows 11 - Version 10.0.22621 Build 22621

Debug Logs

Chrome Version 120.0.6099.200 (Official Build) (64-bit)

Other

No response

KoenBrouwer commented 9 months ago

@mduivcap I can confirm that we're facing the same issue. We're seeing this behaviour also on the latest macOS and in our CI with Docker on Node 20+.

Also, I suspect that your 750ms and 1000ms timeouts are based on the length of the pages that you're testing (since you're scrolling to the footer). This shouldn't be necessary. Artificially waiting a few seconds might be a solution for low impact tests, but this drastically slows down automated tests in large quantities. In this context, it is highly important that we have a command where we can rely on the viewport being done with scrolling before the screenshot gets taken.

mduivcap commented 9 months ago

Also, I suspect that your 750ms and 1000ms timeouts are based on the length of the pages that you're testing (since you're scrolling to the footer).

That is correct. I did enter 750ms for the scrolling and 1000ms wait so there is enough time for the scrolling to be done before I trigger the screenshot function on this particular page. On less high pages I can do with less, on larger pages I might need slightly more. But so far 750ms scroll & 1000ms fixed wait seems to be a sweet spot in my case. I also noticed that when I made the wait less than 250ms difference from the scrolling like it's in this example (e.g. 750ms scroll and 800ms wait), the screenshot also failed in some way

mduivcap commented 8 months ago

The workaround does not seem to work for images that are higher than the screensize (like a photoalbum). The first part of the screenshot will be fine. but since the screen needs to scroll again for the next part, it looks like stitching went wrong (see referenced tickets), but in fact it the same issue with the screenshot function not waiting for the scrolling to be done. So unfortunatelly at this point I can't use Cypress to create reliable screenshots for me and so far all of the plugins for image compare (that underwater use the screenshot method) that I tried suffer from the same issue as I;ve described here above.

mduivcap commented 8 months ago

Maybe Cypress can implement something like they do in Playwright. Which is making multiple screenshots until there is no difference between the two that are taken (a.k.a. no more scrolling/animation) and than compare the last one with the reference image. I tried and with Playwright I have no issues with the same page/elements that give me issues with Cypress

https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-2

toHaveScreenshot() Added in: v1.23 This function will wait until two consecutive page screenshots yield the same result, and then compare the last screenshot with the expectation.

mduivcap commented 1 week ago

Did anyone found the time to investigate this issue?

jennifer-shehane commented 1 week ago

@mduivcap No, we're not currently prioritizing looking at this.