Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shadow-dom support for selenium

I am working on an automation project which uses shadow DOMs extensively. I use the execute_script function to access shadow root elements.

For example:

root = driver.execute_script('return document.querySelector(".flex.vertical.layout").shadowRoot')

Then I use the root element to access the elements within. Since we have shadow root elements at many levels, this is annoying me a lot. Is there any better solution to access elements within shadow root elements?

I am using Chrome 2.20 driver.

like image 989
Arav Avatar asked Mar 21 '16 18:03

Arav


People also ask

What is shadow DOM elements in selenium?

Shadow DOM refers to the ability of the browser to include a subtree of DOM elements into the rendering of a document, but not into the main document DOM tree. Shadow DOM enables encapsulation. With Shadow DOM, a component can have its own “shadow” DOM tree that cannot be accidentally accessed from the main document.

What is shadow DOM automation?

Shadow DOM allows DOM elements to contain child nodes and CSS, which helps web developers by better encapsulating their code. But this creates challenges for automation testing, because elements inside a shadow root technically don't exist in the main DOM.


3 Answers

By googling I found another workaround for this problem - which is using the "/deep/ combinator".

For example, I was able to access all the shadow roots elements with

driver.find_elements_by_css_selector('body/deep/.layout.horizontal.center')

This will have access to the element with the compound class name layout horizontal center regardless of the number of shadow roots it has.

But this only works for the chromedriver and /deep/ is a deprecated approach.

like image 75
Arav Avatar answered Oct 13 '22 18:10

Arav


The WebDriver spec still doesn't have anything specific to say about Shadow DOM.

Nor the Selenium project pages - which is understandable, as they closely follow the spec. Yet there is some low-level code in existence.

So, the short answer is: no, there is no special support in the spec, in Selenium's WebDriver API or implementation code at present.

Yes, the capability seems to exist in ChromeDriver 2.14 (as a wrapper around Chrome). However, as far as I can tell there are no Selenium or WebDriver-level bindings to let you use it.

But for more detail and possible workarounds, see also: Accessing Shadow DOM tree with Selenium, also: Accessing elements in the shadow DOM, and especially: Finding elements in the shadow DOM

like image 31
Andrew Regan Avatar answered Oct 13 '22 20:10

Andrew Regan


You can write extension methods to operate on IWebElement to expand the root as below.

public static class SeleniumExtension
{
    public static IWebElement ExpandRootElement(this IWebElement element, IWebDriver driver)
    {
        return (IWebElement)((IJavaScriptExecutor)driver)
                .ExecuteScript("return arguments[0].shadowRoot", element);
    }
}

You can use the above extension method to traverse through the element's hierarchy to reach the element of interest.

By downloads_manager_ShadowDom= By.TagName("downloads-manager");
By downloadToolBarShadowDom = By.CssSelector("downloads-toolbar");
By toolBarElement = By.CssSelector("cr-toolbar");

IWebElement ToolBarElement = driver.FindElement(downloads_manager_ShadowDom).ExpandRootElement(driver).FindElement(downloadToolBarShadowDom).ExpandRootElement(driver).FindElement(toolBarElement);
like image 45
Gitesh P Avatar answered Oct 13 '22 20:10

Gitesh P