Tanvir Ahmed
Tanvir Ahmed

Reputation: 49

How to automate/access nested shadow DOM elements using selenium python?

I want to access/automate an element of nested shadow DOM. Ley's say for the given link https://books-pwakit.appspot.com/ I want to search some books by sending some book name. I am trying like this according to my learnt knowledge but it is not locating the element. My code is like this...

url = "https://books-pwakit.appspot.com/"
driver.get(url)

shadow_host1 = driver.find_element(By.CSS_SELECTOR, "book-app[apptitle='BOOKS']")
shadow_root1 = driver.execute_script('return arguments[0].shadowRoot', shadow_host1)

shadow_host2 = driver.find_element(By.CSS_SELECTOR, "app-header[effects='waterfall']")
shadow_root2 = driver.execute_script('return arguments[0].shadowRoot', shadow_host2)

shadow_host3 = driver.find_element(By.CSS_SELECTOR, '.toolbar-top')
shadow_root3 = driver.execute_script('return arguments[0].shadowRoot', shadow_host3)

shadow_host4 = driver.find_element(By.CSS_SELECTOR, '.toolbar-bottom')
shadow_root4 = driver.execute_script('return arguments[0].shadowRoot', shadow_host4)

shadow_host5 = driver.find_element(By.CSS_SELECTOR, 'book-input-decorator')
shadow_root5 = driver.execute_script('return arguments[0].shadowRoot', shadow_host5)

shadow_content = shadow_root5.find_element(By.CSS_SELECTOR, '#input')

shadow_content.send_keys("Twilight")   

Can anyone help me please and describe me why I am getting that error.

Upvotes: 2

Views: 7557

Answers (1)

Prophet
Prophet

Reputation: 33381

In order to get the inner shadow_hosts you need to apply the find_element() method on outer shadow_host element, not on the global driver object.
The following code works:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

options = Options()
options.add_argument("start-maximized")

webdriver_service = Service('C:\webdrivers\chromedriver.exe')
driver = webdriver.Chrome(options=options, service=webdriver_service)
wait = WebDriverWait(driver, 30)

url = "https://books-pwakit.appspot.com/"
driver.get(url)

shadow_host1 = driver.find_element(By.CSS_SELECTOR, "book-app[apptitle='BOOKS']")
shadow_root1 = driver.execute_script('return arguments[0].shadowRoot', shadow_host1)

shadow_host2 = shadow_root1.find_element(By.CSS_SELECTOR, "app-header[effects='waterfall']")
shadow_root2 = driver.execute_script('return arguments[0].shadowRoot', shadow_host2)

shadow_host3 = shadow_root1.find_element(By.CSS_SELECTOR, '.toolbar-top')
shadow_root3 = driver.execute_script('return arguments[0].shadowRoot', shadow_host3)

shadow_host4 = shadow_root1.find_element(By.CSS_SELECTOR, '.toolbar-bottom')
shadow_root4 = driver.execute_script('return arguments[0].shadowRoot', shadow_host4)

shadow_host5 = shadow_root1.find_element(By.CSS_SELECTOR, 'book-input-decorator')
shadow_root5 = driver.execute_script('return arguments[0].shadowRoot', shadow_host5)

shadow_content = shadow_host5.find_element(By.CSS_SELECTOR, '#input')
shadow_content.send_keys("Twilight")

This is the result:

enter image description here

Upvotes: 3

Related Questions