Implement ability to auto-scroll to the center of the viewport #5764

Closed
lukeis opened this Issue Mar 4, 2016 · 12 comments

Comments

@lukeis
Member

lukeis commented Mar 4, 2016

Originally reported on Google Code with ID 5764

In this example, I have a floating footer which will always remain at the bottom of
the page, regardless of the size of the page.  The issue is that, depending on the
screen resolution of the machine being used to run the test, or the amount of content
on the page, the footer may cover some links (or other clickable elements) on the page.


For a manual testers, they would scroll the page further, however, WebDriver does not
scroll the page far enough, as WebDriver believes the link is already visible on the
page.

Likewise, if the content on the page is long enough, WebDriver will automatically scroll
the page, but not far enough.  The automatic scroll to bring the element into view
will still leave the element under the footer.

Using the following code and attached html as example:

IWebDriver driver = new InternetExplorerDriver();
driver.Navigate().GoToUrl(@"file:///Example.html");

// Put a breakpoint here.  Size the screen so that the footer is overlaid on top of
the link.  
IWebElement element = driver.FindElement(By.LinkText("Click me!"));
element.Click();

The behavior with the InternetExplorerDriver and FirefoxDriver, is that no exceptions
are thrown, the link is just not clicked, so it fails silently.

With the ChromeDriver, I will get a ElementNotVisibleException, which is desirable,
because then I can then have the test scroll the page further, using a vertical offset
to ensure the element will not be located under the footer.

The desired behavior is that this scenario could be detected with visibility checks
(checking the IsDisplayed will return True when covered by the toolbar), so that the
WebDrivers can scroll to the correct location.  Otherwise, having a ElementNotVisibleException
thrown in these instances would be beneficial so that this scenario can be gracefully
handled.

This scenario was tested using the C# 2.33 bindings with the corresponding IEDriverServer
(2.33) and ChromeDriver 2 (v2.0.204324.dyu)

Reported by nathandace on 2013-06-11 20:23:54


- _Attachment: [Example.html](https://storage.googleapis.com/google-code-attachments/selenium/issue-5764/comment-0/Example.html)_
@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
+1 for coming up with some fix for this even though I'm guessing that the implementation
may not be easy. I'm working with an application that does this sort of thing in multiple
places and it's definitely a pain to deal with. And for people that are new to automation
that encounter this its not going to be easy for them to figure out why the failure
is occurring.

Reported by jfitisoff on 2013-08-01 00:04:22

Member

lukeis commented Mar 4, 2016

+1 for coming up with some fix for this even though I'm guessing that the implementation
may not be easy. I'm working with an application that does this sort of thing in multiple
places and it's definitely a pain to deal with. And for people that are new to automation
that encounter this its not going to be easy for them to figure out why the failure
is occurring.

Reported by jfitisoff on 2013-08-01 00:04:22

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
I'm having this same problem with a floating header. How are you using a vertical offset
to manually scroll the page?

Reported by Scott.Sheri on 2013-08-06 13:23:09

Member

lukeis commented Mar 4, 2016

I'm having this same problem with a floating header. How are you using a vertical offset
to manually scroll the page?

Reported by Scott.Sheri on 2013-08-06 13:23:09

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
If you're using ChromeDriver, you can simply try to catch the ElementNotVisibleException:

try
{
    element.Click();
}
catch (ElementNotVisibleException)
{
    // Scroll the page more and retry the click.
    ((IJavaScriptExecutor)driver).ExecuteScript("window.scrollBy(" + xOffset + ","
+ yOffset + ");");
    element.Click();
}

However, the InternetExplorerDriver and FirefoxDriver do not throw the ElementNotVisibleException,
so the click fails silently.

Reported by nathandace on 2013-08-06 15:08:40

Member

lukeis commented Mar 4, 2016

If you're using ChromeDriver, you can simply try to catch the ElementNotVisibleException:

try
{
    element.Click();
}
catch (ElementNotVisibleException)
{
    // Scroll the page more and retry the click.
    ((IJavaScriptExecutor)driver).ExecuteScript("window.scrollBy(" + xOffset + ","
+ yOffset + ");");
    element.Click();
}

However, the InternetExplorerDriver and FirefoxDriver do not throw the ElementNotVisibleException,
so the click fails silently.

Reported by nathandace on 2013-08-06 15:08:40

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
As a workaround for IE, you can try setting the elementScrollBehavior capability. Setting
it to 0 (the default) causes elements to scroll to the top of the viewport. Setting
it to 1 causes the elements to scroll to the bottom of the viewport. These correspond
to the behaviors of the JavaScript scrollIntoView()[1] function.

[1] https://developer.mozilla.org/en-US/docs/Web/API/element.scrollIntoView

Reported by james.h.evans.jr on 2013-08-13 21:34:46

Member

lukeis commented Mar 4, 2016

As a workaround for IE, you can try setting the elementScrollBehavior capability. Setting
it to 0 (the default) causes elements to scroll to the top of the viewport. Setting
it to 1 causes the elements to scroll to the bottom of the viewport. These correspond
to the behaviors of the JavaScript scrollIntoView()[1] function.

[1] https://developer.mozilla.org/en-US/docs/Web/API/element.scrollIntoView

Reported by james.h.evans.jr on 2013-08-13 21:34:46

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
Issue 6095 has been merged into this issue.

Reported by barancev on 2013-08-20 20:16:03

Member

lukeis commented Mar 4, 2016

Issue 6095 has been merged into this issue.

Reported by barancev on 2013-08-20 20:16:03

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
How about scrolling the element to the middle of the viewport rather than the top or
bottom?

I'm currently working around this using the AdvancedUserInteractions API to scroll
past the element in question to account for the height of the overlaid navbar. Yuk:

var builder = new Actions(driver);
var action = builder.MoveToElement(element, 0, -offset);
action.Perform();

Reported by jim.liddell on 2013-09-10 15:31:03

Member

lukeis commented Mar 4, 2016

How about scrolling the element to the middle of the viewport rather than the top or
bottom?

I'm currently working around this using the AdvancedUserInteractions API to scroll
past the element in question to account for the height of the overlaid navbar. Yuk:

var builder = new Actions(driver);
var action = builder.MoveToElement(element, 0, -offset);
action.Perform();

Reported by jim.liddell on 2013-09-10 15:31:03

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member

Reported by barancev on 2013-10-20 08:32:45

  • Labels added: Type-Enhancement, Component-WebDriver
  • Labels removed: Type-Defect
Member

lukeis commented Mar 4, 2016

Reported by barancev on 2013-10-20 08:32:45

  • Labels added: Type-Enhancement, Component-WebDriver
  • Labels removed: Type-Defect
@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
This is now happening to my tests since upgrading from 2.37 to 2.39. When clicking an
element on giffgaff.com, it scrolls down the page and clicks on the floating header
as opposed to clicking on the element. This often results in tests failing as instead
of clicking a 'submit' button, it clicks on the logo causing the home page to load.

Reported by Chris@giffgaff.co.uk on 2014-01-16 16:21:16

Member

lukeis commented Mar 4, 2016

This is now happening to my tests since upgrading from 2.37 to 2.39. When clicking an
element on giffgaff.com, it scrolls down the page and clicks on the floating header
as opposed to clicking on the element. This often results in tests failing as instead
of clicking a 'submit' button, it clicks on the logo causing the home page to load.

Reported by Chris@giffgaff.co.uk on 2014-01-16 16:21:16

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
I'm also facing the same issue. Its critical to us. Please fix it asap. 

Thanks in advance. 

Reported by devendra4you on 2014-06-03 06:10:22

Member

lukeis commented Mar 4, 2016

I'm also facing the same issue. Its critical to us. Please fix it asap. 

Thanks in advance. 

Reported by devendra4you on 2014-06-03 06:10:22

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member
Scrolling the element to the middle of the viewport is an excellent idea!

As a workaround, I've written a short driver extention that does the trick when needed.
 Of course you'll have to change the offset (in my case, 100):

public static IWebElement ScrollToElement(this IWebDriver driver, By by)
{
    IWebElement element = driver.FindElement(by);
    IJavaScriptExecutor js = driver as IJavaScriptExecutor;
    js.ExecuteScript("window.scrollTo(" + element.Location.X + "," (element.Location.Y
- 100) + ");");
    return element;
 }

Reported by luckyben on 2014-06-10 13:21:40

Member

lukeis commented Mar 4, 2016

Scrolling the element to the middle of the viewport is an excellent idea!

As a workaround, I've written a short driver extention that does the trick when needed.
 Of course you'll have to change the offset (in my case, 100):

public static IWebElement ScrollToElement(this IWebDriver driver, By by)
{
    IWebElement element = driver.FindElement(by);
    IJavaScriptExecutor js = driver as IJavaScriptExecutor;
    js.ExecuteScript("window.scrollTo(" + element.Location.X + "," (element.Location.Y
- 100) + ");");
    return element;
 }

Reported by luckyben on 2014-06-10 13:21:40

@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member

Reported by barancev on 2014-10-01 19:43:00

  • Status changed: Duplicate
  • Merged into: #4175
Member

lukeis commented Mar 4, 2016

Reported by barancev on 2014-10-01 19:43:00

  • Status changed: Duplicate
  • Merged into: #4175
@lukeis

This comment has been minimized.

Show comment
Hide comment
@lukeis

lukeis Mar 4, 2016

Member

Reported by luke.semerau on 2015-09-17 18:17:21

  • Labels added: Restrict-AddIssueComment-Commit
Member

lukeis commented Mar 4, 2016

Reported by luke.semerau on 2015-09-17 18:17:21

  • Labels added: Restrict-AddIssueComment-Commit
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.