gpt4 book ai didi

java - 使用 Java 的 Selenium WebDriver 和 HTML 窗口位置

转载 作者:搜寻专家 更新时间:2023-10-30 21:06:25 26 4
gpt4 key购买 nike

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

目前一切正常,但我遇到了一个小问题,因为我似乎无法找到一种好的方法来获取 Web 元素在屏幕上的位置。标题栏、菜单栏、导航栏等都将内容向下推到物理屏幕上(机器人从中获取坐标),但对 Selenium 报告元素所在的位置没有影响。

当我在 Selenium WebElement 上调用:element.getLocation(); 时,它总是给我它相对于 HTML 内容呈现 Pane 的位置,而不是浏览器窗口本身。

更好的例子是:driver.findElement(By.tagName("body")).getLocation(); 总是返回 0,0,无论窗口在屏幕上的实际位置如何。

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

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

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

最佳答案

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

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

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

在 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 - 使用 Java 的 Selenium WebDriver 和 HTML 窗口位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14655581/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com