uezo / TinySeleniumVBA

A tiny Selenium wrapper written in pure VBA
MIT License
60 stars 16 forks source link

Add Method. IsElementPresent, IsEnabled, IsDisplayed #27

Open ghost opened 3 years ago

ghost commented 3 years ago

TinySeleniumVBA WebDriver.cls

' Is Element Present            '2021/7/3 add ishi
Public Function IsElementPresent(by_ As By, _
                                 value As String, _
                                 Optional ByVal sessionid As String = vbNullString) As Boolean
    ' ImplicitlyWait Get
    Dim timeout As Double
    timeout = GetImplicitlyWait
    ' ImplicitlyWait Disable
    ImplicitlyWait 0

    Dim data As Dictionary
    Set data = ToSelector(by_, value)
    If sessionid = vbNullString Then
        data.Add "sessionId", DefaultSessionId
    Else
        data.Add "sessionId", sessionid
    End If

    ' Set Method and Path
    Dim method As String: method = CMD_FIND_ELEMENT(0)
    Dim path As String: path = CMD_FIND_ELEMENT(1)

    ' Set params to path
    Dim dataKey As Variant
    For Each dataKey In data
        If VarType(data(dataKey)) = vbString Then
            path = Replace(path, "$" + dataKey, data(dataKey))
        End If
    Next

    ' Send request to selenium server
    Dim resp As Dictionary
    Set resp = SendRequest(method, UrlBase + path, data)

    ' ImplicitlyWait Setting
    ImplicitlyWait timeout

    ' Return Boolean
    If IsNull(resp("value")) Then
        IsElementPresent = True         'Set Execute = New Dictionary
    ElseIf TypeName(resp("value")) = "Collection" Then
        IsElementPresent = True         'Set Execute = resp("value")
    ElseIf VarType(resp("value")) = vbObject Then
        If resp("value").Exists("error") Then
            IsElementPresent = False    'Err.Raise 513, "WebDriver.Execute", JsonConverter.ConvertToJson(resp("value"))
        Else
            IsElementPresent = True     'Set Execute = resp("value")
        End If
    Else
        IsElementPresent = True         'Execute = resp("value")
    End If
End Function

' Is Enabled                    '2021/7/13 add ishi
Public Function IsEnabled(ByVal ElementId As String, _
                          Optional ByVal sessionid As String = vbNullString) As Boolean
    Dim data As New Dictionary
    If sessionid <> vbNullString Then
        data.Add "sessionId", sessionid
    End If
    data.Add "id", ElementId

    IsEnabled = Execute(CMD_IS_ELEMENT_ENABLED, data)
End Function

' Is Displayed                  '2021/7/13 add ishi
Public Function IsDisplayed(ByVal ElementId As String, _
                            Optional ByVal sessionid As String = vbNullString) As Boolean
    Dim data As New Dictionary
    If sessionid <> vbNullString Then
        data.Add "sessionId", sessionid
    End If
    data.Add "id", ElementId

    IsDisplayed = Execute(CMD_IS_ELEMENT_DISPLAYED, data)
End Function

TinySeleniumVBA WebElement.cls

' Is Enabled                        '2021/7/13 add ishi
Public Function IsEnabled() As Boolean
    IsEnabled = Driver_.IsEnabled(ElementId_, SessionId_)
End Function

' Is Displayed                      '2021/7/13 add ishi
Public Function IsDisplayed() As Boolean
    IsDisplayed = Driver_.IsDisplayed(ElementId_, SessionId_)
End Function
GCuser99 commented 2 years ago

Shouldn't the ImplicitlyWait methods in IsElementPresent function take sessionid as an input? And I suggest the following more efficient way to disable-enable Implicitly wait:

    'ImplicitlyWait Disable
    timeout = GetImplicitlyWait(SessionId)
    If timeout <> 0 Then Me.ImplicitlyWait 0, SessionId 

    'ImplicitlyWait Re-Enable
    If timeout <> 0 Then Me.ImplicitlyWait timeout, SessionId
GCuser99 commented 2 years ago

If you add the raise parameter to Execute function, as I demonstrated use for in Navigate function here, then IsElementPresent can be simplified as below:

Public Function IsElementPresent(by_ As by, ByVal value As String, Optional ByVal SessionId As String = vbNullString) As Boolean
    Dim timeout As Double, resp As Dictionary, Data As Dictionary

    timeout = GetImplicitlyWait(SessionId)
    If timeout <> 0 Then Me.SetImplicitlyWait 0, SessionId ' ImplicitlyWait Disabled

    Set Data = ToSelector(by_, value)
    If SessionId = vbNullString Then
        Data.Add "sessionId", DefaultSessionId
    Else
        Data.Add "sessionId", SessionId
    End If

    Set resp = Execute(CMD_FIND_ELEMENT, Data, False) 'don't raise an error if not found

    If resp("error") = "" Then
        IsElementPresent = True
    Else
        IsElementPresent = False
    End If

    If timeout <> 0 Then Me.SetImplicitlyWait timeout, SessionId 'ImplicitlyWait re-enabled

End Function

Here is what raise-enabled Execute looks like (edited to fix Execute bug #46 ):

Public Function Execute(driverCommand, Optional parameters As Dictionary = Nothing, Optional ByVal raise As Boolean = True)
    Dim method As String: method = driverCommand(0)
    Dim path As String: path = driverCommand(1)

    If parameters Is Nothing Then
        Set parameters = New Dictionary
    End If

    ' Set default session id if session id is missing
    If Not parameters.Exists("sessionId") Then
        parameters.Add "sessionId", DefaultSessionId
    End If

    'Set path params to path, and save non-path params to nonPathParameters
    Dim paramKey As Variant, nonPathParameters As New Dictionary
    For Each paramKey In parameters
         If InStr(path, "$" & paramKey) > 0 Then 'path parameter
            path = Replace(path, "$" & paramKey, parameters(paramKey))
        Else 'non-path parameter
            nonPathParameters.Add paramKey, parameters(paramKey)
        End If
    Next paramKey

    ' Send request to selenium server
    Dim resp As Dictionary
    Set resp = SendRequest(method, UrlBase + path, nonPathParameters)

    ' Return value(s)
    If IsNull(resp("value")) Then
        Set Execute = New Dictionary 'executescript returns vbnullstring
    ElseIf TypeName(resp("value")) = "Collection" Then
        Set Execute = resp("value")
    ElseIf VarType(resp("value")) = vbObject Then
        If resp("value").Exists("error") And raise Then
            'make this user optional
            Err.raise 513, "WebDriver.Execute", JsonConverter.ConvertToJson(resp("value"))
        Else
            Set Execute = resp("value")
        End If
    Else
        Execute = resp("value")
    End If

End Function
ghost commented 2 years ago

Thank You.

GCuser99 commented 2 years ago

Suggest to change method name IsElementPresent to IsPresent to be consistent with IsEnabled and IsDisplayed..

ghost commented 2 years ago

Change method name IsElementPresent to IsPresent.

' Is Present                    '2022/1/10 chg ishi
Public Function IsPresent(by_ As By, _
                          ByVal value As String, _
                          Optional ByVal sessionId As String = vbNullString) As Boolean
    Dim timeout As Double
    Dim Resp As Dictionary
    Dim Data As Dictionary

    timeout = GetImplicitlyWait(sessionId)
    If timeout <> 0 Then SetImplicitlyWait 0, sessionId      ' ImplicitlyWait Disable

    Set Data = ToSelector(by_, value)
    If sessionId = vbNullString Then
        Data.Add "sessionId", DefaultSessionId
    Else
        Data.Add "sessionId", sessionId
    End If

    Set Resp = Execute(CMD_FIND_ELEMENT, Data, False)("value")  ' don't raise an error if not present

    If Not Resp.Exists("error") Then
        IsPresent = True
    Else
        IsPresent = False
    End If

    If timeout <> 0 Then SetImplicitlyWait timeout, sessionId
End Function