通过使用Java Selenium WebDriver和HTML窗口位置

我将Selenium

WebDriver与java.awt.Robot结合使用,以更好地模拟用户与Web应用程序的交互。是的,我知道可能没有必要,但是我所服务的客户都需要它。

当前,一切运行良好,但是我有一个小问题,就是我似乎找不到找到将Web元素显示在屏幕上位置的好方法。诸如标题栏,菜单栏,导航栏之类的东西都将内容向下推到物理屏幕上(Robot从中获取坐标),但对Selenium报告元素所在的位置没有影响。

当我element.getLocation();在Selenium

WebElement上调用:时,它总是为我提供相对于HTML内容呈现窗格的位置,而不是浏览器窗口本身的位置。

一个更好的示例是:driver.findElement(By.tagName("body")).getLocation();无论窗口的实际屏幕位置如何,始终返回0,0。

现在,我通过在最大化窗口后添加垂直和水平偏移量来破解它,但是不同的浏览器之间这些偏移量并不相同(例如,IE的顶部装饰所占的空间要比Firefox更大),并且每个用户可能会有所不同如果其中添加了书签工具栏,搜索栏等。

是的,我知道我可以在全屏模式下运行,但如果可能的话,我宁愿不运行。

有没有一种方法可以使用WebDriver以可靠的方式获取元素在屏幕上的物理位置?

回答:

我相信无法获得页面上元素的真实屏幕位置。

我也认为全屏模式是您最好的选择。

就是说,我写了一个RobotCalibration可以检测当前浏览器实际偏移量的类。它会打开一个特制页面,并使用Robot该类单击它。该算法从浏览器的中心开始,然后使用二等分线找到浏览器视口的左上角。

在IE8和FF18上测试。适用于最大化和窗口浏览器。已知问题:如果启用了顶部的书签工具栏,则它可能会单击某些书签,因此会重定向。它可以很容易地处理,但是如果您需要它,我留给您:)。

测试页面:

<!DOCTYPE html>

<html lang="en" onclick="document.getElementById('counter').value++">

<head>

<meta charset="utf-8" />

<title>Calibration Test</title>

</head>

<body>

<img height="1" width="1" style="position: absolute; left: 0; top: 0;"

onclick="document.getElementById('done').value = 'yep'" />

<input type="text" id="counter" value="0" />

<input type="text" id="done" value="nope" />

</body>

</html>

RobotCalibration班。它有点长,所以我建议您将其复制粘贴到您喜欢的IDE中并在其中进行探索:

import java.awt.AWTException;

import java.awt.Dimension;

import java.awt.Point;

import java.awt.Robot;

import java.awt.Toolkit;

import java.awt.event.InputEvent;

import java.nio.file.Paths;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.ie.InternetExplorerDriver;

public class RobotCalibration {

public static Point calibrate(WebDriver driver) {

return new RobotCalibration(driver).calibrate();

}

/** Time for which to wait for the page response. */

private static final long TIMEOUT = 1000;

private final WebDriver driver;

private final Robot r;

private final Point browserCenter;

private int leftX;

private int rightX;

private int midX;

private int topY;

private int bottomY;

private int midY;

private RobotCalibration(WebDriver driver) {

this.driver = driver;

try {

driver.manage().window().getSize();

} catch (UnsupportedOperationException headlessBrowserException) {

throw new IllegalArgumentException("Calibrating a headless browser makes no sense.", headlessBrowserException);

}

try {

this.r = new Robot();

} catch (AWTException headlessEnvironmentException) {

throw new IllegalStateException("Robot won't work on headless environments.", headlessEnvironmentException);

}

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

org.openqa.selenium.Dimension browserSize = driver.manage().window().getSize();

org.openqa.selenium.Point browserPos = driver.manage().window().getPosition();

// a maximized browser returns negative position

// a maximized browser returns size larger than actual screen size

// you can't click outside the screen

leftX = Math.max(0, browserPos.x);

rightX = Math.min(leftX + browserSize.width, screenSize.width - 1);

midX = (leftX + rightX) /2;

topY = Math.max(0, browserPos.y);

bottomY = Math.min(topY + browserSize.height, screenSize.height - 1);

midY = (topY + bottomY) /2;

browserCenter = new Point(midX, midY);

}

private Point calibrate() {

driver.get(Paths.get("files/RobotCalibration.html").toUri().toString());

// find left border

while (leftX < rightX) {

click(midX, midY);

if (clickWasSuccessful()) {

rightX = midX;

} else {

leftX = midX + 1;

// close any menu we could have opened

click(browserCenter.x, browserCenter.y);

}

midX = (leftX + rightX) /2;

}

// find top border

while (topY < bottomY) {

click(midX, midY);

if (clickWasSuccessful()) {

bottomY = midY;

} else {

topY = midY + 1;

// close any menu we could have opened

click(browserCenter.x, browserCenter.y);

}

midY = (topY + bottomY) /2;

}

if (!isCalibrated()) {

throw new IllegalStateException("Couldn't calibrate the Robot.");

}

return new Point(midX, midY);

}

/** clicks on the specified location */

private void click(int x, int y) {

r.mouseMove(x, y);

r.mousePress(InputEvent.BUTTON1_DOWN_MASK);

r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

// for some reason, my IE8 can't properly register clicks that are close

// to each other faster than click every half a second

if (driver instanceof InternetExplorerDriver) {

sleep(500);

}

}

private static void sleep(int millis) {

try {

Thread.sleep(millis);

} catch (InterruptedException ignored) {

// nothing to do

}

}

private int counter = 0;

/** @return whether the click on a page was successful */

private boolean clickWasSuccessful() {

counter++;

long targetTime = System.currentTimeMillis() + TIMEOUT;

while (System.currentTimeMillis() < targetTime) {

int pageCounter = Integer.parseInt(driver.findElement(By.id("counter")).getAttribute("value"));

if (counter == pageCounter) {

return true;

}

}

return false;

}

/** @return whether the top left corner has already been clicked at */

private boolean isCalibrated() {

long targetTime = System.currentTimeMillis() + TIMEOUT;

while (System.currentTimeMillis() < targetTime) {

if (driver.findElement(By.id("done")).getAttribute("value").equals("yep")) {

return true;

}

}

return false;

}

}

用法示例:

WebDriver driver = new InternetExplorerDriver();

Point p = RobotCalibration.calibrate(driver);

System.out.println("Left offset: " + p.x + ", top offset: " + p.y);

driver.quit();

如果有不清楚的地方,请随时提出任何问题。

以上是 通过使用Java Selenium WebDriver和HTML窗口位置 的全部内容, 来源链接: utcz.com/qa/407247.html

回到顶部