HTML5 input+datalist control item selection with Selenium - java

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.

Related

Selenium webdriver java - Automating Dojo Dropdown - Getting no such element exception

After clicking one hyperlink in my application. There is a Dojo popup appears mentioned below:
From the dropdown I need to select QA/SIT environment value.
HTML code for this is mentioned below:
<input class="dijitReset dijitInputInner" type="text" autocomplete="off" data-dojo-attach-point="textbox,focusNode" role="textbox" tabindex="0" id="dijit_form_FilteringSelect_0" aria-required="true" value="" aria-invalid="false">
Now, I tried below code to select the value from dropdown But I am getting no such element exception.
Select drpCountry = new Select(driver.findElement(By.xpath("//*[#id=\\\"dijit_form_FilteringSelect_0\\")));
drpCountry.selectByIndex(4);
I am getting below No such element exception error.
Can anyone please explain what I am missing here. How to Automate Dojo select dropdown
You can try below code to select your option. First click on drop down arrow present in there
:
String option = "QA/SIT"
driver.findElement(By.xpath("//input[#class='dijitReset dijitInputField dijitArrowButtonInner']")).sendKeys(option ) # Choose a valid xpath if its not correct
optionXpath = "//div[text()='"+option+"']"
optEle = driver.findElement(By.xpath(optionXpath ))
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(""arguments[0].click();",optEle );

How can i deselect an option from a dropdown, when that respective dropdown is not a "multi-select" / java & Selenium

I tried to use the objname.deselectByVisibileText() on multiple dropdowns (select/span) and I get the following error
Exception in thread "main" java.lang.UnsupportedOperationException: You may only deselect options of a multi-select.
How can I clear those respective fields? My method atm looks like this:
public void deselect(String s, String t)
{
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(s)));
Select select = new Select(element);
select.deselectByVisibleText(t);
}
Obviously, I need a solution without deselect, as none of them work (byValue, byIndex, etc.) due to the same error as above.
Typically the first option is the default. You can just select it.
select.selectByIndex(0);
If you have a select element that looks like this:
<select id="ddlViewBy">
<option value="1">test1</option>
<option value="2" selected="selected">test2</option>
<option value="3">test3</option>
</select>
Running the code:
var e = document.getElementById("ddlViewBy");
var strUser = e.options[e.selectedIndex];
would return the selected option.
Now you got to know the selected index. So, use javascript executor to unselect it

Pick value in dropdown menu using VBA web scrape

I've got an issue trying to select items from a dropdown menu on a javascript webpage. My end goal is to fill in the menu value via a userform but I'm not having any success creating the VB to select the drop down. Web code is below
<select name="dateSelector0" class="clsInputArea selectBox valid" style="display: none; "onchange="setDateRange(this, 'rtf[0].val1', 'rtf[0].val2')">
<option value="-1"></option>
<option value="1">Last Month</option>
<option value="2">Current Month</option>
<option value="3">Next Month</option>
<option value="4">Last Year</option>
<option value="5">Current Year</option>
<option value="6">Next Year</option>
<option value="7">First Quarter</option>
<option value="8">Second Quarter</option>
<option value="9">Third Quarter</option>
<option value="10">Fourth Quarter </option></select>
<a tabindex="NaN" title="" class="selectBox clsInputArea selectBox-dropdown" style="width: 147px; display: inline-block;" href="javascript:void(0);"><span class="selectBox-label" style="width: 127px;"> </span><span class="selectBox-arrow"></span></a>
I've tried various GetElementsBy, with both the above name, trying the below with the name and with ID rtf[0].val1 but to no avail, example below. I believe going by the dateSelector0 name will be best, but I would greatly appreciate input from those of you better at this than me.
ie.Document.Body.GetElementsByname("dateSelector0").Value = "1"
ie.Document.Body.GetElementsByname("dateSelector0").Item(0).FireEvent ("onchange")
You almost had it. I just tried:
Sub IE_Navigate()
'Declare
Dim IE As Object
'Use IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.navigate ("Website URL")
'Wait for Load to finish
While IE.readyState <> 4
DoEvents
Wend
Application.Wait (Now + TimeValue("0:00:01"))
Both of these approaches worked for me.
Select data from dropmenu by ClassName:
IE.document.getElementsByClassName("clsInputArea")(0).Value = 1
Or
Select data from dropmenu by Name
IE.document.getElementsByName("dateSelector0")(0).Value = 1
Which returned the first item from the drop down menu.
EDITED
If you observe the following CSS selector, where "." means class and " option" means select all "option" tags inside elements of that class (clsInputArea selectBox valid), you will see it makes the correct selections.
Note: You aren't allowed compound names in CSS selectors which is why the spaces are replaced with "." in the class name.
Sample CSS query results:
VBA:
Now, we can translate that into the following syntax:
ie.Document.getElementsByClassName("clsInputArea selectBox valid")(0).getElementsByTagName("option")
This assumes that index 0 is the correct one to use for elements of the class "select_list". You can easily inspect the collection to find the right index if you set it to a variable e.g.
Dim x As Object
Set x = ie.Document.getElementsByClassName("clsInputArea selectBox valid")(0).getElementsByTagName("option")
Assuming the object is not nothing then we can either select an option by its index (i.e. position) or by looping the collection and selecting when a certain condition is met e.g. its innerText matches a wanted phrase.
Selecting by Index:
This means for you you might say
x.SelectedIndex = 1 to select Last Month
Selecting by looping:
Dim currentOption As Object
For Each currentOption In x
If InStr(currentOption.innerText, "Last Month") > 0 Then
currentOption.Selected = True
Exit For
End If
Next currentOption
Full example of selecting drop down:
As you don't supply an URL, here is an example using a different website. The webpage target drop down, Código de Ativo, is shown here:
The target option to select is AALR21, which is number 3, or item 2 on 0 based index.
Looping and matching on the item innertext AAL21:
Option Explicit
Public Sub MakeSelectiong()
Dim IE As New InternetExplorer
Const URL = "http://www.debentures.com.br/exploreosnd/consultaadados/sndemumclique/"
Const optionText As String = "AALR21" 'Number2
Application.ScreenUpdating = False ' a.selectedIndex = 2
With IE
.Visible = True
.navigate URL
While .Busy Or .readyState < 4: DoEvents: Wend
Dim a As Object, currentOption As Object
Set a = .document.getElementById("ctl00_ddlAti")
For Each currentOption In a.getElementsByTagName("Option")
If InStr(currentOption.innerText, optionText) > 0 Then
currentOption.Selected = True
Exit For
End If
Next currentOption
Stop
.Quit
End With
End Sub
Selecting by index:
I could remove the entire loop and simply say:
a.selectedIndex = 2

How to retrieve the dynamic value in selenium webdriver

I'm trying to create the test cases using Selenium WebDriver with Java. I have the following HTML syntax in the source.
<label for="00N30000005wfev"><span class=class="requiredMark">*</span>Type</label>
<select id="00N30000005wfev" tabindex="34" name="00N30000005wfev">
<option value="Account">Account</option>
<option value="Client">Client</option>
<option value="Service">Service</option>
</select>
All the "for","id" and "name" value are dynamically generated when the application creates a new item every time. The label name is fixed for the item details. How can I dynamically retrieve this value based on the label name value (e.g. Type)?
When Java runs, it will look at the "Type" label first, then it will be able to find the "for" value.
Thanks
You could use a XPath expression to do this:
WebElement element = driver.findElement(By.xpath("//label[contains(text(),'Type')]"));
String labelForValue = element.getAttribute("for");

Selenium select dropdown option

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)

Categories