alb19542006 Posted July 12, 2018 Share Posted July 12, 2018 Could you please tell me where the complete UDF is located for download. The source code on GitHub has wd_core.au3, wd_helper.au3, and wd_test.au3, but no webdriver.au3. Thank you. Link to comment Share on other sites More sharing options...
Danp2 Posted July 12, 2018 Author Share Posted July 12, 2018 That is the complete source code. Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
BigDaddyO Posted July 16, 2018 Share Posted July 16, 2018 I've been using this with SalesForce and have a decent amount of luck with it. I needed to make a couple changes to two functions so far _WD_FrameEnter() SalesForce has many nested Frames and I needed to remove the $_WD_ELEMENT_ID in order to access any frame. expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name ..........: _WD_FrameEnter ; Description ...: This will enter the specified frame for subsequent WebDriver operations. ; Syntax ........: _WD_FrameEnter($sIndexOrID) ; Parameters ....: ; Return values .: Success - True ; Failure - WD Response error message (E.g. "no such frame") ; Author ........: Decibel ; Modified ......: 2018-04-27 ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _WD_FrameEnter($sSession, $sIndexOrID) Local $sOption Local $sResponse, $sJSON Local $sValue ;*** Encapsulate the value if it's an integer, assuming that it's supposed to be an Index, not ID attrib value. If IsInt($sIndexOrID) = True Then $sOption = '{"id":' & $sIndexOrID & '}' Else ;~ $sOption = '{"id":{"' & $_WD_ELEMENT_ID & '":"' & $sIndexOrID & '"}}' ;This won't work with Salesforce for some reason $sOption = '{"id":"' & $sIndexOrID & '"}' EndIf $sResponse = _WD_Window($sSession, "frame", $sOption) $sJSON = Json_Decode($sResponse) $sValue = Json_Get($sJSON, "[value]") ;*** Evaluate the response If $sValue <> Null Then $sValue = Json_Get($sJSON, "[value][error]") Else $sValue = True EndIf Return $sValue EndFunc ;==>_WD_FrameEnter Since SalesForce can take a long time to load some pages and controls, I'm using _WD_WaitElement a lot, so I updated it to return the Element(s) once it finally shows up. expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name ..........: _WD_WaitElement ; Description ...: Wait for a element to be found in the current tab before returning ; Syntax ........: _WD_WaitElement($sSession, $sElement, $sStrategy, $sSelector[, $iDelay = 0[, $iTimeout = -1]]) ; Parameters ....: $sSession - Session ID from _WDCreateSession ; $sStrategy - Locator strategy. See defined constant $_WD_LOCATOR_* for allowed values ; $sSelector - Value to find ; $sStartElement - [optional] a string value. Default is "". ; $lMultiple - [optional] True returns Array of Element ID's. Default is False. ; $iDelay - [optional] Milliseconds to wait before checking status ; $iTimeout - [optional] Period of time to wait before exiting function ; Return values .: Success - Element ID(s) returned by web driver ; Failure - 0 and sets the @error flag to non-zero ; @error - $_WD_ERROR_Success ; - $_WD_ERROR_Timeout ; Author ........: Dan Pollak ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _WD_WaitElement($sSession, $sStrategy, $sSelector, $sStartElement = "", $lMultiple = False, $iDelay = 0, $iTimeout = -1) Local Const $sFuncName = "_WD_WaitElement" Local $bAbort = False, $iErr, $iResult If $iTimeout = -1 Then $iTimeout = $_WD_DefaultTimeout Sleep($iDelay) Local $hWaitTimer = TimerInit() While 1 $FindRet = _WD_FindElement($sSession, $sStrategy, $sSelector, $sStartElement, $lMultiple) $iErr = @error If $iErr = $_WD_ERROR_Success Then $iResult = 1 ExitLoop ElseIf $iErr = $_WD_ERROR_NoMatch Then If (TimerDiff($hWaitTimer) > $iTimeout) Then $iErr = $_WD_ERROR_Timeout ExitLoop EndIf Else ExitLoop EndIf Sleep(1000) WEnd Return SetError(__WD_Error($sFuncName, $iErr), $iResult, $FindRet) EndFunc Link to comment Share on other sites More sharing options...
Danp2 Posted July 16, 2018 Author Share Posted July 16, 2018 @BigDaddyO Thanks for sharing. Which browser are you using to perform these actions? Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
BigDaddyO Posted July 16, 2018 Share Posted July 16, 2018 10 minutes ago, Danp2 said: @BigDaddyO Thanks for sharing. Which browser are you using to perform these actions? Chrome: Version 67.0.3396.99 (Official Build) (64-bit) Link to comment Share on other sites More sharing options...
Danp2 Posted July 17, 2018 Author Share Posted July 17, 2018 (edited) @BigDaddyO Based on my limited testing, I believe the issue lies with Chromedriver not conforming to the W3C specs. Firefox works fine with the UDF as-is, but fails when I implement your change. Chrome failed for me either way, returning __WD_Post: StatusCode=500; ResponseText={"value":{"error":"unknown error","message":"missing 'ELEMENT'(Session infochrome=67.0.3396.99)","stacktrace":"Backtrace:\n\tOrdinal0 [0x00C0DF70+778096]\n\tOrdinal0 [0x00BBB42D+439341]\n\tOrdinal0 [0x00B9807F+295039]\n\tOrdinal0 [0x00B80619+198169]\n\tOrdinal0 [0x00B78349+164681]\n\tOrdinal0 [0x00B7F96B+194923]\n\tOrdinal0 [0x00B7824F+164431]\n\tOrdinal0 [0x00B61B45+72517]\n\tOrdinal0 [0x00B62F2A+77610]\n\tOrdinal0 [0x00B62ECC+77516]\n\tGetHandleVerifier [0x00CA9936+3478]\n\tOrdinal0 [0x00C188C3+821443]\n\tOrdinal0 [0x00BC7066+487526]\n\tOrdinal0 [0x00BC7393+488339]\n\tOrdinal0 [0x00BC74A3+488611]\n\tOrdinal0 [0x00C1AA67+830055]\n\tOrdinal0 [0x00BC6DAF+486831]\n\tOrdinal0 [0x00BD13FE+529406]\n\tOrdinal0 [0x00BDC57B+574843]\n\tOrdinal0 [0x00BDC6CD+575181]\n\tOrdinal0 [0x00BDB92B+571691]\n\tBaseThreadInitThunk [0x75FA8484+36]\n\tRtlValidSecurityDescriptor [0x77362FEA+282]\n\tRtlValidSecurityDescriptor [0x77362FBA+234]\n"}} in one case and __WD_Post: StatusCode=404; ResponseText={"value":{"error":"no such frame","message":"(Session infochrome=67.0.3396.99)","stacktrace":"Backtrace:\n\tOrdinal0 [0x00C0DF70+778096]\n\tOrdinal0 [0x00BBB42D+439341]\n\tOrdinal0 [0x00B97E1D+294429]\n\tOrdinal0 [0x00B9A2C1+303809]\n\tOrdinal0 [0x00B80787+198535]\n\tOrdinal0 [0x00B78349+164681]\n\tOrdinal0 [0x00B7F96B+194923]\n\tOrdinal0 [0x00B7824F+164431]\n\tOrdinal0 [0x00B61B45+72517]\n\tOrdinal0 [0x00B62F2A+77610]\n\tOrdinal0 [0x00B62ECC+77516]\n\tGetHandleVerifier [0x00CA9936+3478]\n\tOrdinal0 [0x00C188C3+821443]\n\tOrdinal0 [0x00BC7066+487526]\n\tOrdinal0 [0x00BC7393+488339]\n\tOrdinal0 [0x00BC74A3+488611]\n\tOrdinal0 [0x00C1AA67+830055]\n\tOrdinal0 [0x00BC6DAF+486831]\n\tOrdinal0 [0x00BD13FE+529406]\n\tOrdinal0 [0x00BDC57B+574843]\n\tOrdinal0 [0x00BDC6CD+575181]\n\tOrdinal0 [0x00BDB92B+571691]\n\tBaseThreadInitThunk [0x75FA8484+36]\n\tRtlValidSecurityDescriptor [0x77362FEA+282]\n\tRtlValidSecurityDescriptor [0x77362FBA+234]\n"}} in the other. Edit: Seems they are already aware of the issue. Edited July 17, 2018 by Danp2 Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
Danp2 Posted July 17, 2018 Author Share Posted July 17, 2018 @BigDaddyO Regarding the enhancements to _WD_WaitElement, I understand the addition of the optional parameters to take full advantage of _WD_FindElement. Not sure I see the real benefit of returning the found elements. Please elaborate on how you are using this and why you this change is more desirable than making another call to _WD_FindElement. Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
BigDaddyO Posted July 17, 2018 Share Posted July 17, 2018 8 hours ago, Danp2 said: @BigDaddyO Regarding the enhancements to _WD_WaitElement, I understand the addition of the optional parameters to take full advantage of _WD_FindElement. Not sure I see the real benefit of returning the found elements. Please elaborate on how you are using this and why you this change is more desirable than making another call to _WD_FindElement. I guess because I'm lazy and don't want to write another line when the _WD_WaitElement just performed the _WD_FindElement command. Granted, the extra two options "", True in the function are a little annoying, perhaps putting those to the end since someone would most likely use the Delay and Wait options more often. Link to comment Share on other sites More sharing options...
BigDaddyO Posted August 3, 2018 Share Posted August 3, 2018 (edited) @Danp2 I created a _WD_WaitElementVisible() function based off your _WD_WaitElement() function. For most elements I don't need this, but I came across a popup that seems to get created and is hidden in the background after logging into the website so the _WD_WaitElement() returned right away. I needed to create this so it will wait for the element to exist AND be visible. I included the link to where I found the code which is apparently what the JQuery code .is(':visible') uses. OLD updated function is 2 posts below! expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name ..........: _WD_WaitElementVisible ; Description ...: Wait for a element to be found in the current tab and that its visible before returning ; Syntax ........: _WD_WaitElementVisible($sSession, $sElement, $sStrategy, $sSelector[, $iDelay = 0[, $iTimeout = -1]]) ; Parameters ....: $sSession - Session ID from _WDCreateSession ; $sStrategy - Locator strategy. See defined constant $_WD_LOCATOR_* for allowed values ; $sSelector - Value to find ; $iDelay - [optional] Milliseconds to wait before checking status ; $iTimeout - [optional] Period of time to wait before exiting function ; Return values .: Success - 1 ; Failure - 0 and sets the @error flag to non-zero ; @error - $_WD_ERROR_Success ; - $_WD_ERROR_Timeout ; Author ........: Dan Pollak, BigDaddyO added visible ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom/28933648 ; Example .......: No ; =============================================================================================================================== Func _WD_WaitElementVisible($sSession, $sStrategy, $sSelector, $iDelay = 0, $iTimeout = -1) Local Const $sFuncName = "_WD_WaitElement" Local $bAbort = False, $iErr, $iResult If $iTimeout = -1 Then $iTimeout = $_WD_DefaultTimeout Sleep($iDelay) Local $hWaitTimer = TimerInit() While 1 $FindRet = _WD_FindElement($sSession, $sStrategy, $sSelector) $iErr = @error If $iErr = $_WD_ERROR_Success Then Local $sJsonElement = '{"' & $_WD_ELEMENT_ID & '":"' & $FindRet & '"}' $sResponse = _WD_ExecuteScript($sSession, "return arguments[0].offsetWidth || arguments[0].offsetHeight || arguments[0].getClientRects().length", $sJsonElement) ;Not visible returns {"value":0} ;Visible returns a # for example {"value":115} $sJSON = Json_Decode($sResponse) ;Use Json_Decode to pull just the value from the response $isVisible = Json_Get($sJSON, "[value]") If $isVisible > 0 Then $iResult = 1 ExitLoop EndIf ElseIf $iErr = $_WD_ERROR_NoMatch Then If (TimerDiff($hWaitTimer) > $iTimeout) Then $iErr = $_WD_ERROR_Timeout ExitLoop EndIf Else ExitLoop EndIf Sleep(1000) WEnd Return SetError(__WD_Error($sFuncName, $iErr), $iResult) EndFunc Edited August 3, 2018 by BigDaddyO Danp2 found a better option Link to comment Share on other sites More sharing options...
Danp2 Posted August 3, 2018 Author Share Posted August 3, 2018 @BigDaddyO I haven't tested this, but the w3c specs show that you can check the element's visibility like this -- /session/{session id}/element/{element id}/displayed Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
BigDaddyO Posted August 3, 2018 Share Posted August 3, 2018 (edited) 3 hours ago, Danp2 said: @BigDaddyO I haven't tested this, but the w3c specs show that you can check the element's visibility like this -- /session/{session id}/element/{element id}/displayed That worked! at least in Chrome. I did have to update the _WD_ElementAction() Function to include 'displayed' as a valid command Switch $sCommand Case 'name', 'rect', 'text', 'selected', 'enabled', 'displayed' expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name ..........: _WD_WaitElementVisible ; Description ...: Wait for a element to be found in the current tab and that its visible before returning ; Syntax ........: _WD_WaitElementVisible($sSession, $sElement, $sStrategy, $sSelector[, $iDelay = 0[, $iTimeout = -1]]) ; Parameters ....: $sSession - Session ID from _WDCreateSession ; $sStrategy - Locator strategy. See defined constant $_WD_LOCATOR_* for allowed values ; $sSelector - Value to find ; $iDelay - [optional] Milliseconds to wait before checking status ; $iTimeout - [optional] Period of time to wait before exiting function ; Return values .: Success - 1 ; Failure - 0 and sets the @error flag to non-zero ; @error - $_WD_ERROR_Success ; - $_WD_ERROR_Timeout ; Author ........: Dan Pollak ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _WD_WaitElementVisible($sSession, $sStrategy, $sSelector, $iDelay = 0, $iTimeout = -1) Local Const $sFuncName = "_WD_WaitElementVisible" Local $bAbort = False, $iErr, $iResult, $isVisible If $iTimeout = -1 Then $iTimeout = $_WD_DefaultTimeout Sleep($iDelay) Local $hWaitTimer = TimerInit() While 1 $FindRet = _WD_FindElement($sSession, $sStrategy, $sSelector) $iErr = @error If $iErr = $_WD_ERROR_Success Then $isVisible = _WD_ElementAction($sSession, $FindRet, 'displayed') if $isVisible = True Then $iResult = 1 ExitLoop EndIf ElseIf $iErr = $_WD_ERROR_NoMatch Then If (TimerDiff($hWaitTimer) > $iTimeout) Then $iErr = $_WD_ERROR_Timeout ExitLoop EndIf Else ExitLoop EndIf Sleep(1000) WEnd Return SetError(__WD_Error($sFuncName, $iErr), $iResult) EndFunc Edited August 3, 2018 by BigDaddyO change needed to _WD_ElementAction() duzers 1 Link to comment Share on other sites More sharing options...
Danp2 Posted August 3, 2018 Author Share Posted August 3, 2018 @BigDaddyO Thanks for testing. I'll incorporate the change to _WD_ElementAction into the UDF. Would it make more sense to add a parameter to _WD_WaitElement instead of adding a whole new function? Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
BigDaddyO Posted August 3, 2018 Share Posted August 3, 2018 Yeah, that would make sense. I'm not sure yet if it should default to IsVisible or not. I'm still using my updated _WD_WaitElement that returns an elementID but it gets errors occasionally about stale elements so I have been meaning to change my code back to your Standard, it's just going to be a lot of work. Also, It seems that the function can use = True instead of = "true" so I'm going to update the function in the above post Link to comment Share on other sites More sharing options...
Danp2 Posted August 3, 2018 Author Share Posted August 3, 2018 For compatibility with existing scripts, I would recommend not checking the element's visibility by default. Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
Danp2 Posted August 5, 2018 Author Share Posted August 5, 2018 Here's the revised _WD_WaitElement with the optional visibility check. Seems to work well in my testing. Let me know if you encounter any issues. expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name ..........: _WD_WaitElement ; Description ...: Wait for a element to be found in the current tab before returning ; Syntax ........: _WD_WaitElement($sSession, $sStrategy, $sSelector[, $iDelay = 0[, $iTimeout = -1[, $lVisible = False]]]) ; Parameters ....: $sSession - Session ID from _WDCreateSession ; $sStrategy - Locator strategy. See defined constant $_WD_LOCATOR_* for allowed values ; $sSelector - Value to find ; $iDelay - [optional] Milliseconds to wait before checking status ; $iTimeout - [optional] Period of time to wait before exiting function ; $lVisible - [optional] Check visibility of element? ; Return values .: Success - 1 ; Failure - 0 and sets the @error flag to non-zero ; @error - $_WD_ERROR_Success ; - $_WD_ERROR_Timeout ; Author ........: Dan Pollak ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _WD_WaitElement($sSession, $sStrategy, $sSelector, $iDelay = 0, $iTimeout = -1, $lVisible = False) Local Const $sFuncName = "_WD_WaitElement" Local $bAbort = False, $iErr, $iResult, $sElement, $lIsVisible = True If $iTimeout = -1 Then $iTimeout = $_WD_DefaultTimeout Sleep($iDelay) Local $hWaitTimer = TimerInit() While 1 $sElement = _WD_FindElement($sSession, $sStrategy, $sSelector) $iErr = @error If $iErr = $_WD_ERROR_Success Then If $lVisible Then $lIsVisible = _WD_ElementAction($sSession, $sElement, 'displayed') EndIf If $lIsVisible = True Then $iResult = 1 ExitLoop EndIf ElseIf $iErr <> $_WD_ERROR_NoMatch Then ExitLoop EndIf If (TimerDiff($hWaitTimer) > $iTimeout) Then $iErr = $_WD_ERROR_Timeout ExitLoop EndIf Sleep(1000) WEnd Return SetError(__WD_Error($sFuncName, $iErr), $iResult) EndFunc BigDaddyO 1 Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
BigDaddyO Posted August 6, 2018 Share Posted August 6, 2018 I finished updating my Chrome SalesForce script to use this and everything is working as expected. Danp2 1 Link to comment Share on other sites More sharing options...
BigDaddyO Posted August 6, 2018 Share Posted August 6, 2018 (edited) Looks like the Return isn't setup properly in the _WD_WaitElement() It is returning the $iResult in @Extended. I think it should be something like this: Return SetError(__WD_Error($sFuncName, $iErr), 0, $iResult) Also, in the Local line, should $iResult be preset to 0 to return 0 if it errors? Edited August 6, 2018 by BigDaddyO Link to comment Share on other sites More sharing options...
Danp2 Posted August 6, 2018 Author Share Posted August 6, 2018 Thanks for the feedback. I'll make those corrections ASAP. Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
Danp2 Posted August 6, 2018 Author Share Posted August 6, 2018 I posted a new release on GH for anyone interested in the latest changes. Latest Webdriver UDF Release Webdriver Wiki FAQs Link to comment Share on other sites More sharing options...
BigDaddyO Posted August 7, 2018 Share Posted August 7, 2018 These are no longer in the wd_core.au3, is there a reason they were removed? Global Const $_WD_LOCATOR_ByID = "id" Global Const $_WD_LOCATOR_ByName = "name" Global Const $_WD_LOCATOR_ByClassName = "class name" Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now