webdriver icon indicating copy to clipboard operation
webdriver copied to clipboard

Add Locator strategy for finding an input (labellable) element by the text of the label

Open msingle opened this issue 3 years ago • 5 comments

Add a Locator Strategy for locating an input-type element (<select>, <input>, etc and potentially even non-input labellable elements) by the text of the label for that element.

In addition to being an incredibly common use case, this will encourage improving the accessibility (a11y) of the markup - forms having labels is one of the first checks by Chrome DevTools' Lighthouse, Firefox's Developer Tools (Accessibility tab) or other accessibility checkers. These are all based off the WCAG guidelines

I'll can write it up more formally with a pull request if it seems worthwhile.

(Originally created in https://github.com/SeleniumHQ/selenium/issues/9342)

msingle avatar Mar 29 '21 05:03 msingle

I'm in favour of anything that encourages improving a11y of markup, and which makes using webdriver easier. I'll happily review a PR for this.

shs96c avatar Mar 31 '21 10:03 shs96c

Your motivation sounds similar to gh-1440. That describes the feature in terms of the Accessible Name API, which may be a more powerful entry point than labellable elements.

jugglinmike avatar Apr 02 '21 03:04 jugglinmike

Just for clarity @msingle are you wanting to do the following (In python for simplicity)?

driver.find_element(By.LABEL, "some_text_in_a_for")

# this will then essentially do document.querySelectorAll("*[for='some_text_in_a_for']") which we can do the normal element storing etc

AutomatedTester avatar Apr 14 '21 14:04 AutomatedTester

Your motivation sounds similar to gh-1440. That describes the feature in terms of the Accessible Name API, which may be a more powerful entry point than labellable elements.

I think that this strategy is a half way point to #1440. One of the concerns for that was the performance cost of starting up the accessibility tree for webdriver while AOM is still being worked on.

AutomatedTester avatar Apr 14 '21 14:04 AutomatedTester

@AutomatedTester for some html like:

<form>
<label for="customerNameWithGeneratedID1234">Name:</label>
<input id="customerNameWithGeneratedID1234" name="customerNameWithGeneratedID1234" type="text" >
</form>
// something like the following javascript (i might have messed up some syntax) 
var labelNode = document.evaluate( '//label[contains(text(),"Name:")]', 
    document, 
    null, 
    XPathResult.FIRST_ORDERED_NODE_TYPE, 
    null ).singleNodeValue; // this could probably switched to a non-XPath javascript, but this is the basic idea
var idOfInput = labelNode.getAttribute("for") // will be 'customerNameWithGeneratedID1234'
return document.getElementById( idOfInput ); // will return the '<input>'

There are some significant corner cases (eg using <label> as the parent element of <input> ), but the idea is that knowing the Id of the desired input is a means to an end (and sometimes a complicated one), but not the actual objective.

msingle avatar Apr 15 '21 16:04 msingle