How to get WebDriver object from WebElement object in Selenium Java automated tests

Despite there is no any public interface to obtain WebDriver object having just WebElement object, sometimes it becomes necessary to extract it from given element in your Selenium automated tests. This is possible with certain assumptions. Here we’re going to look at one of such examples.

Let’s now take a closer look at the case.

Example description: having WebElement extract WebDriver

We’re going to look up WebElement using our WebDriver and then extract that driver back from the element. We’re going to use reflection mechanisms in order to break into WebElement implementation where we will modify the access level of the object’s field. It is not recommended to use such approach unless there is no other way to have the reference to your WebDriver since you might break the logic of other processes which expect that field to be protected.

Why it is not always possible

Basically WebDriver and WebElement are just the interfaces. They define the contract the implementations has to adhere and the contract of WebElement does not imply any possibility of extracting WebDriver reference from it.

At the same time Selenium provides the implementation of WebDriver and WebElement as RemoteWebDriver and RemoteWebElement correspondingly where the element has the reference to a parent driver. There are some good news and some bad news here. Good news is that the most of known drivers like FirefoxDriver or ChromeDriver are actually the extensions of RemoteWebDriver. Bad news is that the reference has protected access modifier.

So why this approach won’t be working for all the possible cases. Because you might have some other driver implementation which does not extend RemoteWebDriver.

Implementation

Below is the example of the method that returns WebDriver object for given WebElement object. Since we cannot just take the field (it is protected) we have to involve reflection to work this limitation around:

private WebDriver getWebDriverFromWebElement(WebElement webElement){
    if(!webElement.getClass().isAssignableFrom(RemoteWebElement.class)){
        return null;
    }
    try {
        Field parent = webElement.getClass().getDeclaredField("parent");
        parent.setAccessible(true);
        return (RemoteWebDriver)parent.get(webElement);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        return null;
    }
}

If field accessing issue is encountered the method returns null reference. This is tested for FirefoxDriver and ChromeDriver drivers.

Testing the implementation

Lets write a simple test showing how our implementation works:

@Test
public void testWebDriver(){
    driver.get("https://webelement.click/en/welcome");
    WebElement element = driver.findElement(By.tagName("li"));
    System.out.println(driver.equals(getWebDriverFromWebElement(element)));
}

The test output demonstrates objects equality.

If you still have the questions please send them to me using this form. I will amend the article according to your feedback.