12

With ASP.NET the tag IDs are pretty volatile so to make my tests more robust I want to locate elements by their label texts. I have played some with WatiN and it does this perfectly but that project seem kind of dead nowadays so I thought I'd look into Selenium as well before I decide on a framework.

I have html that looks something like this

<label for="ctl00_content_loginForm_ctl01_username">Username</label>:
<input type="text" id="ctl00_content_loginForm_ctl01_username" />

I don't want to type:

selenium.Type("ctl00_content_loginForm_ctl01_username", "xxx");

That is too reliant on the ID. In WatiN I'd write:

browser.TextField(Find.ByLabelText("Username")).TypeText("xxx");

Is there a way to do this in Selenium?

2
  • Sorry you got the impression WatiN is a dead project, but it is alive and kicking. Last December we did a release of WatiN 2.0 RC1. Jeroen van Menen Commented Jan 15, 2010 at 10:36
  • Well, you had a roadmap that mentioned a release q1 2009 and towards the end of 2009 it still hadn't been released and the roadmap hadn't been updated. Also, when I submitted a patch to the source forge feature request forum (to access raw html source) I didn't get any reply at all. It did seem like pretty dead project. I'm glad I was wrong. Commented Jan 23, 2010 at 12:25

4 Answers 4

14

This works:

//input[@id=(//label[text()="Username"]/@for)]

Explanation: Since you are looking for the input:

//input[@id=("ctl00_content_loginForm_ctl01_username")]

replace the "ctl00_content_loginForm_ctl01_username" by the attribute's value of the label:

//label[text()="Username"]/@for
Sign up to request clarification or add additional context in comments.

1 Comment

I had no idea you could use "sub-queries" in xpath. I no longer have access to the project where I had this problem, so I can't easily verify the solution. But it looks promising. Thanks!
7

I believe you can do this with the following:

selenium.Type(selenium.getAttribute("//label[text()='Username']/@for"), "xxx");

The text()='Username' bit gets the label you want by its innerHTML, then the /@for gives you back the value of its "for" attribute.

Heads up: this is not tested (apologies for that!) but I think it'll work, based on some tooling around in the IDE plugin

2 Comments

It looks promising. I will give it a try tomorrow.
Thanks. That worked fine (except GetAttribute should be capitalized). The syntax is nowhere near as nice as WatiN's but it will get the job done.
3

Ok, this may be a year old but what they hey. This will select the first input under a label containing the text 'Username'.

//label[text()='Username']/input

I generally prefer using contains() as I find that some browsers are adding annoying spaces into the occasional element:

//label[contains(., 'Username')]/input

Note that the single slash before input denotes it will only look one level down, where the double slash would check all levels under the label. Use XPather for Firefox to create and check your XPaths, it's very useful.

1 Comment

Yes, that question is a bit old, but I don't think I ever solved that problem in a clean way. The problem with your suggestion is that it requires the <input> input to be inside the <label> and that is not typically how they are used.
1

Yes, you can use XPath, CSS or DOM locators to identify your element. In this example your XPath could look like //lable[@for='ctl00_content_loginForm_ctl01_username'] to identify that particular label.

3 Comments

Except it's not the label I want to identify - it is the input box.
Oh then change the XPath to look for that input - in this case: //input[@id='ctl00_content_loginForm_ctl01_username'] Here is the explanation for it - you are looking for all the input elements (hence //) where the attribute id equals ctl00_content_loginForm_ctl01_username
Yes, but my whole problem is that I don't want any of the IDs in my test code since they change as soon as I change something on the page. There was more to my question than I could fit in the headline...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.