Does Anybody Know How to Identify Shadow Dom Web Elements Using Selenium Webdriver

Accessing Shadow DOM tree with Selenium

Unfortunately it looks like the webdriver spec does not support this yet.

My snooping uncovered :

http://www.w3.org/TR/webdriver/#switching-to-hosted-shadow-doms

https://groups.google.com/forum/#!msg/selenium-developers/Dad2KZsXNKo/YXH0e6eSHdAJ

What is the correct way to correctly identify an object via Python and Selenium?

econ-button btn btn-primary are actually 3 class names.

By.CLASS_NAME gets only single class name parameter.

To work with locators containing multiple class names you can use By.XPATH or By.CSS_SELECTOR.

As for me both the above methods are good, each of them having several cons and pros.

So, here you can use

browser.find_element(By.CSS_SELECTOR, 'button.econ-button.btn.btn-primary')

Or

browser.find_element(By.XPATH, "//button[@class='econ-button btn  btn-primary']")

Generally, you can use By.CSS_SELECTOR or By.XPATH. No need to utilize By.ID or By.CLASS_NAME since they are actually internally immediately translated to By.CSS_SELECTOR or By.XPATH :)

Some people preferring to use By.CSS_SELECTOR while others prefer By.XPATH.

As I mentioned previously, each of the above 2 methods having cons and pros.

For example you can locate elements by their texts with XPath only. XPath supports locating parent element based on their child nodes.

On the other hand XPath will not work so good on Firefox driver while it works perfectly on Chrome driver etc.

UPD
The locator for the second nein radio button can be:

"//label[.//input[@data-econ-property='kreditdaten-beduerfnisfragen-flexibilitaetGewuenscht'][@value='radio3']]"  

So, Selenium click can be done with

browser.find_element(By.XPATH, "//label[.//input[@data-econ-property='kreditdaten-beduerfnisfragen-flexibilitaetGewuenscht'][@value='radio3']]").click()

And so on with other buttons

Unable to locate the Sign In element within #shadow-root (open) using Selenium and Python

To Sign In button is deep within multiple #shadow-root (open)

shadow-root-open-multiple



Solution

Tto click() on the desired element you can use shadowRoot.querySelector() and you can use the following Locator Strategy:

from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
driver.get('https://developer.servicenow.com/dev.do')
SignInButton = driver.execute_script("return document.querySelector('dps-app').shadowRoot.querySelector('dps-navigation-header').shadowRoot.querySelector('header.dps-navigation-header dps-login').shadowRoot.querySelector('dps-button')")
SignInButton.click()

  • Browser Snapshot:

shadow-root-open



References

You can find a couple of relevant detailed discussions in:

  • How to interact with the elements within #shadow-root (open) while Clearing Browsing Data of Chrome Browser using cssSelector
  • How to automate shadow DOM elements using selenium?


Related Topics



Leave a reply



Submit