1

I am trying to locate an input text from input field that is saved in shadow DOM with:

driver.find_element_by_css_selector("#my_id div:nth-of-type(2)").text 

but it does not help. HTML part

<input _ngcontent-c21="" class="clr-input ng-untouched ng-pristine ng-valid" id="my_id" name="my_id" placeholder="My placeholder namespace" size="40" type="text">
 #shadow-root {user-agent}
  <div pseudo="-webkit-input-placeholder" id="placeholder" style="display: none !important;">My placeholder namespace</div>
  <div>Text I need to find</div>

Also tried this with not luck:

shadow_section = driver.execute_script('''return 
document.querySelector("#my_id").shadowRoot''')
            print(shadow_section.find_element_by_css_selector("div:nth-of-type(2)").text)

What is the best approach for finding elements in shadow DOM in this case? In my case locator should be linked to element.

Update: as suggested I tried:

  shadow_root = driver.execute_script('return arguments[0].shadowRoot', driver.find_element_by_css_selector("#my_id"))
  shadow_root_element = shadow_root(driver.find_element_by_css_selector('div:nth-child(2)'))

But received:

TypeError: 'NoneType' object is not callable

on shadow_root_element row.

vitaliis
  • 4,082
  • 5
  • 18
  • 40
  • 1
    You can not query ``user-agent`` shadowRoots. Those are Browser specific implementations. So the HTML in Safari *could* be different from the HTML in Chrome or FireFox. If try to edit it (double-click) in F12 Elements.. you can't. – Danny '365CSI' Engelman Mar 05 '21 at 13:13
  • Thank you very much. I understood it in a hard way. – vitaliis Mar 05 '21 at 21:19

2 Answers2

1
element=driver.execute_script(
    "return document.querySelector('#my_id').shadowRoot.querySelector('div:nth-child(2)')")

you have to use execute script to find shadow root, the element will have the item you want. You can now use element.text to get the text

PDHide
  • 18,113
  • 2
  • 31
  • 46
  • Thanks. When I execute this, I get: selenium.common.exceptions.JavascriptException: Message: javascript error: Cannot read property 'querySelector' of null – vitaliis Mar 05 '21 at 02:55
  • I found this answer for Java, trying to use it in Python https://stackoverflow.com/questions/56380091/how-to-interact-with-the-elements-within-shadow-root-open-while-clearing-brow – vitaliis Mar 05 '21 at 02:56
  • 1
    Make sure there is only one element we the id as my id – PDHide Mar 05 '21 at 03:02
  • This id is unique, I checked it in Chrome devtools before. Maybe I should try a different locators for element in shadow DOM. – vitaliis Mar 05 '21 at 03:48
  • 1
    Find that element and then pass that to execute script and do arguments[0].shadowRoot – PDHide Mar 05 '21 at 03:53
  • So you know the element root is actually being found – PDHide Mar 05 '21 at 03:54
  • Thanks, I've updated the question. I get this error on shadow_root_element – vitaliis Mar 05 '21 at 04:39
  • `driver.execute_script("return arguments[0].shadowRoot.querySelector('div:nth-child(2)')", driver.find_element_by_css_selector("#my_id"))` – PDHide Mar 05 '21 at 06:13
  • Use locator like this – PDHide Mar 05 '21 at 06:14
  • Thanks. Looks like it is not ordinary DOM. I got "javascript error: Cannot read property 'querySelector' of null" when executing the latest selector. I found a simplier option and I will post it shortly. – vitaliis Mar 05 '21 at 06:20
  • Posted working option. I will try options with execute_script tomorrow. – vitaliis Mar 05 '21 at 06:28
1

I was not able to find a solution with Javascripts .shadowRoot option and it is a mystery for me why it does not work. This option works just fine. It input text:

driver.find_element_by_css_selector("#my_id").get_attribute("value")

or

driver.find_element_by_id("my_id").get_attribute("value")

I am still very interested in the approach proposed by PDHide.

vitaliis
  • 4,082
  • 5
  • 18
  • 40
  • in the example you showed there is no attribute called value , then how will this work? – PDHide Mar 05 '21 at 06:37
  • Do you have a website link? – PDHide Mar 05 '21 at 06:37
  • 1
    The site closed app. I found this answer useful https://stackoverflow.com/questions/10251525/how-can-i-get-the-current-contents-of-an-element-in-webdriver . So, in the case of input elements we should use "element.get_attribute('value')". Also, from what I learned it matters what type of #shadow-root it is. In my case it is {user-agent}. I think in other cases javascript approach would work with no problems. – vitaliis Mar 05 '21 at 06:46
  • There is no value attribute in my HTML. – vitaliis Mar 05 '21 at 06:49