Dynamic XPath- Selenium - selenium

I have the following dynamic xpath:
/html/body[#class='modal-open']/div[#class='container']/form[#id='form_application']/div[#id='interviewContent']/div[#class='modal-dialog']/div[#class='modal-content']/div[#class='modal-body']/div[#id='form_application:interviewContent']/div[#id='form_application:questionDropdown']/select[#id='form_application:j_idt473']
How can I make this unique for Selenium Web Driver? I was going to do a Starts-with method but this is pertaining to a drop down box where the values selected changes with each log in.
Page Source:
<br /><select id="form_application:j_idt473" name="form_application:j_idt473" class="form-control" size="1" style="width:250px;display:inline" onchange="mojarra.ab(this,event,'change','#this','form_application:questionDropdown form_application:dropdown_interview')"> <option value=""></option>
<option value="02">Alaska</option>
<option value="01">Alabama</option>
<option value="05">Arkansas</option>
<option value="60">American Samoa</option>
<option value="04" selected="selected">Arizona</option>
<option value="06">California</option>
""""

You can use css attribute selectors to match partial strings. I would get rid of that super complex xpath and use a contains selector instead to match a substring. Something like this should do the trick...
select[onchange*="form_application:questionDropdown form_application:dropdown_interview"]

As you mentioned in your Question that the xpath is dynamic and the HTML clearly shows the element as a <select> tag so we have to construct our xpath accordingly. I think you were quite right when you spoke about using Starts-with method as looking at the id and name attributes it seems to me though the attributes are dynamic but the string form_application: will be a constant. So we can use the following xpath :
Java
Select city = new Select(driver.findElement(By.xpath("//select[#class='form-control' and starts-with(#id,'form_application:')]")));
city.selectByIndex(2);
Python
select = Select(driver.find_element_by_xpath("//select[#class='form-control' and starts-with(#id,'form_application:')]"))
select.select_by_visible_text("Alabama")

Related

Creating an xpath with a dynamic id

I am having difficulty creating an xpath. I can write an xpath and map it directly to the id and it works fine. The problem arises when I need to select a different product. Most of the id is static and does not change, but the rest of it does change. I've tried writing an xpath with the contains clause and it still does not work.
Here is what I have tried:
//*[contains(#id, 'j_id0:j_id1:j_id6:section2:j_id34:j_id35:j_id67:j_id68:0:j_id138:j_id139:1:j_id219')]
//*[#id='j_id0:j_id1:j_id6:section2:j_id34:j_id35:j_id67:j_id68:']/option[5]
Here is the code I'm writing the xpath from:
<select id="j_id0:j_id1:j_id6:section2:j_id34:j_id35:j_id67:j_id68:0:j_id138:j_id139:0:j_id222" name="j_id0:j_id1:j_id6:section2:j_id34:j_id35:j_id67:j_id68:0:j_id138:j_id139:0:j_id222" class="user-success">
<option value="">--None--</option>
<option value="Budget">Budget</option>
<option value="Drop/New">Drop/New</option>
<option value="Management Change">Management Change</option>
<option value="Never Fulfilled">Never Fulfilled</option>
<option value="Product Swap">Product Swap</option><option value="Renewal">Renewal</option><option value="Stacked">Stacked</option></select>
Try using following:
//div[#class='user-success']/option[5]
This way you don't have to worry about changing xpath.

Selenium 3.0.1 with geckodriver 0.11.1 can't find correct option for select control

I just upgraded some functional testing code to use a newer version of Selenium and the required geckodriver, and now code that previously was selecting an option in an HTML select control is no longer working. I can reproduce the problem with a trivial page:
Here's the relevant code:
1. my_select = Select(driver.find_element_by_id("foo_select"))
2. my_select.select_by_value("3")
and the relevant HTML
<form>
<select id="foo_select" name="foo_select">
<option selected="selected" value="1">Ford</option>
<option value="2">Hyundai</option>
<option value="3">Jeep</option>
<option value="4">Kia</option>
<option value="5">Nissan</option>
<option value="6">Toyota</option>
</select>
</form>
I can check the value of my_select after 1 above and it does indeed refer to the select named "foo_select". But line 2 doesn't seem to be selecting the option with value "3" (it's not selecting anything. I've also tried the other "select_by.." variations). Indeed, if I look at my_select.first_selected_option (after 2) it still refers to the first option, "Ford".
The problem goes away when using Firefox 49. I was using 48.

Selenium XPath not found for IEDriver when I add URL/Domain in compatibility view

When I execute my script using IEDriver without compatibility view, my test script is running without any problem.
But, If I execute the same script after adding domain in compatibility view, then some elements are not found and I'm getting exceptions.
e.g.
I want to get text of selected item from this DOM:
<select id="selectNumber" name="selectNumber" style="width:180px;">
<option selected="selected" value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
and I'm using XPath .//*[#id='selectNumber']/option[#selected='selected']
to get text but it does not work.
I just checked that in IE DOM selected="selected" is not displayed for selected option until I change Document version manually.
You can use the Select class that works with every browser. Here's some code
Select sel = new Select(driver.findElement(By.id("selectNumber")));
WebElement selectOption = sel.getFirstSelectedOption();
String text = selectOption.getText();
I think you should consider to change from using XPath to use cssSelector. It's much safer to find the elements, not depending on the whole "path". There's a big chance it would not break when using cssSelector running with IEDriver (as you stated in your question).
You can achieve the same goal with both, but when you use XPath, your DOM is much more sensible to changes, and you have bigger chances to see tests broken after page changes.
For your case, you could use it in two ways:
XPath (as you must have it)
driver.findElement(By.xpath(".//*[#id='selectNumber']/option[#selected='selected']"))
Selector
driver.findElement(By.cssSelector("#selectNumber[selected]"))
When you have more complex "paths" you can combine more things like CSS classes in cssSelectors. For example (when you don't have ID):
<select class"nice-dropdown" name="selectNumber" style="width:180px;">
<option selected="selected" value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
driver.findElement(By.cssSelector("select.nice-dropdown")) (return the select element)
driver.findElement(By.cssSelector("select.nice-dropdown option[value='3']")) (return the option with value=3)
With selectors you have shorter "paths". They work in the same way as selectors are used in CSS.
As reference:
Selectors = w3schools
Selectors = W3C
Hope this information is somehow helpful.

How to retrieve a selected value from a list box?

HTML Content:
<select id="modalNewUser-body-information-timeZone" class="span12 ng-valid ng-dirty" ng-options="timezone for timezone in timezoneList" ng-model="newUser().timeZone" uid="timeZone" name="timezone">
<option selected="" value="">-- Select One --</option>
<option value="0">AST</option>
<option value="1">EST</option>
<option value="2">CST</option>
<option value="3">MST</option>
<option value="4">PST</option>
<option value="5">YST</option>
<option value="6">HST</option>
</select>
suppose I have selected 'EST' from the list box How can I retrieve it?
I am not able to retrieve with getFirstSelectedOption().getText()
Select select = new Select(driver.findElement(By.id("modalNewUser-body-information-timeZone")));
select.selectByVisibleText("EST");
String timeZone = select.getFirstSelectedOption().getText();
It is my understanding that you can only use Select elements when there is actually a 'select' tag. Often times, things that look like drop down boxes don't truly behave like Select elements. What if you tried to get the text this way (I'm C# here, but Java just has different capital letters for this, I believe):
string timeZone = driver.FindElement(By.XPath("//option[#value = '1']")).Text;
expected return: "EST"
You can try this:
$("#modalNewUser-body-information-timeZone option:selected").text();
The code provide by you is working fine for me.
Could you please update your selenium version and try again?
Following is the tested code:
Select select = new Select(abhiDriver.findElement(By.id("modalNewUser-body-information-timeZone")));
select.selectByVisibleText("EST");
String timeZone = select.getFirstSelectedOption().getText();
System.out.println(timeZone);

Using Selenium for selecting an option on a select with optgroup

I'm trying to select a value in a select element. I'm using Selenium RC (Java) to run the test cases. I understand that the code for selecting a value is given by:
selenium.select("locator", "value=REQUIRED VALUE")
I'm unable to select the desired value with the above code. I think it might be something to do with optgroup in the select source code. I do not get any exceptions, the command executes fine but looking at the page the required value is not selected.
Also, I cant use ids (instead of value) because there arent any. Here is the source code of the selector:
<select>
<optgroup label="Group1">
<option value="13">some value1</option>
<option value="25">some value2</option>
</optgroup>
<optgroup label="Group2">
<option value="18">REQUIRED VALUE</option>
<option value="34">some value3</option>
...
...
</optgroup>
</select>
Is there any way to select the required value using Selenium?
It would be great if we could avoid the option values (such as "18", "34" etc) because these numbers change later as the values change. For example, "REQUIRED VALUE" has a value -18 but if I were to delete this item and add it again its value would be different. Basically this drop-down box is dynamic.
The value for the required option in your example is actually '18'. Try the following:
selenium.select("locator", "label=REQUIRED VALUE")