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 |
可以使用
爪哇:
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); |
使用驱动程序发送键,如pagedown或dowsnow键,以使元素进入视图。我知道这个解决方案太简单了,可能不适用于所有情况。
用于将元素滚动到视图中的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); |
在上面的语句中,
我试过上面的代码,它对我有用。
我有一个完整的帖子和视频:
如果你认为其他的答案太老套,那么这个答案也太老套了,但是没有涉及到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的重复解决方案,但添加了一个等待元素。
否则,如果对元素执行某些操作,则可能会出现
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 |
然后做你想做的。