2

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?

Ajeet Verma
  • 2,938
  • 3
  • 13
  • 24

2 Answers2

2

you first need to locate the element that contains the shadow-root using any strategy (XPath, CSS selector, name, etc).

In your case, this element would be the tag <w3m-wallet-button name="MetaMask"

shadow_element = driver.find_element(By.CSS_SELECTOR, 'w3m-wallet-button[name="MetaMask"]').shadow_root

WebDriverWait(shadow_element, 10).until(EC.element_to_be_clickable((By.TAG_NAME, 'button'))).click()

Import the required modules:

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

[UPDATE]:

  • Various elements on this website are embedded inside the shadow-root.
  • for example, your target/desired button is embedded in a 5-layer nested shadow-root

Here's the complete working solution:

import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

options = ChromeOptions()
options.add_argument("--start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])

driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)
url = "https://wallet.polygon.technology/?redirectOnConnect=zkEVM_bridge"

driver.get(url)
# click on the "Connect to a Wallet" button
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.navbar__apps-section__auth__login"))).click()
time.sleep(2)
driver.execute_script("""document.querySelector('w3m-modal').shadowRoot.querySelector('w3m-modal-router').shadowRoot.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-modal-footer').querySelectorAll('w3m-wallet-button')[0].shadowRoot.querySelector('button').click();""")
time.sleep(5)
  • After clicking on the Connect to a Wallet, we wait for 1-2 seconds just to make sure that the overlay window is visibly present, although it appears very quickly.
  • The used javascript query to locate and click on the desired button
    document.querySelector('w3m-modal').shadowRoot.querySelector('w3m-modal-router').shadowRoot.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-modal-footer').querySelectorAll('w3m-wallet-button')[0].shadowRoot.querySelector('button').click();
    
    will click on the very first wallet, if you like to click on the 2nd or 3rd wallet option, just simply replace the querySelectorAll('w3m-wallet-button')[0] with querySelectorAll('w3m-wallet-button')[1] or querySelectorAll('w3m-wallet-button')[2] respectively in the above-mentioned javascript query.

Ajeet Verma
  • 2,938
  • 3
  • 13
  • 24
1

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
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352