Selenium select dropdown option - java

I'm going to say the dreaded words - i'm fairly new to java
But I can't find my answer online in the most obvious places so I'm going to ask the question here
The program i'm testing is a customer database, when you select the Country drop down box, other fields may become mandatory
Amongst those fields is "State"
This field can either be a free text or a drop down box
So i've created an if statement that lets me input free text if the conditions for a state drop down box is not met:
if (selenium.isElementPresent("xpath=//*[#id='state']/option[2]"))
{selenium.select("xpath=//select[#id='state']/option","index=2" );}
else {checkfield("xpath=//td[contains(.,'State/Province:')]/
preceding-sibling::td[contains(.,'*')]",
"xpath=//*[#id='address.state']",
state1);}
<td>
<!-- begin state drop down menu -->
<select id="state" name="address.state">
<option selected="selected" value="">Please Select</option>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="WY">Wyoming</option>
</select>
<!-- end state drop down menu -->
</td>
My question may be a very basic one and you guys can probably already see where my code fails
I want to choose option 2 of the drop down box if a drop down box is present, otherwise enter a string which has been declared in the free text box
up until now i've only ever used selenium.select for selecting a label which has specific text

Firstly: Upgrade to Selenium WebDriver
Selenium 1.0 is just an undead.
That's the way to do it with WebDriver:
if(stateDropdown.isEnabled()&&(!stateField.isEnabled())){
Select state = new Select(stateDropdown);
// state.selectByValue("Illinois");
state.selectByIndex(2);
}else if(stateField.isEnabled()&&(!stateDropdown.isEnabled){
stateField.sendKeys("Salzburg");
}
Isn't it pretty?

Could you try doing it using labels instead?
selenium.select("state", "label=Alaska")
You're likely to know what the values will be unless new states get added (seems unlikely)

Related

HTML5 input+datalist control item selection with Selenium

Use case is to select an item from a dropdown with help of selenium. I have tried the following but unable to achieve my goal. The input tag refers to a datalist .
String baseUrl = "https://angular-cwmwke.stackblitz.io" ;
driver.get(baseUrl); // opens the webpage
// Put some wait for the page to load the dropdown
driver.findElement(By.xpath("//input[#list='id-car']")).click(); // clicks on the dropdown
driver.findElement(By.xpath("//*[#id='id-car']/option[1]")).click(); // Does not works.
It fails and this is the exception .
JavascriptException: javascript error: option element is not in a select
Selenium version : 3.14.0 and
Chrome version : 78.0.3904.108
Here is the HTML ( Please ignore the option values ) :
<input _ngcontent-c0="" list="id-car" ng-reflect-model="[object Object]" class="ng-pristine ng-valid ng-touched">
<datalist _ngcontent-c0="" id="id-car">
<!--bindings={
"ng-reflect-ng-for-of": "[object Object],[object Object"
}-->
<option _ngcontent-c0="" value="[object Object]" ng-reflect-value="[object Object]">Ford-GTX</option>
<option _ngcontent-c0="" value="[object Object]" ng-reflect-value="[object Object]">Ferarri - Enzo</option>
<option _ngcontent-c0="" value="[object Object]" ng-reflect-value="[object Object]">VW - Amarok</option>
</datalist>
Some things to note initially about the datalist tag, this is different than a select in that a select element limits the choices to a predefined set, and a datalist gives suggested options, but can take any input. Also, the datalist options are usually used with the value attribute, so in this case (and you can test this manually too) when you click any option, the displayed value is the same ([object Object]).
That being noted, the reason you are getting an JavascriptException: javascript error: option element is not in a select is due to, I think, Selenium expecting option tags to be under a select element. The datalist tag operates more like a regular input text box than a select, and must be treated as such when using Selenium.
So, firstly, if you have access to that html code I would update the values to be what the text is now. It would look something like this:
<option _ngcontent-c0="" value="Ford-GTX" ng-reflect-value="Ford-GTX"/>
<option _ngcontent-c0="" value="Ferarri - Enzo" ng-reflect-value="Ferarri - Enzo"/>
<option _ngcontent-c0="" value="VW - Amarok" ng-reflect-value="VW - Amarok"/>
The Selenium code for "selecting" a certain option would then be something like this:
var input = driver.findElement(By.xpath("//input[#list='id-car']"));
var option = driver.findElement(By.xpath("//*[#id='id-car']/option[1]"));
var value = option.getAttribute("value");
input.clear();
input.SendKeys(value);
If this isn't the behavior you would like to achieve, and again you have access to the html, you might consider using a select element instead.
If you don't have access to the html, and really want to use the inner html text, you can simply modify the above code to reference the innerHTML instead of value:
var input = driver.findElement(By.xpath("//input[#list='id-car']"));
var option = driver.findElement(By.xpath("//*[#id='id-car']/option[1]"));
var text = option.getAttribute("innerHTML");
input.clear();
input.SendKeys(text);
Keep in mind however, that this might lead to some strange behavior upon form submit, as a true user click is displaying the value, and not the text.

SpringBoot & Thymeleaf multiple select dropdown not showing selected when editing

My project uses Java 8, Springboot 2 and Thymeleaf 3. I want to add a multiple select drop down to my form. I've tried it a few different ways, like trying to use Select2, and trying to just manually do it with Thymeleaf & Springboot.... I eventually got the select2 to work and make it a drop down view. I can get the functionality of it to work but can't get the selection to show up on the editable view. All options get to the SQL database, and if you only have one choice it will show on the edit page, but if more than one option is selected, it wont show anything on the edit broker page.
If I change to th:name instead of th:field, I can see the selected options, but now I can not save any options as well...
I am not getting any errors so I am not sure why this isn't working. Any idea what I need to do to get the edit view to show all options selected? Is it some sort of binding issue?
<select id="brokerTargetIndustries" th:field="*{brokerTargetIndustries}" multiple="multiple" class="text-left form-control" >
<option value="Social Service WC" th:selected="${broker!=null and broker!=null and broker.targetIndustries!=null and #strings.contains(broker.targetIndustries,'Social Service WC')}">Social Service WC</option>
<option value="Propane Fuel Dealers" selected="${broker!=null and broker.targetIndustries!=null and #strings.contains(broker.targetIndustries,'Propane Fuel Dealers')}">Propane/Fuel Dealers</option>
<option value="Building Services PKG" selected="${broker!=null and broker.targetIndustries!=null and #strings.contains(broker.targetIndustries,'Building Services PKG')}">Building Services PKG</option>
<option value="Contractor WC" selected="${broker!=null and broker.targetIndustries!=null and #strings.contains(broker.targetIndustries,'Contractor WC')}">Contractor WC</option>
</select>
Here is the controller for edit:
#RequestMapping(value="/edit/{id}")
public String editBroker(Model model,#PathVariable("id") Long id, Broker broker){
Broker existing = brokerRepository.findById(id).get();
model.addAttribute("broker",existing);
return "brokerProfile";
}

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.

Selenium select reports empty text selected option when there is a text in the selected option

I'm using selenium and at some point of my tests I'm checking a select box selected item text.
Selenium reports empty text
new Select(selectElement).getFirstSelectedOption().getText()
But if I inspect element code:
selectElement.getAttribute("innerHTML")
it reports somthing like
<option selected='selected' value='op1'>op1</option>
<option value='op2'>op2</option>
<option value='op3'>op3</option>
One thing that might be causing this (I'm not sure) is the fact that selenium is not being able to scroll to the element (it is in some other scenarios)
Does anyone have an idea?
Thanks

Categories