Danp2 / au3WebDriver

Web Driver UDF for AutoIt
MIT License
107 stars 21 forks source link

Frame issues #488

Open Danp2 opened 1 year ago

Danp2 commented 1 year ago
          I ran into problems handling frames on `Chrome` , so as so far I`m not able to test this.

Will open separate issue for handling frames.

Originally posted by @mlipok in https://github.com/Danp2/au3WebDriver/issues/487#issuecomment-1658496472

Danp2 commented 1 year ago

Could you test DemoFrames from wd_demo.au3 and say if it works fine for you on each browser ?

Can you be more specific? What errors / issues should I be looking for?

Danp2 commented 1 year ago

Seems like Chrome and Edge are failing on the tests that begin here --

#Region - Testing element location in frame set and iframe collecion

Danp2 commented 1 year ago

Also, all browsers are returning -1 for this line --

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

mlipok commented 1 year ago

So we have confirmed issue. Are you looking on this ? I be able in next few hours.

Danp2 commented 1 year ago

This is an example of what I'm seeing with Chrome --

    __WD_Post: URL=HTTP://127.0.0.1:9515/session/e28110002b6ee495e0a547c51014dc14/frame; Data={"id":0}
    __WD_Post ==> No match [8] : HTTP status = 404 ResponseText={"value":{"error":"no such frame","message":"no such frame\n  (Session info: chrome=115.0.5790.110)","stacktrace":"Backtrace:\n\tGetHandleVerifier [0x00ED1C53+49427]\n\t(No symbol) [0x00E65F41]\n\t(No symbol) [0x00D6C510]\n\t(No symbol) [0x00D71720]\n\t(No symbol) [0x00DC82AC]\n\t(No symbol) [0x00DB4A1C]\n\t(No symbol) [0x00DC6F2A]\n\t(No symbol) [0x00DB4816]\n\t(No symbol) [0x00D91127]\n\t(No symbol) [0x00D922AD]\n\tGetHandleVerifier [0x01127149+2496009]\n\tGetHandleVerifier [0x0116D572+2783794]\n\tGetHandleVerifier [0x01167491+2758993]\n\tGetHandleVerifier [0x00F511D0+571024]\n\t(No symbol) [0x00E6F96A]\n\t(No symbol) [0x00E6BD88]\n\t(No symbol) [0x00E6BE6B]\n\t(No symbol) [0x00E5EA97]\n\tBaseThreadInitThunk [0x74EA7D59+25]\n\tRtlInitializeExceptionChain [0x771FB79B+107]\n\tRtlClearBits [0x771FB71F+191]\n"}}
    _WD_Window ==> No match [8] : Parameters:   Command=frame   Option={"id":0}
    _WD_FrameEnter ==> Webdriver Exception [10] : Parameters:    Identifier=null/1/1/0 Error on ID#4 > {"id":0}

I'm not sure why this is occurring or when I will get a chance to take a closer look.

mlipok commented 1 year ago

Working on.

mlipok commented 1 year ago

some findings: https://bugs.chromium.org/p/chromedriver/issues/list?q=frame&can=2&sort=-id

https://bugs.chromium.org/p/chromedriver/issues/detail?id=4465&q=frame&can=2&sort=-id

https://bugs.chromium.org/p/chromedriver/issues/detail?id=4509&q=frame&can=2&sort=-id

https://bugs.chromium.org/p/chromedriver/issues/detail?id=4513&q=frame&can=2&sort=-id

mlipok commented 1 year ago

I already checked: Upcoming version: 115.0.5790.110 (r1148114)

https://googlechromelabs.github.io/chrome-for-testing/#stable https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/115.0.5790.110/win32/chromedriver-win32.zip

still the same issue

mlipok commented 1 year ago

It looks like when I use $__WDVERSION = "0.8.1" Together with current chromedriver.exe DemoFrames works fine.

mlipok commented 1 year ago

it looks that DemoFrames works fine with: https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom and had issues on: https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_iframe

https://www.tutorialspoint.com/html/html_frames.htm#

Danp2 commented 1 year ago

That's from over a year ago. 😦 I would recommend that you narrow down the cause so that it can be reproduced with a minimal set of code. Something like --

    _WD_Navigate($sSession, 'https://www.tutorialspoint.com/html/html_frames.htm#')
    _WD_LoadWait($sSession)
    $aFrameList = _WD_FrameList($sSession, True)

Even more ideal would be to eliminate _WD_FrameList and use _WD_Window commands instead.

mlipok commented 1 year ago

I was testing also other for example au3WebDriver-0.11.0 was first with _WD_FrameList so each older version has old DemoFrames

mlipok commented 1 year ago

Even more ideal would be to eliminate _WD_FrameList and use _WD_Window commands instead.

working on

mlipok commented 1 year ago
__WD_Post: URL=HTTP://127.0.0.1:9515/session/12e26bc8a5b17bb912c5cd72a5af6df5/execute/sync; Data={"script":"function FrameAttributes(FrameIDX) { let nodes = document.querySelectorAll('iframe');    if (nodes.length)   { return nodes[FrameIDX].outerHTML; }   else   { return window.frames[FrameIDX].frameElement.outerHTML; } }; return FrameAttributes(22);", "args":[]}
__WD_Post ==> Javascript Exception [23] : HTTP status = 500 ResponseText={"value":{"error":"javascript error","message":"javascript error: Cannot read properties of undefined (reading 'outerHTML')\n  (Session info: chrome=115.0.5790.110)","stacktrace":"Backtrace:\n\tGetHandleVerifier [0x003D1C63+49427]\n\t(No symbol) [0x00365F51]\n\t(No symbol) [0x0026C64D]\n\t(No symbol) [0x0026FAA2]\n\t(No symbol) [0x00270FD2]\n\t(No symbol) [0x002C7754]\n\t(No symbol) [0x002B4A1C]\n\t(No symbol) [0x002C6F2A]\n\t(No symbol) [0x002B4816]\n\t(No symbol) [0x00291127]\n\t(No symbol) [0x002922AD]\n\tGetHandleVerifier [0x00627159+2496009]\n\tGetHandleVerifier [0x0066D582+2783794]\n\tGetHandleVerifier [0x006674A1+2758993]\n\tGetHandleVerifier [0x004511E0+571024]\n\t(No symbol) [0x0036F97A]\n\t(No symbol) [0x0036BD98]\n\t(No symbol) [0x0036BE7B]\n\t(No symbol) [0x0035EAA7]\n\tBaseThreadInitThunk [0x76597D59+25]\n\tRtlInitializeExceptionChain [0x77E7B79B+107]\n\tRtlClearBits [0x77E7B71F+191]\n"}}
_WD_ExecuteScript ==> Javascript Exception [23] : javascript error: Cannot read properties of undefined (reading 'outerHTML')
Danp2 commented 1 year ago

I saw the same earlier today while testing DemoFrames. I think if you look earlier in the logs you will see the "no such frame" error like I posted above.

mlipok commented 1 year ago

Yes. I notice no such frame _WD_FrameEnter is not able to change frames. as for now I found quick solution in this function:

https://github.com/Danp2/au3WebDriver/blob/42dda7d9a9e78b3c7cc2d419b0e84eaf1335f6a8/wd_helper.au3#L848-L863

just modify this line: https://github.com/Danp2/au3WebDriver/blob/42dda7d9a9e78b3c7cc2d419b0e84eaf1335f6a8/wd_helper.au3#L863

;~  If $iErr = $_WD_ERROR_Success Then
    If 1 Then

and entire DemoFrames starts to works fine.

but as you can see not all frames are accesible: image

mlipok commented 1 year ago

It looks like some frames are blocked: image image

mlipok commented 1 year ago

After testing with FireFox the one thing what comes to my mind that Chrome gives us much more information.

Because FireFox returns only #39 frames and Chrome #145 frames

image

Danp2 commented 1 year ago

Because FireFox returns only #39 frames and Chrome #145 frames

I wonder if that's a function of the website where it renders the page differently based upon the browser in use. 🤔

mlipok commented 1 year ago

I think It is possible. I think that it depends on cookies and geolocation diferences in both browsers.

mlipok commented 1 year ago

ok so currently get another issue with: https://github.com/Danp2/au3WebDriver/blob/42dda7d9a9e78b3c7cc2d419b0e84eaf1335f6a8/wd_demo.au3#L942-L948

here is my modification:

    ; entering to the frame
    _WD_DebugSwitch($_WD_DEBUG_Full)
    _WD_FrameEnter($sSession, $sFrame)
    If @error Then Return SetError(@error, @extended, '')

    ClipPut(_WD_GetSource($sSession))
    MsgBox($MB_TOPMOST, "", 111)
;~  $aFrameList = _WD_FrameList($sSession, True, 0,100)
;~  _ArrayDisplay($aFrameList, 'Test 2', 0, 0, Default, $sArrayHeader)

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    ; get <select> element by it's name
    _WD_WaitElement($sSession,  $_WD_LOCATOR_ByXPath, '//*[@name="pets"]')
    If @error Then Return SetError(@error, @extended, '')
    _WD_DebugSwitch()
    MsgBox($MB_TOPMOST, "", 222)

please note that on FireFox it puts into clipboard entire desired frame content.

and for chrome you get: <html><head></head><body></body></html>

mlipok commented 1 year ago

this following part

    ; entering to the frame
    _WD_DebugSwitch($_WD_DEBUG_Full)
    _WD_FrameEnter($sSession, $sFrame)
    If @error Then Return SetError(@error, @extended, '')

    ClipPut(_WD_GetSource($sSession))
    MsgBox($MB_TOPMOST, "", 111)
;~  $aFrameList = _WD_FrameList($sSession, True, 0,100)
;~  _ArrayDisplay($aFrameList, 'Test 2', 0, 0, Default, $sArrayHeader)

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    ; get <select> element by it's name
    _WD_WaitElement($sSession,  $_WD_LOCATOR_ByXPath, '//*[@name="pets"]')
    If @error Then Return SetError(@error, @extended, '')
    _WD_DebugSwitch()
    MsgBox($MB_TOPMOST, "", 222)

will return

! Error = 7 occurred on: DemoSelectOptions
! _WD_LastHTTPResult = 404
! _WD_LastHTTPResponse = {"value":{"error":"no such element","message":"no such element: Unable to locate element: {\"method\":\"xpath\",\"selector\":\"//*[@name=\"pets\"]\"}\n  (Session info: chrome=115.0.5790.110)","stacktrace":"Backtrace:\n\tGetHandleVerifier [0x00351C63+49427]\n\t(No symbol) [0x002E5F51]\n\t(No symbol) [0x001EC64D]\n\t(No symbol) [0x00219818]\n\t(No symbol) [0x002198DB]\n\t(No symbol) [0x002487D2]\n\t(No symbol) [0x00234A64]\n\t(No symbol) [0x00246F2A]\n\t(No symbol) [0x00234816]\n\t(No symbol) [0x00211127]\n\t(No symbol) [0x002122AD]\n\tGetHandleVerifier [0x005A7159+2496009]\n\tGetHandleVerifier [0x005ED582+2783794]\n\tGetHandleVerifier [0x005E74A1+2758993]\n\tGetHandleVerifier [0x003D11E0+571024]\n\t(No symbol) [0x002EF97A]\n\t(No symbol) [0x002EBD98]\n\t(No symbol) [0x002EBE7B]\n\t(No symbol) [0x002DEAA7]\n\tBaseThreadInitThunk [0x76597D59+25]\n\tRtlInitializeExceptionChain [0x77E7B79B+107]\n\tRtlClearBits [0x77E7B71F+191]\n"}}

until you scroll into view #frame_advanced_select_with_multiple_features and '//*[@name="pets"]

mlipok commented 1 year ago

until you scroll into view #frame_advanced_select_with_multiple_features and '//*[@name="pets"]

is there something wrong with: _WD_WaitElement($sSession, $_WD_LOCATOR_ByXPath, '//*[@name="pets"]')

I mean _WD_WaitElement by defulat should not care about element visibilty:

    If $iOptions = Default Then $iOptions = $_WD_OPTION_None

    Local Const $bVisible = BitAND($iOptions, $_WD_OPTION_Visible)
    Local Const $bEnabled = BitAND($iOptions, $_WD_OPTION_Enabled)
    Local Const $bNoMatch = BitAND($iOptions, $_WD_OPTION_NoMatch)
    Local Const $bHidden = BitAND($iOptions, $_WD_OPTION_Hidden)
mlipok commented 1 year ago

Because FireFox returns only #39 frames and Chrome #145 frames

I wonder if that's a function of the website where it renders the page differently based upon the browser in use. 🤔

I think renderer currently in Chrome 115 stops to reneder/process iframes that are not visible, and thus using webedriver any frame/iframe element must be scrolled into view to be possible to enter the frame.

EDIT: Going to bed. Please analyze all my post/statment gvien here and give me back some answer/adivce.

Danp2 commented 1 year ago

DemoSelectOptions

Honestly, I think there is something odd with that website as I am unable to open any of the frames in a separate tab.

mlipok commented 1 year ago

Today I'm little tired. Going rest. Will back tomorrow.

Danp2 commented 1 year ago

until you scroll into view #frame_advanced_select_with_multiple_features and '//*[@name="pets"]

It seems like the Chromium based browsers aren't loading the frame until it is scrolled into view (AKA lazy loading). In my testing, I was able to solve this by adding the following prior to entering the frame, which forcibly scrolls the frame into view --

    _WD_ElementActionEx($sSession, $sFrame, 'hover')
mlipok commented 1 year ago

hm... it means that I should suplement _WD_FrameList accordingly

Danp2 commented 1 year ago

A few thoughts / suggestions --

mlipok commented 1 year ago

A few thoughts / suggestions --

  • Maybe you could make it optional? Otherwise, the webpage would be forced to unnecessarily scroll to each frame.

that was immediately one of my assumptions

  • Perhaps you could use _WD_GetSource to detect an empty frame and then react accordingly

good point.

  • It would be good to research further to confirm that this is the only reason that DemoFrames / _WD_FrameList is failing

will work on all of this

mlipok commented 1 year ago
_WD_ElementActionEx($sSession, $sFrame, 'hover')

using:

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    _WD_DebugSwitch($_WD_DEBUG_Full)
    Local $sFrame = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, '#frame_advanced_select_with_multiple_features')
    If @error Then Return SetError(@error, @extended, '')

    _WD_ElementActionEx($sSession, $sFrame, 'hover') ; https://github.com/Danp2/au3WebDriver/issues/488#issuecomment-1661174988
    If @error Then Return SetError(@error, @extended, '')

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    ; change the attributes of the frame to improve the visibility of the <select> element, on which the options will be indicated
    Local $sJavaScript = _
            "var element = arguments[0];" & _
            "element.setAttribute('height', '500');" & _
            "element.setAttribute('padding', '0');"
    _WD_ExecuteScript($sSession, $sJavaScript, __WD_JsonElement($sFrame), Default, Default)
    If @error Then Return SetError(@error, @extended, '')

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    ; entering to the frame
    _WD_DebugSwitch($_WD_DEBUG_Full)
    _WD_FrameEnter($sSession, $sFrame)
    If @error Then Return SetError(@error, @extended, '')

I get:

__WD_Post: URL=HTTP://127.0.0.1:9515/session/bba3ea86bc2b39a33cb42c3265d0be8b/actions; Data={"actions":[{"id":"hover","type":"pointer","parameters":{"pointerType":"mouse"},"actions":[{"type":"pointerMove","duration":100,"x":0,"y":0,"origin":{"ELEMENT":"18FD29400215F7FC504C27BDC0BF6041_element_81","element-6066-11e4-a52e-4f735466cecf":"18FD29400215F7FC504C27BDC0BF6041_element_81"}}]}]}
__WD_Post ==> Webdriver Exception [10] : HTTP status = 500 ResponseText={"value":{"error":"move target out of bounds","message":"move target out of bounds\n  (Session info: chrome=115.0.5790.110)","stacktrace":"Backtrace:\n\tGetHandleVerifier [0x00C11C63+49427]\n\t(No symbol) [0x00BA5F51]\n\t(No symbol) [0x00AAC510]\n\t(No symbol) [0x00B0D037]\n\t(No symbol) [0x00AF4A1C]\n\t(No symbol) [0x00B06F2A]\n\t(No symbol) [0x00AF4816]\n\t(No symbol) [0x00AD1127]\n\t(No symbol) [0x00AD22AD]\n\tGetHandleVerifier [0x00E67159+2496009]\n\tGetHandleVerifier [0x00EAD582+2783794]\n\tGetHandleVerifier [0x00EA74A1+2758993]\n\tGetHandleVerifier [0x00C911E0+571024]\n\t(No symbol) [0x00BAF97A]\n\t(No symbol) [0x00BABD98]\n\t(No symbol) [0x00BABE7B]\n\t(No symbol) [0x00B9EAA7]\n\tBaseThreadInitThunk [0x767D7D59+25]\n\tRtlInitializeExceptionChain [0x77A5B79B+107]\n\tRtlClearBits [0x77A5B71F+191]\n"}}
_WD_Action ==> Webdriver Exception [10] : Parameters:   Command=actions   Option={"actions":[{"id":"hover","type":"pointer","parameters":{"pointerType":"mouse"},"actions":[{"type":"pointerMove","duration":100,"x":0,"y":0,"origin":{"ELEMENT":"18FD29400215F7FC504C27BDC0BF6041_element_81","element-6066-11e4-a52e-4f735466cecf":"18FD29400215F7FC504C27BDC0BF6041_element_81"}}]}]}
_WD_ElementActionEx ==> Webdriver Exception [10] : Parameters:    Element=18FD29400215F7FC504C27BDC0BF6041_element_81    Command=hover    XOffset=Default    YOffset=Default    Button=Default    HoldDelay=Default    Modifier=Default    ScrollView=Default

I suppouse that there is no way to hover over frame. So I used:

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    _WD_DebugSwitch($_WD_DEBUG_Full)
    Local $sFrame = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, '#frame_advanced_select_with_multiple_features')
    If @error Then Return SetError(@error, @extended, '')

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    ; change the attributes of the frame to improve the visibility of the <select> element, on which the options will be indicated
    Local $sJavaScript = _
            "var element = arguments[0];" & _
            "element.setAttribute('height', '500');" & _
            "element.setAttribute('padding', '0');"
    _WD_ExecuteScript($sSession, $sJavaScript, __WD_JsonElement($sFrame), Default, Default)
    If @error Then Return SetError(@error, @extended, '')

    ConsoleWrite("- " & @ScriptLineNumber & @CRLF)
    ; entering to the frame
    _WD_DebugSwitch($_WD_DEBUG_Full)
    _WD_FrameEnter($sSession, $sFrame)
    If @error Then Return SetError(@error, @extended, '')

    Local $sHead = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, 'html head')
    _WD_ElementActionEx($sSession, $sHead, 'hover') ; https://github.com/Danp2/au3WebDriver/issues/488#issuecomment-1661174988
    _WD_LoadWait($sSession, 300)

And it works

mlipok commented 1 year ago

And it works

hm... not always:

_WD_FindElement ==> Success [0] : Parameters:   Strategy=css selector   Selector=html head   StartNodeID=Default   Multiple=Default   ShadowRoot=Default

__WD_Post: URL=HTTP://127.0.0.1:9515/session/333b2e873d78b47b4c633aa30906369e/execute/sync; Data={"script":"arguments[0].scrollIntoView(false);", "args":[{"element-6066-11e4-a52e-4f735466cecf":"C48325A13653E5B177A6E0EEE7D308C2_element_82"}]}
__WD_Post ==> Success [0] : HTTP status = 200 ResponseText={"value":null}
_WD_ExecuteScript ==> Success [0]

__WD_Post: URL=HTTP://127.0.0.1:9515/session/333b2e873d78b47b4c633aa30906369e/actions; Data={"actions":[{"id":"hover","type":"pointer","parameters":{"pointerType":"mouse"},"actions":[{"type":"pointerMove","duration":100,"x":0,"y":0,"origin":{"ELEMENT":"C48325A13653E5B177A6E0EEE7D308C2_element_82","element-6066-11e4-a52e-4f735466cecf":"C48325A13653E5B177A6E0EEE7D308C2_element_82"}}]}]}
__WD_Post ==> Element interaction issue [14] : HTTP status = 400 ResponseText={"value":{"error":"element not interactable","message":"element not interactable: [object HTMLHeadElement] has no size and location\n  (Session info: chrome=115.0.5790.110)","stacktrace":"Backtrace:\n\tGetHandleVerifier [0x00C11C63+49427]\n\t(No symbol) [0x00BA5F51]\n\t(No symbol) [0x00AAC64D]\n\t(No symbol) [0x00AAFAA2]\n\t(No symbol) [0x00AB0DAA]\n\t(No symbol) [0x00AB0E50]\n\t(No symbol) [0x00ADD5FF]\n\t(No symbol) [0x00ADCFA7]\n\t(No symbol) [0x00B0CF21]\n\t(No symbol) [0x00AF4A1C]\n\t(No symbol) [0x00B06F2A]\n\t(No symbol) [0x00AF4816]\n\t(No symbol) [0x00AD1127]\n\t(No symbol) [0x00AD22AD]\n\tGetHandleVerifier [0x00E67159+2496009]\n\tGetHandleVerifier [0x00EAD582+2783794]\n\tGetHandleVerifier [0x00EA74A1+2758993]\n\tGetHandleVerifier [0x00C911E0+571024]\n\t(No symbol) [0x00BAF97A]\n\t(No symbol) [0x00BABD98]\n\t(No symbol) [0x00BABE7B]\n\t(No symbol) [0x00B9EAA7]\n\tBaseThreadInitThunk [0x767D7D59+25]\n\tRtlInitializeExceptionChain [0x77A5B79B+107]\n\tRtlClearBits [0x77A5B71F+191]\n"}}
_WD_Action ==> Element interaction issue [14] : Parameters:   Command=actions   Option={"actions":[{"id":"hover","type":"pointer","parameters":{"pointerType":"mouse"},"actions":[{"type":"pointerMove","duration":100,"x":0,"y":0,"origin":{"ELEMENT":"C48325A13653E5B177A6E0EEE7D308C2_element_82","element-6066-11e4-a52e-4f735466cecf":"C48325A13653E5B177A6E0EEE7D308C2_element_82"}}]}]}
_WD_ElementActionEx ==> Element interaction issue [14] : Parameters:    Element=C48325A13653E5B177A6E0EEE7D308C2_element_82    Command=hover    XOffset=Default    YOffset=Default    Button=Default    HoldDelay=Default    Modifier=Default    ScrollView=Default

__WD_Post: URL=HTTP://127.0.0.1:9515/session/333b2e873d78b47b4c633aa30906369e/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 / 4] : Parameters:    Delay=300    Timeout=Default    Element=Default    DesiredState=complete    : ReadyState= complete (Fully loaded)
__WD_Get: URL=HTTP://127.0.0.1:9515/session/333b2e873d78b47b4c633aa30906369e/source
__WD_Get ==> Success [0] : HTTP status = 200 ResponseText={"value":"\u003Chtml>\u003Chead>\u003C/head>\u003Cbody>\u003C/body>\u003C/html>"}
_WD_GetSource ==> Success [0]
mlipok commented 1 year ago

The trick is to use:

Local $sHead = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, 'html body')

instead:

Local $sHead = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, 'html head')
mlipok commented 1 year ago

Here is first proposal for fix:

Func _WD_FrameEnter($sSession, $vIdentifier, $bHoverBody = True, $bLoadWait = True)
    Local Const $sFuncName = "_WD_FrameEnter"
    If String($vIdentifier) = 'null' Then $vIdentifier = Null ; String must be used because checking 0 = 'null' is True
    Local Const $bIsIdentifierNull = (IsKeyword($vIdentifier) = $KEYWORD_NULL)
    Local Const $sParameters = 'Parameters:    Identifier=' & ($bIsIdentifierNull ? ("Null") : ($vIdentifier) & '  HoverBody=' & $bHoverBody & ' LoadWait=' & $bLoadWait)
    Local $sValue, $sMessage = '', $sOption, $sResponse, $oJSON
    Local $iErr = $_WD_ERROR_Success

    ; must start with null or digit, must have at least one slash (may have many slashes but should not be followed one per other), must end with digit
    Local Const $bIdentifierAsPath = StringRegExp($vIdentifier, "(?i)\A(?:Null|\d+)(?:\/\d+)+\Z", $STR_REGEXPMATCH)

    If $bIdentifierAsPath Then
        ; will be processed below
    ElseIf $bIsIdentifierNull Then
        $sOption = '{"id":null}'
    ElseIf IsInt($vIdentifier) Then
        $sOption = '{"id":' & $vIdentifier & '}'
    Else
        $sOption = '{"id":' & __WD_JsonElement($vIdentifier) & '}'
    EndIf

    If Not $bIdentifierAsPath Then
        $sResponse = _WD_Window($sSession, "frame", $sOption)
        $iErr = @error
    Else
        Local $aIdentifiers = StringSplit($vIdentifier, '/')
        For $i = 1 To $aIdentifiers[0]
            If String($aIdentifiers[$i]) = 'null' Then
                $aIdentifiers[$i] = '{"id":null}'
            Else
                $aIdentifiers[$i] = '{"id":' & $aIdentifiers[$i] & '}'
            EndIf
            $sResponse = _WD_Window($sSession, "frame", $aIdentifiers[$i])
            If Not @error Then ContinueLoop

            $iErr = @error
            $sMessage = ' Error on ID#' & $i & ' > ' & $aIdentifiers[$i]
            ExitLoop
        Next
    EndIf

    If $iErr = $_WD_ERROR_Success Then
        $oJSON = Json_Decode($sResponse)
        $sValue = Json_Get($oJSON, $_WD_JSON_Value)

        ;*** Evaluate the response
        If $sValue <> Null Then
            $sValue = Json_Get($oJSON, $_WD_JSON_Error)
        Else
            $sValue = True
        EndIf
    ElseIf Not $_WD_DetailedErrors Then
        $iErr = $_WD_ERROR_Exception
    EndIf

    If $iErr = $_WD_ERROR_Success And $bHoverBody Then
        If $bLoadWait Then _WD_LoadWait($sSession, 50)
        Local $sHead = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, 'html body')
        _WD_ElementActionEx($sSession, $sHead, 'hover') ; https://github.com/Danp2/au3WebDriver/issues/488#issuecomment-1661174988
        If $bLoadWait Then _WD_LoadWait($sSession, 50)
    EndIf

    Return SetError(__WD_Error($sFuncName, $iErr, $sParameters & $sMessage), 0, $sValue)
EndFunc   ;==>_WD_FrameEnter

if you think that this is good direction, please open new PR for _WD_FrameEnter .

mlipok commented 1 year ago

I have one interesting notice/obervation: Each time I use wd_demo.au3 with DemoFrames which is a kind of checking/testing _WD_FrameEnter with relation to _WD_FrameList my UTM (Zyxel USG 40) block me (totally my IP even ping stop works). And this is not first time. I remember that I hit the same firewall issue when I was working on _WD_FrameList first time.

Danp2 commented 1 year ago

As we've found out recently with the changes to _WD_ExecuteScript, sometimes it's best to not make a change because it can have unintended consequences. While _WD_FrameEnter would appear to be the logical place to insert this code, doing so could cause other issues. Don't forget that we previously broke _WD_FrameEnter with the GUID validation in https://github.com/Danp2/au3WebDriver/commit/3a7921ca112830f6ccc2b2929d65df2b4126ea8c.

_WD_FrameEnter is working as intended, so I'm reluctant to make changes to it when there may be other (better) alternatives.

mlipok commented 1 year ago

As we've found out recently with the changes to _WD_ExecuteScript, sometimes it's best to not make a change because it can have unintended consequences.

I understand your point - I think it's right. But I believe that you also need to think about a step forward, so I propose a small change to my previous proposal.

So let's keep the current way of working by default, but let's add the possibility of extended operation. And in the future, if we decide somewhere that it is good to work in an extended way in other functions, it will not be a problem to immediately use this extended operation.

I mean that ultimately I want to add this action to _WD_FrameList() Of course, you're right that this will allow me to test beforehand whether implementing this change for _WD_FrameList will have a positive or negative result.

Summary: For me, at least for the moment , there is no doubt, however, that such a change will ultimately bring benefits. You can change my mind in this regard if you find good arguments.

So I suggest doing this change to my prev proposal, like this:

Func _WD_FrameEnter($sSession, $vIdentifier, $bHoverBody = False, $bLoadWait = False)
....

Instead of the earlier concept:

Func _WD_FrameEnter($sSession, $vIdentifier, $bHoverBody = True, $bLoadWait = True)
....
Danp2 commented 1 year ago

A few things that warrant further consideration / discussion --

mlipok commented 1 year ago

A few things that warrant further consideration / discussion --

  • Why did _WD_ElementActionEx($sSession, $sFrame, 'hover') work for me, but fail for you?

Do not know, still in testing. I can take a look again.

  • Could your proposal be handled by a single parameter instead of two? IE: $bForceLoad or something similar

Must to think about.

  • How do we know that html head will work correctly with all frames?

We can only try to check it on several pages. And in case of any problem in the future we can tries to react, find solution.

mlipok commented 1 year ago

modified version:

; #FUNCTION# ====================================================================================================================
; Name ..........: _WD_FrameEnter
; Description ...: Enter the specified frame.
; Syntax ........: _WD_FrameEnter($sSession, $vIdentifier[, $bForceLoad = False])
; Parameters ....: $sSession    - Session ID from _WD_CreateSession
;                  $vIdentifier - Target frame identifier. Can be any of the following:
;                  |Null    - Return to top-most browsing context
;                  |String  - Element ID from _WD_FindElement or path like 'null/2/0'
;                  |Integer - 0-based index of frames
;                  $bForceLoad   - [optional] Determine if Frame should be focused on and checked if is Fully loaded. Default is False.
; Return values .: Success - True.
;                  Failure - WD Response error message (E.g. "no such frame") and sets @error to one of the following values:
;                  - $_WD_ERROR_Exception
; Author ........: Decibel
; Modified ......: Danp2, mLipok, jchd
; Remarks .......: You can drill-down into nested frames by calling this function repeatedly or use identifier like 'null/2/0'
; Related .......: _WD_Window, _WD_LastHTTPResult
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _WD_FrameEnter($sSession, $vIdentifier, $bForceLoad = False)
    Local Const $sFuncName = "_WD_FrameEnter"
    If String($vIdentifier) = 'null' Then $vIdentifier = Null ; String must be used because checking 0 = 'null' is True
    Local Const $bIsIdentifierNull = (IsKeyword($vIdentifier) = $KEYWORD_NULL)
    Local Const $sParameters = 'Parameters:    Identifier=' & ($bIsIdentifierNull ? ("Null") : ($vIdentifier) & ' ForceLoad=' & $bForceLoad)
    Local $sValue, $sMessage = '', $sOption, $sResponse, $oJSON
    Local $iErr = $_WD_ERROR_Success

    ; must start with null or digit, must have at least one slash (may have many slashes but should not be followed one per other), must end with digit
    Local Const $bIdentifierAsPath = StringRegExp($vIdentifier, "(?i)\A(?:Null|\d+)(?:\/\d+)+\Z", $STR_REGEXPMATCH)

    If $bIdentifierAsPath Then
        ; will be processed below
    ElseIf $bIsIdentifierNull Then
        $sOption = '{"id":null}'
    ElseIf IsInt($vIdentifier) Then
        $sOption = '{"id":' & $vIdentifier & '}'
    Else
        $sOption = '{"id":' & __WD_JsonElement($vIdentifier) & '}'
    EndIf

    If Not $bIdentifierAsPath Then
        $sResponse = _WD_Window($sSession, "frame", $sOption)
        $iErr = @error
    Else
        Local $aIdentifiers = StringSplit($vIdentifier, '/')
        For $i = 1 To $aIdentifiers[0]
            If String($aIdentifiers[$i]) = 'null' Then
                $aIdentifiers[$i] = '{"id":null}'
            Else
                $aIdentifiers[$i] = '{"id":' & $aIdentifiers[$i] & '}'
            EndIf
            $sResponse = _WD_Window($sSession, "frame", $aIdentifiers[$i])
            If Not @error Then ContinueLoop

            $iErr = @error
            $sMessage = ' Error on ID#' & $i & ' > ' & $aIdentifiers[$i]
            ExitLoop
        Next
    EndIf

    If $iErr = $_WD_ERROR_Success Then
        $oJSON = Json_Decode($sResponse)
        $sValue = Json_Get($oJSON, $_WD_JSON_Value)

        ;*** Evaluate the response
        If $sValue <> Null Then
            $sValue = Json_Get($oJSON, $_WD_JSON_Error)
        Else
            $sValue = True
        EndIf
    ElseIf Not $_WD_DetailedErrors Then
        $iErr = $_WD_ERROR_Exception
    EndIf

    If $iErr = $_WD_ERROR_Success And $bForceLoad Then
        _WD_LoadWait($sSession, 50)
        Local $sHead = _WD_FindElement($sSession, $_WD_LOCATOR_ByCSSSelector, 'html body')
        _WD_ElementActionEx($sSession, $sHead, 'hover') ; https://github.com/Danp2/au3WebDriver/issues/488#issuecomment-1661174988
        _WD_LoadWait($sSession, 50)
    EndIf

    Return SetError(__WD_Error($sFuncName, $iErr, $sParameters & $sMessage), 0, $sValue)
EndFunc   ;==>_WD_FrameEnter
mlipok commented 1 year ago

maybe we can put this change to the upcomming new release ?

Danp2 commented 1 year ago

Please submit a PR so that this can be properly reviewed / tested.