Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Do not complain when endY is bigger than document height #54

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

mehdivk
Copy link

@mehdivk mehdivk commented Jan 10, 2017

This PR fixes the bug that was reported in this issue zinserjan/wdio-visual-regression-service#14

As I mentioned in that issue, if part of an element stays out of viewport (need scroll to be visible) this plugin throws an error. Unfortunately, there is no documentation in code so I couldn't find what's the initial intention for this check. Anyway, what I've done is to use this module directly against our project and with this check removed from the code, wdio-screenshot successfully takes expected screenshot of the element.

As side note, I think we can remove the similar check for endX as well. Unit tests are passing but integration tests are failing in my end when I run npm run test:local due to some pixel ratio.

@zinserjan
Copy link
Owner

Thanks for your PR.

Unfortunately, there is no documentation in code so I couldn't find what's the initial intention for this check.

My intention for this check was to find a test case that fails. Initially I thought that when endY is bigger than the documents height, then we have to use the documentHeight instead to get properly taken screenshots. But I wasn't sure if that 's the right way so I ended up with that error instead 😄

As I can see you just removed that check. Are the screenshots really ok?
I thought that this may record screenshots from areas that are not visible for user and this should never happen.

Regardless of the direction, it would be awesome & necessary to get a simple integration test for this.

@mehdivk
Copy link
Author

mehdivk commented Jan 10, 2017

@zinserjan glad to hear that. I totally agree with the integration test for this scenario. As I mentioned I tried to run integration tests using npm run test:local and it fails in image comparison part and as far as I can say it's because of pixel ratio difference between my workstation and the one that was used to generate the reference images.

I wonder what was the environment that you ran integration tests on it (in terms of pixel ratio).

@zinserjan
Copy link
Owner

I wonder what was the environment that you ran integration tests on it (in terms of pixel ratio).

Pixelratio 1. I created some of the screenshots in a VM with Ubuntu, some others with Windows (for the IE cases).

When you are testing with a Retina Macbok, tests will fail due to the size (twice as big).

@mehdivk
Copy link
Author

mehdivk commented Jan 11, 2017

@zinserjan I managed to run integration tests on Ububunu and all of them are passing. I also added two more integration tests for the new scenario and it works. Can you help on broken tests in Travis/Appveyor please? What's the process of generating reference IE images, I just copied the Linux one.

@zinserjan
Copy link
Owner

@mehdivk

Screenshots for IE are generated by IE ;-) But I'm not sure which version it was. Must be IE 9 or IE 10.

I just looked over the test page and I didn't found any reason in my browser why this should fail and tried the tests with the old code. And indeed tests passes with the old code cause element height is smaller than documents height.

Can you update the test case in a way that it will fail with the original code? I think it should be enough to expand height of the element.

@mehdivk
Copy link
Author

mehdivk commented Jan 13, 2017

@zinserjan let's park IE screenshots for now as it's not a big deal. I updated the example so it fails with the original code and passes with the change. The endY > documentHeight usually happens when you disable the main scroll by overflow: hidden and enable it again using overflow: scroll on an inner element on the page. This is a known approach when you want to have a header that remains on top of the screen during scroll and a footer that sticks to the bottom of the screen during scrolling. Updated example tries to replicate this issue with the minimum code, so it doesn't have header/footer but uses the same approach.

Digging into this problem, I noticed that we don't have the support of scrolling an element instead of the whole page. With the original fix, we can take the screenshot but the screenshot is broken because we move up the whole page instead of a specific element. I think, allowing the user to define an element as scroll target would fix this issue. I'm open to any suggestion to fix this problem.

@zinserjan
Copy link
Owner

I noticed that we don't have the support of scrolling an element instead of the whole page.

Yes, this is right and that's the real issue here. Just disabling the endY > documentHeight check doesn't solve this.

With the original fix, we can take the screenshot but the screenshot is broken

With broken you mean kind of incomplete, right? Only the visible part of the element is recorded and the rest of the screen is filled with the next element (below the captured/desired element)?

I think, allowing the user to define an element as scroll target would fix this issue.

I think it's more complicated. We have to think about two use cases:

  • element screenshots
  • document screenshots

element screenshots

This should be easiest case, cause we could detect if the element is scrollable or inside a scrollable container. I'm not sure right now if we have to check the second condition.
If the element is scrollable, we can do it the same way like with the document and move the element with css into position, take screenshot, move again and so on until it's completely recorded.

document screenshots

That's the funny part, when we want to consider the following use case:

disable the main scroll by overflow: hidden and enable it again using overflow: scroll on an inner element on the page.

This is already complicated to handle but we can increase the complexity when you have multiple elements with that behavior (e.g. side by side with different heights). How does the final screenshot look like? I think everyone has a different opinion about that.

@mehdivk
Copy link
Author

mehdivk commented Jan 15, 2017

Yes, this is right and that's the real issue here. Just disabling the endY > documentHeight check doesn't solve this.

Indeed.

With broken you mean kind of incomplete, right? Only the visible part of the element is recorded and the rest of the screen is filled with the next element (below the captured/desired element)?

Yes, the visible part will be available in screenshot and rest will be yellow in our case (background color of the page is yellow). This is due to behavour of transform: transition

or inside a scrollable container. I'm not sure right now if we have to check the second condition.
I can't think of any solution to detect if an element is within a scrollable container in a recursive way because an element may be within a container that is not scrollable but the container itself is within another container that is scrollable.

This should be easiest case, cause we could detect if the element is scrollable or inside a scrollable container. I'm not sure right now if we have to check the second condition.
If the element is scrollable, we can do it the same way like with the document and move the element with css into position, take screenshot, move again and so on until it's completely recorded.

I propose to add an scroll option to browser.saveElementScreenshot(). If provided we use related DOM element that matches the selector for the purpose of scrolling otherwise we use html. This way we won't break existing clients of the module.

disable the main scroll by overflow: hidden and enable it again using overflow: scroll on an inner element on the page.

Well I don't think we need to mess with the elements. If consumer provides a selector as scroll target, we assume that the element is already scrollable. Am I missing something?

This is already complicated to handle but we can increase the complexity when you have multiple elements with that behavior (e.g. side by side with different heights). How does the final screenshot look like? I think everyone has a different opinion about that.
TBH I'm not user of document screenshot as I belive that it's not a good pattern to take screenshot of whole document for the purpose of CSS regression tests but other devs might use it for some other reason.

We can keep this small and add support of custom scroll to the element

@mehdivk
Copy link
Author

mehdivk commented Jan 16, 2017

@zinserjan I added my proposed solution for the scroll to the PR.

*/
let html = options && options.scroll
? document.querySelector('.test-target')
: document.documentElement;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zinserjan we can throw an error if selector doesn't match any element in DOM to help for debugging.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the query Selector should be configuration if we are adding a scroll option.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the forked repo (autopilothq/wdio-screenshot) master branch has fixed this in a later commit. But those changes haven't been merged into the autopilothq:set-scroll-area-bug-fix branch, where this PR originated from.

@zinserjan
Copy link
Owner

I'm not convinced that this will work in all cases. I still think that we need the original virtualScroll on html to get the scroll container into position and move the content with virtualScroll again and take screenshots.

I'll try to create an example. But maybe I'm wrong cause CSS isn't my daily business 😆

@mehdivk
Copy link
Author

mehdivk commented Jan 16, 2017

I'm not convinced that this will work in all cases. I still think that we need the original virtualScroll on HTML to get the scroll container into position and move the content with virtualScroll again and take screenshots.

TBH I can't think of a case in which we need to move to scroll two scrollbars at the same time to take a screenshot of an element, neither this PR is going to fix all possible situations. I updated the new tests, so scroll target is different from the element under the test to show they don't need to be the same element. I would like to think of this PR as a fix and a feature

  • Fix: Don't complain when endY > documentHeight, this is a legit case and can be reproduced using new tests

  • Feature: Allow consumer of the API to customize scroll target per test optionally.

@mehdivk
Copy link
Author

mehdivk commented Jan 23, 2017

@zinserjan is there any intention to proceed with this PR?

@mehdivk
Copy link
Author

mehdivk commented Feb 2, 2017

@zinserjan Hi. Are you still interested in this PR? We need this feature for our project and if it's not going to be merged we have to find another solution for our problem.

Thanks

@zinserjan
Copy link
Owner

@mehdivk Sorry for the delay but the new year is very time consuming and I haven't found the time, yet.

We need this feature for our project

Which of the following do you mean exacly?

  • Fix: Don't complain when endY > documentHeight, this is a legit case and can be reproduced using new tests

  • Feature: Allow consumer of the API to customize scroll target per test optionally.

At the moment I would like to avoid introducing a new option that allows the user to define a custom scroll target until #21 and #48 are resolved. My preference is a automatic scroll element detection, so that the screenshot stitching algorithm remains as a black box for the user.

@cdaringe
Copy link

cdaringe commented Apr 6, 2017

hi all. i just got x-reffed here after suffering the following error endY is out of range. i also see that it's been open a while. can i help in any way to get it movin?

@cdaringe
Copy link

cdaringe commented Apr 6, 2017

ah, & i should have asked earlier... is there a temp workaround?

@JefroB
Copy link

JefroB commented Oct 1, 2018

Just chiming in to say that this still exists. I'm also seeing a similar error with endX.

@@ -23,8 +23,6 @@ export default class BaseStrategy {
throw new Error('startY is out of range');
} else if (endX > documentWidth) {
throw new Error('endX is out of range');
} else if (endY > documentHeight) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are passing options, I would disabling this error should be in the option as well. By removing this, this is breaking expected behavior (though I think most people would be okay with it)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants