Mattemingda
Mattemingda

Reputation: 81

org.openqa.selenium.interactions.MoveTargetOutOfBoundsException: move target out of bounds using Selenium Chrome and java.version: '16.0.2'

I am trying to click a link that is on a dropdown menu. This dropdown menu appears when I hover over a button. Right now, my test crashes with a MoveTargetOutOfBoundsException, which happens when I try to hover the button. When I open the page in my browser, I have no trouble finding or hovering over the button, as it doesn't seem to be outside of the viewport by any means. The code I use to hover the button is:

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");
        }
    }

Then, the test waits for the dropdown menu to appear and loops through the available options to find the desired one, and finally clicks it:

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");
    }

Now, when I comment out a.moveToElement(button).build().perform(); , run the test and move the mouse to the button myself in order to display the dropdown menu, the test is terminated instead by the Assert.fail() call. This means that the test does find a list of links, since dataItems.size() == 0 evaluates to false, but it is unable to find the desired link on the dropdown menu. I have added a print method to print the text of all the links on the dropdown menu that appears:

private void printDataItems() {
        for (WebElement item: dataItemsText) {
            System.out.println(item.getText());
        }
    }

but that just prints 5 empty Strings. When I look for the elements that contain the link texts on the dropdown menu in devTools with the selector div[class='dataitems'] a span, it lists all the links and highlights the link texts like it should, but it doesn't work when I try it with Selenium.

The text nodes look like this:

span

I have manually checked all my locators, and they are all correct, so I don't know what I'm doing wrong here. I should note that I run into this issue with chromedriver (96) and edgedriver (95), but not with geckodriver (94). When I run this test with geckodriver, the test script correctly hovers the button, prints out all the available links on the dropdown menu and clicks the link. Any ideas?

Edit: As requested, here are the locators for the WebElements that I refer to in my question:

@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;

And the stacktrace of the MoveTargetOutOfBoundsException (I'm assuming it is this):

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)

Edit: solved

I contacted our frontend dev, and they asked to try it on the production environment. It worked there, and after some searching I noticed that the containing element that I was trying to interact with had zoom: 90%. I ran my test, paused it and set the element zoom to 100% in devTools, and continued execution; everything worked again. I did some digging, and apparently this is a known thing: link

Upvotes: 4

Views: 32888

Answers (2)

gerardnico
gerardnico

Reputation: 1073

With the following implementation, you will get to see the element in the browser and resolves this error.

It uses the scrollByAmount method.

public static WebElement scrollToElement(WebElement elementToScroll, WebDriver webDriver) {

    Rectangle rect = elementToScroll.getRect();
    int deltaY = rect.y + rect.height;
    new Actions(webDriver)
      .scrollByAmount(0, deltaY)
      .perform();
    return elementToScroll;

}

Ps: The MoveTargetOutOfBoundsException: move target out of bounds can be seen when using the moveToElement or scrollToElement method. My best guess is that this function scrolls to the element but only to the top position of the bounding rectangle, making the element not visible.

Upvotes: 1

undetected Selenium
undetected Selenium

Reputation: 193108

This error message...

org.openqa.selenium.interactions.MoveTargetOutOfBoundsException: 

...implies that Selenium was unable to focus on the desired element as the element was out of bounds of the viewport.

Your main issue is the WebElement identified as button is out of Viewport so Selenium can't move the focus on the desired element through moveToElement() method.


Solution

A simple solution would be to use the scrollIntoView() method to bring the desired element within the viewport and then invoke moveToElement() method as follows:

WebElement myElement = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOf(button));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", myElement);
a.moveToElement(webElement).build().perform();

Update

A conservative suggestion would be replace java.version: '16.0.2' with stable latest JDK 8u311 as earlier we have faced the following issues of Selenium with higher Java versions:


References

You can find a relevant detailed discussion in:

Upvotes: 4

Related Questions