pythonselenium-webdrivermetamask

Selenium: how to get element in shadow root of html page code?


I need to get the element of the button to connect the MetaMask wallet to the polygon network bridge using selenium.

the button I need to find: But the button, as I understand it is hidden in shadow root of the html page.

If I find HTML code of the button with right click and 'inspect', I can try to copy it s X-Path. When I paste it is: /button That does not work:

metamask = wait.until(EC.element_to_be_clickable((By.XPATH, '/button')))
metamask.click()

Results in an error. Text of these errors is every time the same so I will paste it in the end.

If I try to right click, 'inspect' and copy CSS-Selector it also does not work. The CSS-Selector copied is: button:nth-child(1) I can not get the button with this.

Now, text of the error which arises when I try to find the button by CSS-Selector or X-Path:

Traceback (most recent call last):
  File "C:\Users\childoflogos\Desktop\selenium_airdrop_hunter\main.py", line 126, in <module>
    metamask = wait.until(EC.element_to_be_clickable((By.XPATH, '/button')))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\childoflogos\Desktop\selenium_airdrop_hunter\venv\Lib\site-packages\selenium\webdriver\support\wait.py", line 95, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 
Stacktrace:
Backtrace:
    GetHandleVerifier [0x00B9A813+48355]
    (No symbol) [0x00B2C4B1]
    (No symbol) [0x00A35358]
    (No symbol) [0x00A609A5]
    (No symbol) [0x00A60B3B]
    (No symbol) [0x00A8E232]
    (No symbol) [0x00A7A784]
    (No symbol) [0x00A8C922]
    (No symbol) [0x00A7A536]
    (No symbol) [0x00A582DC]
    (No symbol) [0x00A593DD]
    GetHandleVerifier [0x00DFAABD+2539405]
    GetHandleVerifier [0x00E3A78F+2800735]
    GetHandleVerifier [0x00E3456C+2775612]
    GetHandleVerifier [0x00C251E0+616112]
    (No symbol) [0x00B35F8C]
    (No symbol) [0x00B32328]
    (No symbol) [0x00B3240B]
    (No symbol) [0x00B24FF7]
    BaseThreadInitThunk [0x76A100C9+25]
    RtlGetAppContainerNamedObjectPath [0x77D77B4E+286]
    RtlGetAppContainerNamedObjectPath [0x77D77B1E+238]

A common error when selenium is unable to find and click an element

Button element in HTML code of the page (better try to locate the element in html code yourself)

How can I find and click this button with selenium?

UPDATE: I found information on how to locate elements inside shadow root:

shadow_element = driver.execute_script("return document.querySelector('w3m-modal').shadowRoot.querySelector('div').querySelector('div')")

Yet still I can not make a path to my target button Code above reaches one of divs inside of correct shadow root, yet can not grasp any element after following html comment:

<!--?lit$702571791$-->

How do I proceed and grasp elements that go after the comment above?


Solution

  • The <button> element is within multiple #shadow-root (open)

    w3m


    Solution

    To click on button with text MetaMask you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following locator strategy:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((driver.execute_script("return document.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-wallet-button').shadowRoot.querySelector('button > div > w3m-text.w3m-sublabel')")))).click()
    

    Note: You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC