2

Given this html:

<input id="test" value="my text" />

it is easy to get a handle on the input element with xpath. Something like:

input[@value="my text"]

But what if the original html looks like this:

<input id="test" />

It still has 'my text' in it if you look in the browser - because this has been added with javascript like this:

document.getElementById('test').value = 'my text';

In the fiddle you can see that the input field has the word(s) 'my text' in it but does not have a value attribute: https://jsfiddle.net/justinwyllie/5dsxa8mc/

How can I select this element? Just xpath - no jQuery.

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • What is the reason you don't want to use `id` to locate the element? Thanks. – alecxe Jun 14 '16 at 15:45
  • Another quick question: are you using `selenium` to locate the element? – alecxe Jun 14 '16 at 15:48
  • LOL. Yes. Selenium Python bindings. In my actual case there is no id. The element is generated by React. The only identifying factor was the value attribute. We've just updated React and the latest version (15.1.0) appears to no longer set the value attribute. –  Jun 14 '16 at 15:51
  • Gotcha - tagged the question with Python+Selenium and provided a Python+Selenium solution, hope you are okay with it. You cannot solve it with just xpath from what I understand. – alecxe Jun 14 '16 at 16:35
  • You should get a bonus point for guessing I was using Selenium. –  Jun 14 '16 at 17:16

1 Answers1

4

Taking into account that this is Python+Selenium, I would approach it the following way:

inputs = driver.find_elements_by_tag_name("input")  # TODO: improve the locator to get less input elements
input_elm = next(input_elm for input_elm in inputs 
                 if input.get_attribute("value") == "my text")

Note that get_attribute("value") would get the computed value of the .value property which is exactly why this would solve the problem.

Also note that next() would throw you the StopIteration exception if there would be no match - you can either handle that via try/except, or provide a default value:

input_elm = next((input_elm for input_elm in inputs 
                 if input.get_attribute("value") == "my text"), None)
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • Yep. That works. Not sure how you can do get_attribute("value") and that works? I guess the value attribute has been set but just not rendered into the DOM? –  Jun 14 '16 at 17:08
  • @JustinWyllie it is reading the `input` computed property..there is the difference between attributes and properties, please see http://stackoverflow.com/questions/6003819/properties-and-attributes-in-html. `get_attribute()` (link to the [source](https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/remote/webelement.py#L89)) would first see if there is a `value` property and, if there is as in this case, it would return it. Otherwise, it would have returned the `value` attribute which in this case is not specified. Hope that makes things a little clearer. – alecxe Jun 14 '16 at 17:15
  • It does. Thanks for your help. –  Jun 14 '16 at 17:29