Unable to Select From Dropdown By Index in Selenium and Java - java

I understand how to Select an element from dropdown using selectByIndex method. Howeverwhen I try to perform selectByIndex ( select.selectByIndex (index) ) on the following HTML snippet:
<select id="destinationAllocationId" name="destinationAllocationId">
<optgroup label="Anywhere Virtual Cards">
<option value="1555555555f0a19">NNN0 [*-2453]</option>
<option value="1555555555f0519">NNN1 [*-8354]</option>
<option value="155555555550419">NNN2 [*-5765]</option>
<option value="155555555520919">NNN3 [*-8875]</option>
</optgroup>
</select>
</div>
I'm unable to maintain the selected option.
At first it appears to work (the dropdown menu opens and the correct option is highlighted inblue). However as soon as the program continues with execution (something unrelated to dropdown) the dro pdown reverts back to the original state (the default option).
In other words, initially the the program selects the appropriate option just fine but it automatically reverts back to the default option and doesn't actually change the value in the dropdown once the dropdown menu disappears (Usually when I select an option manually I can see that option being selected once the drop down is closed however in this case as long as dropdown is open the option is selected but as soon as it closes the default option is selected)
Any ideas why this happens

i had this issue, too
this is how i solved it
/**
* helper method for handling drop downs
* #param idPrefix the id of the drop down without any _xy
* #param value the value to be selected
*/
public void clickDropdown(String idPrefix, String value) {
// find & click on the label element of the drop down
firefoxDriver.findElement(By.id(idPrefix + "_label")).click();
// find & choose element from drop down
firefoxDriver.findElement(By.xpath("//div[#id='" + idPrefix + "_panel']/div/ul/li[text()='" + value + "']")).click();
}
u call it like this:
// choosing an element in the drop down menu
clickDropdown("projectForm:stellvertreter", "StringToSelect");
this i wrote for use with primefaces, you have to modify it anyway but u get the idea
for the issue with selecting and reverting... try sending an enter key press to the selected item or clicking it again... didnt have that with my approach

Related

unable to get the default selected value of drop down from selenium

Scenario1: I have two fields in the screen district and territory. For some user it has default value selected and the drop down is disabled.
PFB code for reference.
<select id="abcd" name="xyz" class="12234" style="ghfhgfhfh">
<option class="hide" value="4541ghj" selected="">valley
none</option>
</select>.
I am trying to get the "valley none" as the output if the drop down is disabled.
Scenario 2: I have two fields in the screen district and territory. For some user it has default value selected and the drop down is enabled.
At this time I want to select the option from the drop down now.
For this I am trying to make a common code.
What I am doing now:-
I am making a select type element and them I am trying to get the default value by getfirstselectedvalue() and then saving it in the webelement and then I am doing .gettext(). to get the option selected.
other wise if the null is returned from thr firstselectvalue() function then I am trying to select the value by visible text.
Error:-
if the default value is selected and the drop down is disbaled The getfirstselectedvalue() function is returning null ,if the element type is select but if I make it as webelement and then doing gettext it gives me the value in the field but this cannot be done if the drop down is senabled as at that time the type to element should be select to select the value from enabled drop down. At both the scenario the class is select for the fields
Please help....
As mentioned by Greg we need the html and the code you tried for better understanding. However, this is the simple logic that you can use.
//get the listBox Element
WebElement list = driver.findElement(By.xpath("//select[#id='abcd']"));
// check if it's disabled
if (!list.isEnabled()) {
// get value from option 1 as listbox is disabled.
System.out.println(list.findElement(By.tagName("option")).getText());
}else {
// select value as listbox is enabled. (Chnage 'Scenario2' with desired list item
list.findElement(By.xpath(".//option[.='scenario2']")).click();
}

How to verify whether a tag is present in the html code for a drop down using java in Selenium Webdriver

I have a disabled drop down with Values auto populated as True or False. For the auto populated value, I can see a tag named "selected" when I do the inspect element.How can I verify whether the tag "Selected" is present for the drop down?
below is the HTML part
<select name="text" class="Product_Selected" disabled>
<Option value="Flag_True" selected>TRUE </option>
<Option value="Flag_False">False </option> ==$0
</select>
As you can see above, I have selected my previous input as TRUE, so next time im getting the drop down auto populated with TRUE and is DISABLED.
Is there any way where I can see whether tag "selected" is present for that disabled drop down using JAVA code for Selenium Webdriver
OR
Can I get the auto populated value of the Disabled Dropdown?
You don't have to do anything complicated... just treat it like any other SELECT element. There is a special class in Selenium designed to make it easier to interact with SELECT elements called... Select. I just tested this code with true and false selected and it works just fine even though the element is disabled.
Select e = new Select(driver.findElement(By.cssSelector("select.Product_Selected")));
System.out.println(e.getFirstSelectedOption().getText());
You get your SELECT element and send it to the Select constructor. Then you can interact with the Select element with all the new functionality. The example above just gets the selected option (first selected option in the case of a multi-select, but that doesn't apply here) and returns the text displayed, e.g. TRUE.

Is there any way to reduce element locating time in Selenium WebDriver?

I have one select city dropdown and there are around 8000 city presents. My usecase are:
Get the selected city name
If city name is not as expected then select the desired city
Now again get the city name to verify that desired city has been selected
My code is working fine but the issue is to complete these 3 steps it takes around 5-8 minutes. I know its due to the large set of city name available in dropdown
This is the dropdown HTML structure :
<div class="col-md-12">
<label class="mmk-filter-control">Preferred Source City : </label>
<div class="pull-right refe-link">
<div class="mmk-filter-control mmk-select-filter pull-right mr5">
<select id="ddlPrefferedSourceCity" class="form-control" name="ddlPrefferedSourceCity">
<option value="-1">- Select -</option>
<option value="A.S.Peta Bypass">A.S.Peta Bypass</option>
<option value="aadsar">aadsar</option>
<option value="aagariya">aagariya</option>
<option value="aahur">aahur</option>
<option value="aakadiya">aakadiya</option>
<option value="Aala">Aala</option>
<option value="Aanjangaon">Aanjangaon</option>
.
.
around 8000 options
And code is:
if(usersname.size()>0)
{
Select s = new Select(preferredCity);
Comman.wait.until(ExpectedConditions.invisibilityOf(loader));
String cityName = s.getFirstSelectedOption().getText();
if(cityName.equals(preferredCityName))
{
LogWriter.logger.info("Preferred City is already Selected");
TakeScreenshot.passedScreenShot();
}
else
{
Comman.wait.until(ExpectedConditions.invisibilityOf(loader));
LogWriter.logger.info("Last Selected Preferred City is : " + s.getFirstSelectedOption().getText());
TakeScreenshot.passedScreenShot();
s.selectByVisibleText(preferredCityName);
setPreferenceButton.click();
Comman.wait.until(ExpectedConditions.invisibilityOf(loader));
LogWriter.logger.info("New Selected Preferred City is : " + s.getFirstSelectedOption().getText());
TakeScreenshot.passedScreenShot();
}
}
Is there any way to overcome and make the test fast?
The issue is likely due to getFirstSelectedOption since the method sends the isSelected command for each option:
https://github.com/SeleniumHQ/selenium/blob/master/java/client/src/org/openqa/selenium/support/ui/Select.java#L93
So instead of :
s.getFirstSelectedOption().getText()
, I would use a selector to get the first selected option:
preferredCity.findElement(By.cssSelector("option[selected]")).getText()
Update
The selected attribute is not updated in the DOM when the selection changes.
So an alternative would be to read the selectedIndex property on <select> :
int selectedIndex = Integer.parseInt(preferredCity.getAttribute("selectedIndex"));
WebElement selectedOption = preferredCity.findElement(By.cssSelector(
String.format("option:nth-child(%s)", selectedIndex + 1)));
String text = selectedOption.getText();
or with executeScript:
String JS_GET_FIRST_SELECTED_OPTION =
"var e=arguments[0], i=e.selectedIndex; return i < 0 ? null : e.options[i];";
JavascriptExecutor jse = (JavascriptExecutor)driver;
WebElement selectedOption = (WebElement)jse.executeScript(JS_GET_FIRST_SELECTED_OPTION, preferredCity);
if (selectedOption == null)
throw new NoSuchElementException("No options are selected");)
String text = selectedOption.getText();
While 8000 cities in a single dropdown is a questionable design, it might not be the whole issue. I created a simple HTML file that contained 100,000 options and selected a value from that list and it was complete in 12s, including loading the entire page. Granted it wasn't hosted on the web. Your internet connection and/or the site's speed may be factors.
I would look at a few things:
You seem to be using WebDriverWait in Comman.wait (Common is misspelled, btw). Are you also using an implicit wait? If so, the docs state not to mix both.
WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times.
If you are, remove the implicit wait and see if that helps.
Next I would try getting some timings. Add a timing between each of the steps to see where the long waits lie. With that info, you will have a better idea of where the delays are coming from and how to address them.
You are waiting for the loader to be invisible more than I think is necessary. It shouldn't matter but removing some of them might help, especially if you are using an implicit wait (see #1). You wait for it after you grab the SELECT, which shouldn't be needed. You wait for it again in the first line of the else but you haven't done anything that should trigger a loader. The only place that seems reasonable is the 3rd instance, after you select the item from the dropdown.
Have you tried selecting by value instead of by visible text? It may not matter but I'm not really sure how it finds visible text.
Another option is to avoid use of the Select class altogether. While it's a good practice to use it normally because it makes dealing with SELECT so much easier, in this case it may be contributing to the performance issue.
One way to get around it may be to go after the option directly using a CSS selector, e.g. #ddlPrefferedSourceCity > option[value='" + preferredCityName + "']. I tried this on my local machine and it was slightly faster... but it's a difference of 1.2s vs .6s.
I really don't know why it is taking time to get the dropdown value using getFirstSelectedOption
I have tried JavascriptExecutor where i have populated value of the dropdown using jQuery command
public String getDropdownValue()
{
JavascriptExecutor e = (JavascriptExecutor) driver;
return (String) e.executeScript("return $('#ddlPrefferedSourceCity').val();");
}
Now I'm able to get the value even change the dropdown value and again find the selected value. And now the time is 5-8 second.

populate select box based on the another select box

There are two select boxes ,both of them are populating from database.second select box should be populate based on the value selected from the first select box.first select box is already populated but i am unable to populate the second select box
<select id="country_obj" name="custCountry" class="field_size_e">
<%
Iterator contryIter = countries.iterator();
Lookup lookup = null;
while(contryIter.hasNext()) {
lookup = (Lookup)contryIter.next();
if(bbForm.getCircuit().getCustCountry().equalsIgnoreCase(lookup.getLabel())){
out.print("<option selected=\"selected\" value='"+lookup.getValue()+"'");
out.print(">");
out.print(lookup.getLabel());
out.println("</option>");
}else{
out.print("<option value='"+lookup.getValue()+"'");
out.print(">");
out.print(lookup.getLabel());
out.println("</option>");
}
}
%>
</select>
how do i populate the second select box based on the value of first select box
You can have a function in javascript to populate options for your second select tag.
function populate(val)
{
//val is a string similar to "<option value='new_option'>new option</option><option...</option>..."
$('#my_select2').append(val);
}
//below method is triggered whenever you select a value for your first select box
$("#country_obj").change(function(){
var selected_str = $("#country_obj option:selected").text();
//now pass this selected_str to a php page where options generation method is present using $.ajax (refer http://api.jquery.com/jQuery.ajax/)
//or you can implement the method here (in javascript) to generate options for your new select tag.
}
})
Note: This is just for guidance. You can have implementations of both methods in one or you can have multiple methods. I'll leave that for you to decide.
EDIT: you can't have options generated for your second select tag in the same php page (like in your question) because, by the time your page is loaded and a user selects a value for first select tag your php code is already executed.

dynamically update textbox value from database when combobox value is changed

Here is the situation. I have a drop down menu. The option sin this drop down menu are being populated by fetching some values from the database. To do this following is what i have done.. :-
<select name="product_list" onchange="selectProduct(this.value)">
<option value="none">Select one</option>
<%
List<String> options = new ArrayList<String>();
DynamicCombo comboBox = new DynamicCombo();
options = comboBox.generateComboBox();
Collections.sort(options);
int tempVar = 0;
while (tempVar < options.size()) {
out.print("<option value=\"");
out.print(options.get(tempVar));
out.print("\">");
out.print(options.get(tempVar));
out.print("</option>");
tempVar++;
}
%>
</select>
DynamicCombo is a class that has a method called 'generateComboBox()'. This method simply returns an array list containing all the values that are fetched from the database, which is what i need to show in my drop down box in the front end (jsp page). On my jsp page i simply iterate through this list and print it as options appropriately.
This works absolutely fine.
Now i have another text box on my form, say 'textbox1'. Now the requirement is that this text box value should be updated depending on what the user has selected from the above drop down box.
So for example if the user selects 'prod1'(which is a primary key in the backend database table) option from the drop down box, then the corresponding value ( the product name) should be fetched from the database table and should be updated in the textbox named 'textbox1'.
The other thing is this entire thing is contained in a form which is supposed to be finally submitted to the servlet for further processing.
So how can i achieve this.
i figured out the solution to my own problem. It might not be the most elegant way of doing it, but it does the job pretty well.
So as per my requirement, what i exactly wanted to do was.... insert a value (that will be fetched from the database) into a text box on my form depending on what the user chooses from the drop down box that is already present on my form.
To achieve this, i went about and thought if some how i could nest a form withing my main form, it'd solve my issue. But i discovered that nesting of forms is not allowed. So the next option i thought of was to some how submit the same form without the user clicking on the submit button and also handle it appropriately as an 'incomplete' submit (in the sense that the form is still to be submitted manually by the user by clicking on the submit button) on the server.
So i simply made use of the 'onChange' event of a drop down box. I created an additional hidden field on my form.I wrote a simple javascript function that would simply set the value of the hidden field to the string-"partial Submit" and would submit my main form (say named 'form1') as :-
document.getElementById("hidden_id").setAttribute("value","partial submit");
form1.submit;
The function that does the above will be called whenever (and everytime) the onchange event of the drop down box gets fired.
When the user finally clicks on the submit button on the form to submit the finally completed form, then another javascript function is called that simply sets the value of the hidden field on the form to the string, "final submit" and would submit the form as :-
document.getElementById("hidden_id").setAttribute("value","final submit");
form1.submit;
Now on my server, i checked for the value of this hidden field as :-
if(request.getParameter("hidden_id").equals("partial Submit"))
{
// make a database connection, pass the value user selected from the drop down box
// to a prepared statement that does the query for getting the 'productName' from
// the database, collect the returned string in a variable and set a
// request attribute with this returned value. This value can simply be used in the
// jsp to fill in the value part of the textbox1.
}
else
{
if(request.getParameter("hidden_id").equals("final Submit"))
{
// do the rest of the final processing that needs to be done when user finally
// submits the completed form.
}
else
{
// throw an exception to take care of the possibility that the user might send
// in a 3rd value as a value for the hidden field.
}
}
Since you havent provided the code for selectProduct(this.value) , i presume that it submits the jsp page as when you change the value in the drop down.
If that the case in the servelt, set the value that you want to show in jsp in request object
request.setAttribute("valuetodisplay" ,valuetodisplay);
and now in jsp
<input type="text" value ='<%= request.getAttribute("valuetodisplay")%>' />

Categories