florentbr/SeleniumBasic

Cannot find element in selenium VBA

TorontoMapleLeaf opened this issue · 12 comments

Hello, everyone,

I try to locate the text " Chrome is up to date" after Chrome is updated, but cannot with all tries. below is the code:

Sub ChromeDriverUpdate()
Dim obj As WebDriver, By As New By
Dim sUrl As String , sXpath as String
Set obj = New WebDriver
sUrl = "chrome://settings/help"
sXpath = "//*[@id='updateStatusMessage']/div"
obj.Start "Chrome", ""
obj.Get sUrl
Application.Wait (Now + TimeValue("00:00:03"))

Debug.Print obj.FindElementById("updateStatusMessage").Text  ' this does not work
Debug.Print obj.FindElementByXPath(XPath).Text   ' this does not work

End Sub

neither find element by ID or Xpath worked. it always showed that "NoSuchElementError"

can anybody help me out?

thank you, ken

You have three shadow-roots in the dom tree path that you need to navigate around to get to that element. Unfortunately, I don't think SeleniumBasic has direct support for shadow-root dom, even though currently the Chrome/Edge drivers do support, and Firefox (geckodriver) is getting close.

So if you look at the full xpath to that element, you will see the shadow-root nodes indicated as "//" below:

/html/body/settings-ui//div[2]/settings-main//settings-about-page//settings-section[1]/div[2]/div[2]/div[1]/div

The only way I know to traverse that path in SeleniumBasic is something like this:

    Set webelem = driver.ExecuteScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-about-page').shadowRoot.querySelector('#updateStatusMessage')")
    Debug.Print  webelem.FindElement(By.Tag, "div").Text

Hope that helps...

Hi there,

while I am not call myself a Selenium professional I think I am pretty experienced and do some stuff with Selenium and VBA. I devleopped some routines also one for accessing shadowDOM which I need to click away the data protection banners.
You may refer to
https://www.youtube.com/watch?v=phYGCGXGtEw
https://titusfortner.com/2021/11/22/shadow-dom-selenium.html
for further information as well. Please note that you need to use CSS Seelctors to find elements under a shadwow DOM root.

Function findElementsShadowDOM(ByRef objSelenium As Selenium.WebDriver, ByVal s_XPath_ShadowHost As String, ByVal s_CSS_Elements As String) As Selenium.WebElements

Dim _
objShadowHost As Selenium.WebElement, _
objShadowRoot As Object
Set objShadowHost = objSelenium.FindElementByXPath(s_XPath_ShadowHost)
If Not objShadowHost Is Nothing Then
Set objShadowRoot = objShadowHost.ExecuteScript("return arguments[0].shadowRoot", objShadowHost)
If (TypeName(objShadowRoot) <> "Dictionary") Then
' Selenium 3 with Chrome-webdriver chromedriver.exe before 96.x
If objShadowRoot Is Nothing Then
Stop
End If
Set findElementsShadowDOM = objShadowRoot.FindElementsByCss(s_CSS_Elements)
Else
' Selenium 3 with Chrome-webdriver chromedriver.exe 96.x
' on error to catch error if subnode to shadowRoot not existing any more
On Error Resume Next
Set findElementsShadowDOM = objShadowHost.ExecuteScript("return arguments[0].shadowRoot.querySelectorAll(arguments[1])", Array(objShadowHost, s_CSS_Elements))
On Error GoTo 0
End If
End If

Set objShadowHost = Nothing
Set objShadowRoot = Nothing

End Function

However, due to unsecure future of SeleniumVBA I moved my stuff to Python. Python is a great platform and can be combined nicely with the COM technology using PyWin32 package by Mark Hammond.

Best regards
dornech

3/4 refers to the language bindings for Python etc. It is not related to SeleniumBasic

Happy to hear I could help.

Starting Python would mean you start with Python 3.10 or 3.11 probably. And the latest version of the packages which is 4.6.1 for the Python Selenium bindings (given you are working with a pretty late Chrome version).

with the help from Dornech, I got the solution to fix the issue .