【发布时间】:2021-12-26 17:50:18
【问题描述】:
我正在尝试单击下拉菜单上的链接。当我将鼠标悬停在按钮上时,会出现此下拉菜单。现在,我的测试因MoveTargetOutOfBoundsException 而崩溃,当我尝试悬停按钮时会发生这种情况。当我在浏览器中打开页面时,我可以轻松找到或将鼠标悬停在按钮上,因为它似乎无论如何都不在视口之外。
我用来悬停按钮的代码是:
private void hoverButtonWaitDropDown(WebElement button) {
a.moveToElement(button).build().perform();
try {
w.until(ExpectedConditions.visibilityOf(dropDownMenu));
} catch (TimeoutException ex) {
ExtentTestManager.log(logger, Level.WARN, "Dropdown menu failed to display");
}
}
然后,测试等待下拉菜单出现并循环通过可用选项来找到所需的选项,最后单击它:
public void clickContextSetting(String setting) {
hoverButtonWaitDropDown(contextButton);
if (dataItems.size() == 0) {
ExtentTestManager.log(logger, Level.WARN, "There are no context settings on the dropdown menu");
return;
}
for (WebElement con : dataItems) {
if (con.findElement(By.tagName("span")).getText().trim().equalsIgnoreCase(setting)) {
con.click();
return;
}
}
Assert.fail("Test aborted because context setting: " + setting + " is not present on the topbar dropdown menu");
}
现在,当我注释掉 a.moveToElement(button).build().perform(); 时,我自己运行测试并将鼠标移动到按钮上以显示下拉菜单,测试被 Assert.fail() 调用终止。这意味着测试确实找到了链接列表,因为dataItems.size() == 0 评估为假,但无法在下拉菜单中找到所需的链接。我添加了一个打印方法来打印出现的下拉菜单上所有链接的文本:
private void printDataItems() {
for (WebElement item: dataItemsText) {
System.out.println(item.getText());
}
}
但这只会打印 5 个空的 Strings。
当我使用选择器div[class='dataitems'] a span 在 devTools 的下拉菜单中查找包含链接文本的元素时,它会列出所有链接并按应有的方式突出显示链接文本,但是当我尝试使用 Selenium 时它不起作用.
文本节点如下所示:
我已经手动检查了我所有的定位器,它们都是正确的,所以我不知道我在这里做错了什么。 我应该注意,我在 chromedriver (96) 和 edgedriver (95) 中遇到了这个问题,但在 geckodriver (94) 中没有。当我使用 geckodriver 运行此测试时,测试脚本正确地悬停在按钮上,打印出下拉菜单上的所有可用链接并单击该链接。有什么想法吗?
编辑: 根据要求,这里是我在问题中提到的 WebElements 的定位器:
@FindBy(css = "div[gadget-name='Topbar context btn']")
private WebElement contextButton;
@FindBy(css = "div[class^='dropdata']")
private WebElement dropDownMenu;
@FindBy(css = "div[class='dataitems'] a")
private List<WebElement> dataItems;
@FindBy(css = "div[class='dataitems'] a span")
private List<WebElement> dataItemsText;
还有 MoveTargetOutOfBoundsException 的堆栈跟踪(我假设是这样的):
org.openqa.selenium.interactions.MoveTargetOutOfBoundsException: move target out of bounds
(Session info: chrome=95.0.4638.69)
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: 'DESKTOP-I6V1OLJ', ip: '192.168.2.8', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '16.0.2'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 95.0.4638.69, chrome: {chromedriverVersion: 95.0.4638.17 (a9d0719444d4b..., userDataDir: C:\Users\mb_vl\AppData\Loca...}, goog:chromeOptions: {debuggerAddress: localhost:59476}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:virtualAuthenticators: true}
Session ID: 6003d76fccdd4ddbed789b440fa9e6f7
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
at org.openqa.selenium.remote.RemoteWebDriver.perform(RemoteWebDriver.java:618)
at org.openqa.selenium.interactions.Actions$BuiltAction.perform(Actions.java:639)
at ObjectRepository.items.topbar_improved.hoverButtonWaitDropDown(topbar_improved.java:65)
at ObjectRepository.items.topbar_improved.clickContextSetting(topbar_improved.java:500)
at test_classes.general_scenarios.topbar_general.checkModal(topbar_general.java:50)
at test_classes.pages_local.local_test.topBar_clickLastLogins_modalIsDisplayed(local_test.java:102)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:132)
at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:599)
at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:174)
at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:822)
at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:147)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.testng.TestRunner.privateRun(TestRunner.java:764)
at org.testng.TestRunner.run(TestRunner.java:585)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
at org.testng.SuiteRunner.run(SuiteRunner.java:286)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1218)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
at org.testng.TestNG.runSuites(TestNG.java:1069)
at org.testng.TestNG.run(TestNG.java:1037)
at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:284)
at org.apache.maven.surefire.testng.TestNGXmlTestSuite.execute(TestNGXmlTestSuite.java:75)
at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:119)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:428)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:562)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:548)
编辑:已解决
我联系了我们的前端开发人员,他们要求在生产环境中试用。它在那里工作,经过一番搜索,我注意到我试图与之交互的包含元素有zoom: 90%。我运行了我的测试,暂停它并在 devTools 中将元素 zoom 设置为 100%,然后继续执行;一切都再次奏效。
我做了一些挖掘,显然这是一个已知的事情:link
【问题讨论】:
-
您应该显示定位“contextButton”、“dropDownMenu”、“dataItems”和“dataItemsText”的代码。 (您问题的第一部分将涉及“contextButton”......第二部分似乎仅与等待可见性有关(这可能还不够),并且可能仅在容器上用于跨度......)跨度>
-
我已经用您要求的代码更新了我的问题。
-
MoveTargetOutOfBoundsException的错误堆栈跟踪? -
我现在也添加了stacktrace。
-
对于第二部分,您可能希望包含您尝试从中获取文本()的 标记之一的 HTML。您没有收到过时元素异常的事实表明那里还有另一个节点。或者,要进行故障排除,请检查: System.out.println(item.getAttribute('innerHTML'));
标签: java selenium selenium-chromedriver java-16 selenium-edgedriver