Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with duplicate ids in selenium webdriver

I am trying to automate some tests using selenium webdriver. I am dealing with a third-party login provider (OAuth) who is using duplicate id's in their html. As a result I cannot "find" the input fields correctly. When I just select on an id, I get the wrong one.

This question has already been answered for JQuery. But I would like an answer (I am presuming using Xpath) that will work in Selenium webdriver.

On other questions about this issue, answers typically say "you should not have duplicate id's in html". Preaching to the choir there. I am not in control of the webpage in question. If it was, I would use class and id properly and just fix the problem that way.

Since I cannot do that. What options do I get with xpath etc?

like image 496
ftrotter Avatar asked Aug 14 '12 10:08

ftrotter


3 Answers

you can do it by driver.find_element_by_id, for example ur duplicate "duplicate_ID" is inside "div_ID" wich is unique :

driver.find_element_by_id("div_ID").find_element_by_id("duplicate_id")

for other duplicate id under another div :

driver.find_element_by_id("div_ID2").find_element_by_id("duplicate_id")
like image 129
Roshan Avatar answered Oct 31 '22 16:10

Roshan


This XPath expression:

//div[@id='something']

selects all div elements in the XML document, the string value of whose id attribute is the string "something".

This Xpath expression:

count(//div[@id='something'])

produces the number of the div elements selected by the first XPath expression.

And this XPath expression:

(//div[@id='something'])[3]

selects the third (in document order) div element that is selected by the first XPath expression above.

Generally:

(//div[@id='something'])[$k]

selects the $k-th such div element ($k must be substituted with a positive integer).

Equipped with this knowledge, one can get any specific div whose id attribute has string value "something".

like image 6
Dimitre Novatchev Avatar answered Oct 31 '22 15:10

Dimitre Novatchev


Which language are you working on? Dublicate id's shouldn't be a problem as you can virtually grab any attribute not just the id tag using xpath. The syntax will differ slightly in other languages (let me know if you want something else than Ruby) but this is how you do it:

driver.find_element(:xpath, "//input[@id='loginid']"

The way you go about constructing the xpath locator is the following: From the html code you can pick any attribute:

<input id="gbqfq" class="gbqfif" type="text" value="" autocomplete="off" name="q">

Let's say for example that you want to consturct your xpath with the html code above (Google's search box) using name attribute. Your xpath will be:

    driver.find_element(:xpath, "//input[@name='q']"

In other words when the id's are the same just grab another attribute available!

Improvement:

To avoid fragile xpath locators such as order in the XML document (which can change easily) you can use something even more robust. Two xpath locators instead of one. This can also be useful when dealing with hmtl tags that are really similar. You can locate an element by 2 of its attributes like this:

driver.find_element(:id, 'amount') and driver.find_element(xpath: "//input[@maxlength='50']")

or in pure xpath one liner if you prefer:

//input[@id="amount" and @maxlength='50']

Alternatively (and provided your xpath will only return one unique element) you can move one more step higher in the abstraction level; completely omitting the attribute values:

//input[@id and @maxlength]

like image 4
Xwris Stoixeia Avatar answered Oct 31 '22 17:10

Xwris Stoixeia