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.