au3WebDriver icon indicating copy to clipboard operation
au3WebDriver copied to clipboard

Add _WD_FindElementFrames

Open mlipok opened this issue 3 years ago • 25 comments

Pull request

Proposed changes

There should be easy way to find element location in the frame list returned by _WD_FrameList

Checklist

  • [x] I have read and noticed the CODE OF CONDUCT document
  • [x] I have read and noticed the CONTRIBUTING document
  • [ ] I have added necessary documentation or screenshots (if appropriate)

Types of changes

Please check x the type of change your PR introduces:

  • [ ] Bugfix (change which fixes an issue)
  • [x] Feature (change which adds functionality)
  • [ ] Code style update (formatting, renaming)
  • [ ] Refactoring (functional, structural)
  • [ ] Documentation content changes
  • [ ] Other (please describe)

What is the current behavior?

No easy way to find element location in the frame list because _WD_FindElement finds element only in current location ( main document or desired frame selected by _WD_FrameEnter )

What is the new behavior?

It shoul be easie with _WD_ElementExist

Additional context

This was initially discussed here: https://github.com/Danp2/au3WebDriver/pull/362#issuecomment-1207494392

and here https://github.com/Danp2/au3WebDriver/pull/362#discussion_r944392108

System under test

not related

mlipok avatar Aug 24 '22 14:08 mlipok

@Danp2 Before I proceed with further work on this functionality, please check if you will initially accept it.

mlipok avatar Aug 24 '22 14:08 mlipok

Please check it with modified wd_demo.au3

mlipok avatar Aug 24 '22 22:08 mlipok

Please check it with modified wd_demo.au3

I did. Unfortunately, it doesn't work for me. This is what I get in the logs --

_WD_ElementExist ==> Success [0] : Parameters:   Strategy=css selector   Selector=div.trytopnav   ShadowRoot=Default    : LocationOfElement= null
wd_demo.au3: (583) : $sLocationOfElement1=null
<snip>
_WD_ElementExist ==> Success [0] : Parameters:   Strategy=css selector   Selector=div.trytopnav   ShadowRoot=Default    : LocationOfElement= null
wd_demo.au3: (606) : $sLocationOfElement2=null

Danp2 avatar Aug 25 '22 16:08 Danp2

And this are correct result. If you want other example provide another website where desired element is located in inner frame.

mlipok avatar Aug 25 '22 16:08 mlipok

OIC. I misinterpreted the results by assuming that "null" was incorrect.

Danp2 avatar Aug 25 '22 16:08 Danp2

OIC. I misinterpreted the results by assuming that "null" was incorrect.

So I assume that now you understand that 'null' is correct result as this is exact location for this element, as it is located on top window

mlipok avatar Aug 25 '22 17:08 mlipok

@mlipok Some feedback on this PR --

  • I'm still trying to understand the "Use Case" for this function.
  • I find the function name misleading. Have you considered any other names (ie: something like _WD_ElementContext)?
  • How do you plan to handle multiple matching elements? Hidden / disabled elements?

Danp2 avatar Aug 25 '22 19:08 Danp2

  • I'm still trying to understand the "Use Case" for this function.

When non advance user is using HTML DOM structure in browser DevTools to find element by XPATH or by CSSQuerySelector they do not bother about frames as because browser find them just a way. So user is using _WD_FindElement which as you can expect in case of frames do not find the desired element, because frame was not changed.

You can even teach user how to use browser to check if there are frames. But how would you like to pass the way of identifying a particular frame to the format required by _WD_FrameEnter ?

If user say my XPATH works in browser but not with _WD_FindElement then you should say: Before you use _WD_FindElement you should use the same XPATH with _WD_ElementExist / _WD_ElementeContext and result use with _WD_FrameEnter to change document context

mlipok avatar Aug 25 '22 20:08 mlipok

btw. Even I have sometimes problem with localizing the element in HTML DOM context . Of course I find them but it should be easier, and for this reason I create this function. As you can locate them easily on browser but this is not always easy to get the rigth path like null/2/0/1

mlipok avatar Aug 25 '22 20:08 mlipok

  • How do you plan to handle multiple matching elements? Hidden / disabled elements?

Multiple matching is good point. And will be added soon in this PR. Firstly I want be sure that current state is fine, and I can do next step = multiple element support

Hidden/Disabled that is not our concern. We only finding element locations. I can compare it to _WD_ElementFind which also to not bother about Hidden/Disabled status.

mlipok avatar Aug 25 '22 21:08 mlipok

  • I find the function name misleading. Have you considered any other names (ie: something like _WD_ElementContext)?

My observation:

  • The au3WebDriver UDF is using Frame in fucntion names not Context.
  • We are planing to have multiple Elements support
  • specific XPATH or CSSQuerySelector can locate multiple Elements on multiple Frames

My new proposals for function name are: _WD_GetElementsFramesLocations or _WD_ElementsFramesLocations or _WD_ElementsFrames

mlipok avatar Aug 25 '22 21:08 mlipok

  • I'm still trying to understand the "Use Case" for this function.

try to use:

_WD_Navigate($sSession, "https://www.tutorialspoint.com/html/html_frames.htm#")
_WD_ELementExist($sSession, $_WD_LOCATOR_ByCSSSelector, "li.nav-item[data-bs-original-title='Home Page'] a.nav-link[href='https://www.tutorialspoint.com/index.htm']")

mlipok avatar Aug 25 '22 21:08 mlipok

As you can locate them easily on browser but this is not always easy to get the rigth path like null/2/0/1

It's been a while since I've had to work with frames, but IIRC I always located the frame first with _WD_FindElement and then passed the Element ID to _WD_Window / _WD_FrameEnter.

My new proposals for function name are: _WD_GetElementsFramesLocations or _WD_ElementsFramesLocations or _WD_ElementsFrames

Only the last one has any chance of approval. 😉 Another for consideration is _WD_FindElementFrames.

Danp2 avatar Aug 25 '22 22:08 Danp2

_WD_FindElementFrames is the best.

mlipok avatar Aug 25 '22 22:08 mlipok

It's been a while since I've had to work with frames, but IIRC I always located the frame first with _WD_FindElement and then passed the Element ID to _WD_Window / _WD_FrameEnter.

I had today an issue related to frames which I solve using _WD_FrameList - I just observe when relative path was changed.

mlipok avatar Aug 25 '22 22:08 mlipok

  • I'm still trying to understand the "Use Case" for this function.

So is it now clear to you what is the purpose of this function ?

mlipok avatar Aug 25 '22 22:08 mlipok

So is it now clear to you what is the purpose of this function ?

I tried running your revised demo, but it didn't complete successfully --

__WD_FrameList_Internal ==> Webdriver Exception [10] : Parameters:    Level=null/0 Information: Error occured on "null/0" level when trying to check atributes child frames #0
_WD_FrameList ==> Webdriver Exception [10] : Parameters:    ReturnAsArray=True Information:  Was not able to check / back to "calling frame"
! ---> @error=10  @extended=0 : Example 7
_WD_ElementExist ==> General Error [1] : Parameters:   Strategy=css selector   Selector=li.nav-item[data-bs-original-title='Home Page'] a.nav-link[href='https://www.tutorialspoint.com/index.htm']   ShadowRoot=Default > Was not able to check / back to "calling frame" : StartLocatkon=    : LocationOfElement= 
wd_demo.au3: (711) : $sLocationOfElement3=

The error seems to originate on this line -- https://github.com/Danp2/au3WebDriver/blob/0eb6cc9cdb97e42219ed76485885c46b16ed5209/wd_helper.au3#L828

__WD_Post: URL=HTTP://127.0.0.1:4444/session/48e7da9c-3a00-4644-b871-ba2fa15123ea/execute/sync; Data={"script":"return document.querySelectorAll('iframe')[0].outerHTML;", "args":[]}
__WD_Post ==> Javascript Exception [21] : HTTP status = 500 ResponseText={"value":{"error":"javascript error","message":"TypeError: document.querySelectorAll(...)[0] is undefined","stacktrace":"@https://www.tutorialspoint.com/html/src/creating_frames.htm:2:23\n@https://www.tutorialspoint.com/html/src/creating_frames.htm:3:8\n"}}
_WD_ExecuteScript ==> Javascript Exception [21] : Error occurred when trying to ExecuteScript
__WD_FrameList_Internal ==> Webdriver Exception [10] : Parameters:    Level=null
_WD_FrameList ==> Webdriver Exception [10] : Parameters:    ReturnAsArray=True Information:  Was not able to check / back to "calling frame"
! ---> @error=10  @extended=0 : Example 7

Danp2 avatar Aug 25 '22 22:08 Danp2

So is it now clear to you what is the purpose of this function ?

I understand what it does. It just doesn't feel "natural" to me since I've never located a frame in that manner.

Danp2 avatar Aug 25 '22 22:08 Danp2

It just doesn't feel "natural" to me since I've never located a frame in that manner.

I am not surprised as the ability to specify a path is a new feature ;) It is only quite familiar to me as I'm the author of this concept :) ( using path like 'null/2/0' )

mlipok avatar Aug 25 '22 22:08 mlipok

@mlipok Did you miss this? #386 (comment)

WIP

mlipok avatar Aug 29 '22 13:08 mlipok

When I perform test then I have many issues with internet connectivity. I think my Zyxel UTM thinks my internet activity is suspicious.

mlipok avatar Sep 12 '22 13:09 mlipok

@mlipok Did you miss this? #386 (comment)

do you still have this? If you add 10 seconds of waiting after navigation (to be sure that everything is completed), does the problem stop or is it still happening?

mlipok avatar Sep 14 '22 13:09 mlipok

do you still have this?

Yes

If you add 10 seconds of waiting after navigation (to be sure that everything is completed), does the problem stop or is it still happening?

Still occurs

Danp2 avatar Sep 14 '22 13:09 Danp2

Here is short script to reproduce the issue --

	SetupChrome()
	_WD_Startup()
	$sSession = _WD_CreateSession($sDesiredCapabilities)
	_WD_Navigate($sSession, "https://www.tutorialspoint.com/html/html_frames.htm")
	_WD_LoadWait($sSession)

	_WD_FrameEnter($sSession, 0)
	Local $iCount = _WD_GetFrameCount($sSession) ; $iCount = 3
	;### Debug CONSOLE ↓↓↓
	ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iCount = ' & $iCount & @CRLF & '>Error code: ' & @error & @CRLF)

	_WD_ExecuteScript($sSession, "return document.querySelectorAll('iframe')[0].outerHTML;") ; JS error

	_WD_ExecuteScript($sSession, "return document.querySelectorAll('iframe')[0];")  ; ResponseText={"value":null}

	$result = _WD_ExecuteScript($sSession, "return document.querySelectorAll('iframe');") ; $result = {"value":[]}
	;### Debug CONSOLE ↓↓↓
	ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $result = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

Here's the console output --

__WD_Post: URL=HTTP://127.0.0.1:9515/session; Data={"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "excludeSwitches": [ "enable-automation", "enable-logging"]}}}}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":{"capabilities":{"acceptInsecureCerts":false,"browserName":"chrome","browserVersion":"105.0.5195.102","chrome":{"chromedriverVersion":"104.0.5112.79 (3cf3e8c8a07d104b9e1260c910efb8f383285dc5-refs/branch-heads/5112@{#1307})","userDataDir":"C:\\Users\\danpo\\AppData\\Local\\Temp\\scoped_dir8872_2135953312"},"goog:chromeOptions":{"debuggerAddress":"localhost:51843"},"networkConnectionEnabled":false,"pageLoadStrategy":"normal","platformName":"windows","proxy":{},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify","webauthn:extension:credBlob":true,"webauthn:extension:largeBlob":true,"webauthn:virtualAuthenticators":true},"sessionId":"8b0a345939d5bb12b6207257c82491a7"}}
_WD_CreateSession ==> Success [0] : 8b0a345939d5bb12b6207257c82491a7
__WD_Post: URL=HTTP://127.0.0.1:9515/session/8b0a345939d5bb12b6207257c82491a7/url; Data={"url":"https://www.tutorialspoint.com/html/html_frames.htm"}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":null}
_WD_Navigate ==> Success [0] : Parameters:   URL=https://www.tutorialspoint.com/html/html_frames.htm
__WD_Post: URL=HTTP://127.0.0.1:9515/session/8b0a345939d5bb12b6207257c82491a7/execute/sync; Data={"script":"return document.readyState", "args":[]}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":"complete"}
_WD_ExecuteScript ==> Success [0]
_WD_LoadWait ==> Success [0] : Parameters:    Delay=Default    Timeout=Default    Element=Default
__WD_Post: URL=HTTP://127.0.0.1:9515/session/8b0a345939d5bb12b6207257c82491a7/frame; Data={"id":0}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":null}
_WD_Window ==> Success [0] : Parameters:   Command=frame   Option={"id":0}
_WD_FrameEnter ==> Success [0] : Parameters:    Identifier=0
__WD_Post: URL=HTTP://127.0.0.1:9515/session/8b0a345939d5bb12b6207257c82491a7/execute/sync; Data={"script":"return window.frames.length", "args":[]}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":3}
_WD_ExecuteScript ==> Success [0]
_WD_GetFrameCount ==> Success [0]
@@ Debug(21) : $iCount = 3
>Error code: 0
__WD_Post: URL=HTTP://127.0.0.1:9515/session/8b0a345939d5bb12b6207257c82491a7/execute/sync; Data={"script":"return document.querySelectorAll('iframe')[0].outerHTML;", "args":[]}
__WD_Post ==> Javascript Exception [21] : HTTP status = 500 ResponseText={"value":{"error":"javascript error","message":"javascript error: Cannot read properties of undefined (reading 'outerHTML')\n  (Session info: chrome=105.0.5195.102)","stacktrace":"Backtrace:\n\tOrdinal0 [0x005F78B3+2193587]\n\tOrdinal0 [0x00590681+1771137]\n\tOrdinal0 [0x004A41A8+803240]\n\tOrdinal0 [0x004A6BB4+814004]\n\tOrdinal0 [0x004A6A72+813682]\n\tOrdinal0 [0x004A73EA+816106]\n\tOrdinal0 [0x004FE519+1172761]\n\tOrdinal0 [0x004ED7AC+1103788]\n\tOrdinal0 [0x004FDAE2+1170146]\n\tOrdinal0 [0x004ED5C6+1103302]\n\tOrdinal0 [0x004C77E0+948192]\n\tOrdinal0 [0x004C86E6+952038]\n\tGetHandleVerifier [0x008A0CB2+2738370]\n\tGetHandleVerifier [0x008921B8+2678216]\n\tGetHandleVerifier [0x006817AA+512954]\n\tGetHandleVerifier [0x00680856+509030]\n\tOrdinal0 [0x0059743B+1799227]\n\tOrdinal0 [0x0059BB68+1817448]\n\tOrdinal0 [0x0059BC55+1817685]\n\tOrdinal0 [0x005A5230+1856048]\n\tBaseThreadInitThunk [0x76E16739+25]\n\tRtlGetFullPathName_UEx [0x77AF8FD2+1218]\n\tRtlGetFullPathName_UEx [0x77AF8F9D+1165]\n"}}
_WD_ExecuteScript ==> Javascript Exception [21] : Error occurred when trying to ExecuteScript
__WD_Post: URL=HTTP://127.0.0.1:9515/session/8b0a345939d5bb12b6207257c82491a7/execute/sync; Data={"script":"return document.querySelectorAll('iframe')[0];", "args":[]}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":null}
_WD_ExecuteScript ==> Success [0]
__WD_Post: URL=HTTP://127.0.0.1:9515/session/8b0a345939d5bb12b6207257c82491a7/execute/sync; Data={"script":"return document.querySelectorAll('iframe');", "args":[]}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":[]}
_WD_ExecuteScript ==> Success [0]
@@ Debug(29) : $result = {"value":[]}
>Error code: 0

Danp2 avatar Sep 15 '22 15:09 Danp2

Analyzing.

mlipok avatar Sep 19 '22 21:09 mlipok

I have already done this function but there is too many conflict. I also have it developed on currently WIP (not jet merged PR's) I will back with new PR when ASAP. Temporary closing this PR.

mlipok avatar Mar 01 '23 22:03 mlipok