I am working on an automation project which uses shadow dom extensively. So every time using execute_script function to access shadow root
for eg.
root = driver.execute_script('return document.querySelector(".flex.vertical.layout").shadowRoot')
Then use the root to access the elements within. Since we have shadow roots at many levels, this is annoying me a lot. is there any better solution exist than this to access elements within shadow root?
I am using Chrome 2.20 driver.
Since you use often that you may create a function, then the above becomes:
on the resulting element you can put any of the methods:
later edit:
Sometime the shadow host elements are hidden withing shadow trees that's why the best way to do it is to use the selenium selectors to find the shadow host elements and inject the script just to take the shadow root: :
To put this into perspective I just added a testable example with Chrome's download page, clicking the search button needs open 3 nested shadow root elements:
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 by
driver.find_elements_by_css_selector('body/deep/.layout.horizontal.center')
This will have access to the element with compound class name "layout horizontal center" regardless of the number of shadow roots it has.
But this only working in chrome driver and I see notes "/deep/" is a deprecated approach.
You can write extension methods to operate on IWebElement to expand the root as below.
You can use above extension method to traverse through the elements hierarchy to reach the element of intrest..
Trying to have this automated on Chrome I came up with an inelegant solution of recursively searching through each shadow dom explicitly using:
Here's the javascript (passed as a string):
Since the contents of a shadowRoot might be empty initially one can use
driver.wait
anduntil.elementIsVisible
to avoid returning a null element.Async example:
Alternatively
My previous solution was to traverse the elements with shadowdoms explicitly, but is less autonomous. Same as above but with this script:
Where
selectors
would be something like:Sidenote
I found that running my automation tests on Firefox Quantum 57.0 doesn't suffer from hidden shadow doms, and any element can be found with a simple:
Maybe you may use IJavaScriptExecutor?
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