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

I'm trying to use selenium to automate some actions but am unable to find the first element on the page https://developer.servicenow.com/dev.do and so cannot login

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver_path = "../bin/chromedriver.exe"
driver = webdriver.Chrome(driver_path)

driver.get("https://developer.servicenow.com/dev.do")

driver.find_element_by_xpath("/html/body/dps-app//div/header/dps-navigation-header//header/div/div[2]/ul/li[3]/dps-login//div/dps-button//button/span")

I get the error

selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/dps-app//div/header/dps-navigation-header//header/div/div[2]/ul/li[3]/dps-login//div/dps-button//button/span"}


Solution 1:[1]

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:

Solution 2:[2]

You could look at the Automatepro app on the servicenow store. It uses selenium but they have pre-written the selenium behind the scenes to interact with all the servicenow UI components, including those using shadow DOM. You just pick the UI element and supply the data for your test. We found it saves a lot of time writing and maintaining the selenium code ourselves..

Solution 3:[3]

This solution was what I was looking for to log into my instance using Powershell.

driver.executescript("return document.querySelector('dps-app').shadowRoot.querySelector('dps-navigation-header').shadowRoot.querySelector('header.dps-navigation-header dps-login').shadowRoot.querySelector('dps-button')").Click()

Solution 4:[4]

I think its because you are trying to access the "Sign in" before the website has time to load all of the elements.

I suggest you use

driver.set_page_load_timeout(120)

so the selenium will look for the button after everything is loaded on the website.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Paul
Solution 3 Pjotr
Solution 4 Michael Krezalek