0

Is CSS_SELECTOR the only way I can use to find element inside a shadowroot element? I am using Python 3.10.1, Selenium (4.1.0) chrome(96.0.4664.110).

Below is my code

host = browser.find_element(By.ID, 'someid') 
shadow_root = browser.execute_script('return arguments[0].shadowRoot', host)
goal = shadow_root.find_element(By.XPATH, '//*/button[@aria-label="Required"]')

and the error I got as below if I don't use By.CSS_SELECTOR.

Traceback (most recent call last):
  File "C:\Files\Workspace\PostInstallVerify.py", line 787, in <module>
    maxlenInput = getShadowElement(maxlenid, ".rwa-input")
  File "C:\Files\Workspace\PostInstallVerify.py", line 272, in getShadowElement
    goal = shadow_root.find_element(By.XPATH, '//*/button[@aria-label="Required"]')
  File "C:\Users\Tomas.Tang\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\remote\shadowroot.py", line 45, in find_element
    return self._execute(Command.FIND_ELEMENT_FROM_SHADOW_ROOT, {"using": using, "value": value})['value']
  File "C:\Users\Tomas.Tang\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\remote\shadowroot.py", line 64, in _execute
    return self.session.execute(command, params)
  File "C:\Users\Tomas.Tang\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 424, in execute
    self.error_handler.check_response(response)
  File "C:\Users\Tomas.Tang\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 247, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid locator
  (Session info: chrome=96.0.4664.110)
Stacktrace:
Backtrace:
    Ordinal0 [0x00326903+2517251]
    Ordinal0 [0x002BF8E1+2095329]
    Ordinal0 [0x001C2848+1058888]
    Ordinal0 [0x001ED5C4+1234372]
    Ordinal0 [0x001ED68B+1234571]
    Ordinal0 [0x001E3AE1+1194721]
    Ordinal0 [0x0020650A+1336586]
    Ordinal0 [0x001E3A36+1194550]
    Ordinal0 [0x002065BA+1336762]
    Ordinal0 [0x00215BBF+1399743]
    Ordinal0 [0x0020639B+1336219]
    Ordinal0 [0x001E27A7+1189799]
    Ordinal0 [0x001E3609+1193481]
    GetHandleVerifier [0x004B5904+1577972]
    GetHandleVerifier [0x00560B97+2279047]
    GetHandleVerifier [0x003B6D09+534521]
    GetHandleVerifier [0x003B5DB9+530601]
    Ordinal0 [0x002C4FF9+2117625]
    Ordinal0 [0x002C98A8+2136232]
    Ordinal0 [0x002C99E2+2136546]
    Ordinal0 [0x002D3541+2176321]
    BaseThreadInitThunk [0x766CFA29+25]
    RtlGetAppContainerNamedObjectPath [0x773A7A9E+286]
    RtlGetAppContainerNamedObjectPath [0x773A7A6E+238]
    (No symbol) [0x00000000]
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Myhnet
  • 9
  • 1
  • 1
  • 2
  • Xpathing from an element requires a . in front of it's .// so no you can use any selector after shadow root. – Arundeep Chohan Dec 23 '21 at 06:40
  • it is not due to the syntax of how I wrote the XPATH as the XPATH works fine if not inside the ShadowRoot. I just found a interesting link and it says might be a limitation of chromedriver. will take with firefox again tomorrow to verify if it is true. https://github.com/SeleniumHQ/selenium/issues/10107#issuecomment-986770906 – Myhnet Dec 26 '21 at 14:17
  • Commenting here because I can't comment on the ticket, but https://github.com/SeleniumHQ/selenium/issues/10025 confirms it's a ChromeDriver issue ( https://bugs.chromium.org/p/chromedriver/issues/detail?id=4097 ). – Scott Stevens Dec 15 '22 at 10:11

3 Answers3

0

Simply use

 .//button[@aria-label='Required']

Xpath from an element requires a . unlike others.

Arundeep Chohan
  • 9,779
  • 5
  • 15
  • 32
0

You can locate elements inside the shadow DOM by any regular locator: CSS_SELECTOR, XPATH, ID, CLASS_NAME etc.
Here you are trying to use an invalid XPath expression.

'//*/button[@aria-label="Required"]'

is not a valid XPath expression.
I can't know what page you are working on and what is the correct locator of that element, but this will be at least a correct XPath expression that may be correct for you:

'//button[@aria-label="Required"]'

So instead of

goal = shadow_root.find_element(By.XPATH, '//*/button[@aria-label="Required"]')

Try this:

goal = shadow_root.find_element(By.XPATH, '//button[@aria-label="Required"]')

Or maybe

goal = shadow_root.find_element(By.XPATH, './/button[@aria-label="Required"]')
Prophet
  • 32,350
  • 22
  • 54
  • 79
  • I have tested your suggestion, but the same error of "invalid locater". it is not due to the syntax of how I wrote the XPATH as the XPATH works fine if not inside the ShadowRoot. I just found a interesting link and it says might be a limitation of chromedriver. will take with firefox again tomorrow to verify if it is true. https://github.com/SeleniumHQ/selenium/issues/10107#issuecomment-986770906 – Myhnet Dec 26 '21 at 14:21
0

No, isn't the only way to interact with shadowroot.

Your code trial was near perfect but the XPATH expression wasn't a valid xpath expression as within the expression:

goal = shadow_root.find_element(By.XPATH, '//*/button[@aria-label="Required"]')

the /* wasn't needed as //button itself would look for a button tag within the entire DOM Tree.

So effectively you line of code will be:

goal = shadow_root.find_element(By.XPATH, '//button[@aria-label="Required"]')
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • it is not due to the syntax of how I wrote the XPATH as the XPATH works fine if not inside the ShadowRoot. I just found a interesting link and it says might be a limitation of chromedriver. will take with firefox again tomorrow to verify if it is true. https://github.com/SeleniumHQ/selenium/issues/10107#issuecomment-986770906 – Myhnet Dec 26 '21 at 14:22