teodesian / Selenium-Remote-Driver

Perl Bindings to the Selenium Webdriver server
173 stars 91 forks source link

get_attribute can fail to return a value for an attribute that exists. #414

Closed tod222 closed 4 years ago

tod222 commented 5 years ago

There's another driver bug with get_attribute/get_property where it fails to return the value for an attribute present in the element. I've tested against both FF64 and FFesr60 and it's present in both.

It happens with surprising frequency as shown in the test below.

Output from running repro_ff_get_attribute_issue with FF64 (A means value from get_attribute, P would indicate value is from get_property, and U means undefined):

$ repro_ff_get_attribute_issue
<input class="gLFyf gsfi" maxlength="2048" name="q" type="text" jsaction="paste:puy29d" aria-autocomplete="both" aria-haspopup="false" autocapitalize="off" autocomplete="off" autocorrect="off" role="combobox" spellcheck="false" title="Search" value="" aria-label="Search">
class: U
maxlength: U
name: A "q"
type: A "text"
jsaction: U
aria-autocomplete: U
aria-haspopup: U
autocapitalize: U
autocomplete: A "off"
autocorrect: U
role: U
spellcheck: A "0"
title: A "Search"
value: A ""
aria-label: U

[#407 also involves get_attribute.]

teodesian commented 5 years ago

Looks like

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/outerHTML, {}
RES: {"value":"<input class=\"gLFyf gsfi\" maxlength=\"2048\" name=\"q\" type=\"text\" jsaction=\"paste:puy29d\" aria-autocomplete=\"both\" aria-haspopup=\"false\" autocapitalize=\"off\" autocomplete=\"off\" autocorrect=\"off\" role=\"combobox\" spellcheck=\"false\" title=\"Search\" value=\"\" aria-label=\"Search\">"}

<input class="gLFyf gsfi" maxlength="2048" name="q" type="text" jsaction="paste:puy29d" aria-autocomplete="both" aria-haspopup="false" autocapitalize="off" autocomplete="off" autocorrect="off" role="combobox" spellcheck="false" title="Search" value="" aria-label="Search">
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/class, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/class, {}
RES: {"value":null}

class: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/maxlength, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/maxlength, {}
RES: {"value":null}

maxlength: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/name, {}
RES: {"value":"q"}

name: A "q"
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/type, {}
RES: {"value":"text"}

type: A "text"
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/jsaction, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/jsaction, {}
RES: {"value":null}

jsaction: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/aria-autocomplete, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/aria-autocomplete, {}
RES: {"value":null}

aria-autocomplete: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/aria-haspopup, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/aria-haspopup, {}
RES: {"value":null}

aria-haspopup: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/autocapitalize, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/autocapitalize, {}
RES: {"value":null}

autocapitalize: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/autocomplete, {}
RES: {"value":"off"}

autocomplete: A "off"
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/autocorrect, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/autocorrect, {}
RES: {"value":null}

autocorrect: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/role, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/role, {}
RES: {"value":null}

role: U
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/spellcheck, {}
RES: {"value":false}

spellcheck: A "0"
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/title, {}
RES: {"value":"Search"}

title: A "Search"
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/value, {}
RES: {"value":""}

value: A ""
Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/aria-label, {}
RES: {"value":null}

Prepping getElementProperty
Executing getElementProperty
REQ: GET, http://127.0.0.1:9090/session/e079a028-2b0d-438b-be70-92cd5284e5bf/element/14a7bb3b-1895-4c35-9d6e-90a2bf998fd8/property/aria-label, {}
RES: {"value":null}

aria-label: U

Looks like we aren't getting anything back from the server. Not sure what you want me to do about that other than complain about the upstream devs, but I already do that plenty.

tod222 commented 5 years ago

I was afraid of that. Not much you can do.

Where do you complain? I haven't found where to submit feedback to FF. I looked at the archives for the tools-marionette list but there didn't seem to be any feedback there.

tod222 commented 5 years ago

Here's a problem, though: my script calls get_attribute first, but the driver uses the /property/ path. The log never shows the /attribute/ path getting used.

There should be more /attribute/ path entries than /property/ path entries as the script only calls get_property when get_attribute returns undef. But there are no /attribute/ path entries at all.

teodesian commented 5 years ago

So this is likely confused due to the fact that get_attribute actually got properties under JSONWire. You have to pass the 'no i really mean it' flag to get_attribute to not be "compatible" with the old way of doing things.

We are defaulting to making these methods aliases for each other by default because that's what JSONWire did, and the goal was to not break existing tests.

Passing 1 as the second arg to get_attribute actually gets the attribute. So, this is user error -- see the POD:

458 =head2 get_attribute
459 
460  Description:
461     Get the value of an element's attribute.
462 
463  Compatibility:
464     In older webDriver, this actually got the value of an element's property.
465     If you want to get the initial condition (e.g. the values in the tag hardcoded in HTML), pass 1 as the second argument.
466 
467     Or, set $driver->{emulate_jsonwire} = 0 to not have to pass the extra arg.
468 
469     This can only done on WebDriver 3 enabled servers.
470 
471  Input: 2
472     Required:
473         STRING - name of the attribute of the element
474     Optional:
475         BOOLEAN - "I really mean that I want the initial condition, quit being so compatible!!!"
476 
477 
478  Output:
479     {STRING | NULL} The value of the attribute, or null if it is not set on the element.
480 
481  Usage:
482     $elem->get_attribute('name',1);
483 
484 =cut
tod222 commented 5 years ago

Ahh, I read that several times and never got it. Keeping compatibility with old scripts is a good thing, but this could be clearer in the POD.

So, without arg2, or if arg2 == 0, it uses /property/. When arg2 != 0 it uses /attribute/.

I'll see if I can come up with some changes to the POD.

Thanks for clearing up my confusion!

teodesian commented 5 years ago

Any clarifications to POD would be appreciated -- this isn't the first time I've got an issue like this, so clearly something should be done; however given I'm the originator of the POD any solution I can come up with would be similarly unsatisfactory.