使用Selenium将元素滚动到视图中

Scroll Element into View with Selenium

Selenium 1.x或2.x中是否有任何方法可以滚动浏览器窗口以使由xpath标识的特定元素在浏览器视图中?Selenium中有一个focus方法,但它似乎无法在Firefox中滚动视图。有人对怎么做有什么建议吗?

我需要这样做的原因是我正在测试页面上某个元素的单击。不幸的是,除非元素可见,否则事件似乎不起作用。我无法控制在单击元素时触发的代码,因此无法调试或对其进行修改,因此,最简单的解决方案是将该项滚动到视图中。


在滚动方面做了很多尝试,但是下面的代码提供了更好的结果。

这将滚动直到元素在视图中:

1
2
3
4
5
WebElement element = driver.findElement(By.id("id_of_element"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500);

//do anything you want with the element


可以使用org.openqa.selenium.interactions.Actions类移动到元素。

爪哇:

1
2
3
4
WebElement element = driver.findElement(By.id("my-id"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();

Python:

1
2
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.sl.find_element_by_id('my-id')).perform()


1
2
JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("javascript:window.scrollBy(250,350)");

你可能想试试这个。


如果您想使用SeleWebDever在Firefox窗口上滚动,其中一种方法是在Java代码中使用JavaScript。要向下滚动(到网页底部)的javascript代码如下:

1
2
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0, Math.max(document.documentElement.scrollHeight, document.body.scrollHeight, document.documentElement.clientHeight));");


Selenium 2尝试滚动到元素,然后单击它。这是因为硒2不会与元素相互作用,除非它认为它是可见的。

滚动到元素是隐式的,因此您只需要找到该项,然后使用它。


1
2
webElement = driver.findElement(By.xpath("bla-bla-bla"));
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", webElement);

如需更多示例,请访问此处。都是俄语,但是Java代码是跨文化的:


针对任何元素并发送下键(或上/左/右)似乎也可以。我知道这是一个有点黑客,但我也不太喜欢用javascript来解决滚动问题。


您可以使用此代码段滚动:

C.*

1
2
3
var element = Driver.FindElement(By.Id("element-id"));
Actions actions = new Actions(Driver);
actions.MoveToElement(element).Perform();

给你了


根据我的经验,当页面上有多个可滚动部分时,Selenium WebDriver不会自动滚动到单击时的元素(这很常见)。

我使用的是Ruby,对于我的AUT,我不得不按照下面的方式对click方法进行猴子补丁;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Element

      #
      # Alias the original click method to use later on
      #
      alias_method :base_click, :click

      # Override the base click method to scroll into view if the element is not visible
      # and then retry click
      #
      def click
        begin
          base_click
        rescue Selenium::WebDriver::Error::ElementNotVisibleError
          location_once_scrolled_into_view
          base_click
        end
      end

'location_once_scrolled_into_view'方法是WebElement类上的现有方法。

我承认你可能不使用Ruby,但它应该给你一些建议。


这对我很有用:

1
2
IWebElement element = driver.FindElements(getApplicationObject(currentObjectName, currentObjectType, currentObjectUniqueId))[0];
 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", element);

使用驱动程序发送键,如pagedowndowsnow键,以使元素进入视图。我知道这个解决方案太简单了,可能不适用于所有情况。


用于将元素滚动到视图中的Ruby脚本如下所示。

1
2
3
$driver.execute_script("arguments[0].scrollIntoView(true);", element)
sleep(3)
element.click

在Selenium中,我们需要借助javascript执行器来滚动到元素或滚动页面:

1
je.executeScript("arguments[0].scrollIntoView(true);", element);

在上面的语句中,element是我们需要滚动的确切元素。

我试过上面的代码,它对我有用。

我有一个完整的帖子和视频:

How to Scroll into view in Selenium Webdriver


如果你认为其他的答案太老套,那么这个答案也太老套了,但是没有涉及到JavaScript注入。

当按钮离开屏幕时,它会断开并滚动到屏幕上,因此请重试…ε(/)

1
2
3
4
5
6
7
try
{
    element.Click();
}
catch {
    element.Click();
}


有时我还面临着硒滚动的问题。所以我用javascriptexecuter来实现这一点。

向下滚动:

1
2
3
WebDriver driver = new ChromeDriver();
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollBy(0, 250)","");

或者,也

1
js.executeScript("scroll(0, 250);");

向上滚动:

1
js.executeScript("window.scrollBy(0,-250)","");

或者,

1
js.executeScript("scroll(0, -250);");

您可能希望使用javascript访问页面滚动Web元素和网页-Selenium WebDriver:

1
2
3
4
5
6
7
8
public static void main(String[] args) throws Exception {

    // TODO Auto-generated method stub
    FirefoxDriver ff = new FirefoxDriver();
    ff.get("http://toolsqa.com");
    Thread.sleep(5000);
    ff.executeScript("document.getElementById('text-8').scrollIntoView(true);");
}


我使用这种方式滚动元素并单击:

1
2
3
4
5
6
7
List<WebElement> image = state.getDriver().findElements(By.xpath("//*[contains(@src,'image/plus_btn.jpg')]"));

for (WebElement clickimg : image)
{
  ((JavascriptExecutor) state.getDriver()).executeScript("arguments[0].scrollIntoView(false);", clickimg);
  clickimg.click();
}


在大多数情况下,滚动此代码是可行的。

1
2
WebElement element = driver.findElement(By.xpath("xpath_Of_Element"));                
js.executeScript("arguments[0].click();",element);

1
2
3
4
def scrollToElement(element: WebElement) = {
  val location = element.getLocation
  driver.asInstanceOf[JavascriptExecutor].executeScript(s"window.scrollTo(${location.getX},${location.getY});")
}


在Java中,我们可以使用JavaScript进行滚动,就像下面的代码:

1
driver.getEval("var elm = window.document.getElementById('scrollDiv'); if (elm.scrollHeight > elm.clientHeight){elm.scrollTop = elm.scrollHeight;}");

可以为"elm.scrolltop"变量指定所需的值。


下面是我如何使用PHP Selenium的WebDriver。它适用于Selenium独立服务器2.39.0+https://github.com/element-34/php-webdriver+firefox 25.0

1
2
3
4
5
$element=$session->welement("xpath","//input[@value='my val']");
$element->click();
$element=$session->welement("xpath","//input[@value='ma val2']");
$element->location_in_view(); // < -- this is the candy
$element->click();

注意:我使用的是element34 PHP WebDriver的自定义版本。但核心没有任何变化。我只是用我的"祝福"而不是"元素"。但这对案件没有影响。驱动程序作者说,"允许几乎所有的API调用直接转换WebDriver协议本身定义的内容。"因此,对于其他编程语言应该没有问题。

单击将无法在我的设置中工作。它将做一个滚动而不是点击,所以我必须点击两次而不调用"location_in_view()"。

注意:此方法适用于可以查看的元素,如类型按钮的输入。

看一看:http://code.google.com/p/selenium/wiki/jsonwireprotocol/session/:session id/element/:id/location

jsonwireProtocol的描述建议使用location+moveto,因为在视图中location是一种内部方法。


对我有用的是在浏览器窗口底部的元素上使用browser.moveMouseToElement方法。奇迹般地,它在Internet Explorer、Firefox和Chrome中发挥了作用。

我选择这个而不是JavaScript注入技术仅仅是因为它感觉不那么黑客。


我一直在使用ADF组件进行测试,如果使用延迟加载,则必须有一个单独的滚动命令。如果没有加载对象,并且您试图使用Selenium查找它,Selenium将抛出一个未找到元素的异常。


此代码对我有效:

1
2
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250, 350)");


如果不起作用,请在单击之前尝试此操作:

1
2
3
4
5
public void mouseHoverJScript(WebElement HoverElement) {

    String mouseOverScript ="if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}";
    ((JavascriptExecutor) driver).executeScript(mouseOverScript, HoverElement);
}

SeleniumUS的默认行为是滚动以使元素几乎不在视区顶部的视图中。而且,并非所有浏览器都有完全相同的行为。这是非常令人不满意的。如果您像我一样录制浏览器测试的视频,您希望元素滚动到视图中并垂直居中。

以下是我的Java解决方案:

1
2
3
4
5
6
7
8
9
public List<String> getBoundedRectangleOfElement(WebElement we)
{
    JavascriptExecutor je = (JavascriptExecutor) driver;
    List<String> bounds = (ArrayList<String>) je.executeScript(
           "var rect = arguments[0].getBoundingClientRect();" +
                   "return [ '' + parseInt(rect.left), '' + parseInt(rect.top), '' + parseInt(rect.width), '' + parseInt(rect.height) ]", we);
    System.out.println("top:" + bounds.get(1));
    return bounds;
}

然后,要滚动,您可以这样称呼它:

1
2
3
4
5
6
7
8
public void scrollToElementAndCenterVertically(WebElement we)
{
    List<String> bounds = getBoundedRectangleOfElement(we);
    Long totalInnerPageHeight = getViewPortHeight(driver);
    JavascriptExecutor je = (JavascriptExecutor) driver;
    je.executeScript("window.scrollTo(0," + (Integer.parseInt(bounds.get(1)) - (totalInnerPageHeight/2)) +");");
    je.executeScript("arguments[0].style.outline = "thick solid #0000FF";", we);
}


这是一个使用javascript的重复解决方案,但添加了一个等待元素。

否则,如果对元素执行某些操作,则可能会出现ElementNotVisibleException

1
2
3
this.executeJavaScriptFunction("arguments[0].scrollIntoView(??true);", elementToBeViewable);
WebDriverWait wait = new WebDriverWait(getDriver(), 5);
wait.until(ExpectedConditions.visibilityOf(elementToBeViewab??le));

解决方案是:

1
2
3
4
5
6
7
8
public void javascriptclick(String element)
{
    WebElement webElement = driver.findElement(By.xpath(element));
    JavascriptExecutor js = (JavascriptExecutor) driver;

    js.executeScript("arguments[0].click();", webElement);
    System.out.println("javascriptclick" +"" + element);
}

Selenium可以为一些简单的UI自动滚动到滚动条中的某个元素,但是对于延迟加载的UI,仍然需要滚动元素。

这是我在Java中用JavaScript执行器实现的。您可以在satix源代码中找到更多详细信息:http://www.binpress.com/app/satix-seleniumbased-automation-testing-in-xml/1958年

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public static void perform(WebDriver driver, String Element, String ElementBy, By by) throws Exception  {
    try{
        //long start_time = System.currentTimeMillis();        
        StringBuilder js = new StringBuilder();
        String browser ="firefox";

        if (ElementBy.equals("id")) {
            js.append("var b = document.getElementById(""
                    + Element +"");");
        } else if (ElementBy.equals("xpath")) {
            if (!"IE".equals(browser)) {
                js.append("var b = document.evaluate(""
                        + Element
                        +"", document, null, XPathResult.ANY_TYPE, null).iterateNext();");
            } else {
                throw new Exception("Action error: xpath is not supported in scrollToElement Action in IE");
            }
        } else if (ElementBy.equals("cssSelector")) {
            js.append("var b = document.querySelector(""
                    + Element +"");");
        } else {
            throw new Exception("Scroll Action error");
        }

        String getScrollHeightScript = js.toString()+"var o = new Array(); o.push(b.scrollHeight); return o;";

        js.append("b.scrollTop = b.scrollTop + b.clientHeight;");
        js.append("var tmp = b.scrollTop + b.clientHeight;");
        js.append("var o = new Array(); o.push(tmp); return o;");

        int tries = 1;
        String scrollTop ="0";
        while (tries > 0){
        try{                
            String scrollHeight = ((JavascriptExecutor)driver).executeScript(getScrollHeightScript).toString();        
            if (scrollTop.equals(scrollHeight)) {
            break;
            } else if (driver.findElement(by).isDisplayed()) {
                break;
            }
            Object o = ((JavascriptExecutor)driver).executeScript(js.toString());
            scrollTop = o.toString();
            Thread.sleep(interval);
            tries ++;
        }catch(Exception e){
            throw new Exception("Action error:"
                    +" javascript execute error :" + e.getMessage() +", javascript :" + js.toString());
            }      
        }          

    }catch (Exception e) {
        try {
                ScreenshotCapturerUtil.saveScreenShot(driver, CLASSNAME);
            } catch (IOException e1) {
            throw new Exception("Save screenshot error!", e1);
            }
        throw e;
    }
}

我同意这里的所有人,他们说"硒有一个隐含的滚动选项"。另外,如果您使用的是Selenium 1,现在已经升级到Selenium 2并查找以前版本的命令,则可以使用以下命令:

1
2
3
4
5
6
7
8
Seleniumbackeddriver.

WebDriver driver = new FirefoxDriver();
public void setUp() throws Exception {

    String baseUrl ="http://www.google.co.in/";
    selenium = new WebDriverBackedSelenium(driver, baseUrl);
}

您可以使用这两个版本的命令。


随机点击页面下方:

1
driver.findElement(By.id("ID of a web element present below")).click

然后做你想做的。