Is there a way to select by attribute? We have select drop down with incomplete visible text. We have to rely only on title. Is there a way to select by attribute?
My HTML looks something like
<select id="some ID" name="some Name" class="some class"
<option value="random number" title="testing pvt ltd">testing...</option>
<option value="random number" title="selenium HQ documentation">testing...
</option>
<option value="random number" title="selenium HQ API Request">selenium HQ...
</option>
Not natively, but nothing prevents you from implementing that method yourself, should you need it.
Something like this in C# should do the trick. Translation in your favourite language shouldn't be too hard.
public IWebElement GetWebElementByAttributeValue(string tagType, string attributeName, string attributeValue)
{
//finds all tags of a type, for example h1,a,etc...
//Here Driver is my instance of WebDriver
var allTags = Driver.FindElements(By.XPath("//" + tagType));
//iterate over all elements of that tag, and find the one whose attribute value you want
foreach (var v in allTags)
{
if ((v.GetAttribute.getText().equals(attributeName))
return v;
}
return null;
}
for you you would call it like that :
WebElement chosenOption = GetWebElementByAttributeValue("option","title","testing pvt ltd");
Hope this helps !
Naturally - the locators will go after the specific attribute and value.
Here are samples based on your source; xpath:
//select/option[#title="testing pvt ltd"]
If you're not familiar with xpath, it reads - select the option element that is a direct descendant (e.g. a child) of a select one, and has an attribute title (note the # char, which denotes thst an attribute name follows) with that value.
Absolutely the same with CSS:
select>option[title="testing pvt ltd"]
In general in CSS you can skip the double quotes around the value, if there's no whitespace in it - not like in your case, they are needed here.
el("input[value*='Edit'][type='submit']")
works without issue. I am using Fluentlenium and it makes thing a whole lot easier.
Use selectByValue method under Select class.
Related
I'm brand new to javascript, dojo and HTML and I've searched everywhere for examples of this and cannot find any.
I have a map with some feature points and a find task to highlight the feature points on the map, and display them in a grid with it's field attributes. This works great when I specify the search field as:
findParams.searchFields = ["LOCATION"];
But if I add:
findParams.searchFields = ["LOCATION", "MODEL_NUM"];
The grid displays results from multiple fields (ie. searching for attributes in LOCATION "A" would also find attributes in MODEL_NUM containing the letter "A"). So I decided to add a drop down menu select to specify which field to search in (one at a time) so the results are more precise.
So I added the following dijit:
<select id="fieldSelect" data-dojo-type="dijit/form/Select" name="fieldSelect">
<option value="" selected="selected">Select a field</option>
<option value="MODEL_NUM">Model Number</option>
<option value="LOCATION">Location</option>
<option value="NUM_DEFICIENCIES">Number of Deficiencies</option>
<option value="INSTALL_DATE">Install Date</option>
</select>
I then modified the search field statement to:
findParams.searchFields = "[" + "\"" + dom.byId("fieldSelect").value +
"\"" + "]";
When I click my search button I get an Uncaught TypeError: a.join is not a function (FindParameters.js:5)
I hope this is enough information. Does anyone have a solution or a recommendation?
UPDATE
After a suggestion to pass an array and not a string to the findParams.searchFields, I made the following changes:
findParams.searchFields = [];
findParmas.searchFields.push(dom.byId("fieldSelect").value);
This still gave me attribute results from multiple fields. After running a couple small tests:
var selectedField = document.getElementById('fieldSelect').value;
var index = selectedField.options[selectedField.selectedIndex].value;
And:
var selectedField = dom.byId('fieldSelect').value;
I'm finding that in the Chrome developer tools debugger, when I created a breakpoint at that line and executed the statement, both examples had the value of selectedField as 'undefined'.
Is this an issue of not getting the value from the drop down select dijit?
If no value is passed to findParams.searchFields, the API assumes all fields are valid, which is why I'm getting attribute results from multiple fields.
Thanks.
Use dijit.byId instead of dom.byId.
The following works for me:
var value = dijit.byId("fieldSelect").value;
if ("" != value) {
findParams.searchFields = [value];
} else {
findParams.searchFields = ["MODEL_NUM", "LOCATION", "NUM_DEFICIENCIES", "INSTALL_DATE"];
}
I found the problem.
Ultimately it was the registry.byId that led me to the answer, I had to rearrange some code after I realized the searchFields was in the wrong function and not in the function that is called when I click the search button.
But when accessing the dijit, the only thing that worked was registry.byId to access the dijit node and pass the value of the selected value into my searchFields.
Thanks.
The HTML code is given attached, I do not want to use hard code xpath, the requirement is to make it generic:
<td bgcolor="#FFFFFF">
<input name="hotel_name_0" id="hotel_name_0" type="text" value="Hotel Creek" class="select_text" onfocus="disable_ctrlV()" onkeypress="return Nothingonly(event)">
</td>
Code:
public static boolean fncVerifyTextInColumn(WebElement gridObjWebElement,
String stringToValidate, int columnNumber,String colName) {
boolean flagTextinColumn=false;
ArrayList<WebElement> objRows;
ArrayList<WebElement> objCols;
ArrayList<WebElement> childElement;
objRows=(ArrayList<WebElement>)gridObjWebElement.findElements(By.tagName("tr"));
objCols=(ArrayList<WebElement>)objRows.get(0).findElements(By.tagName("td"));
if(objCols.get(columnNumber).getText().equalsIgnoreCase(colName)){
for(int index=1;index<objRows.size();index++){
objCols=(ArrayList<WebElement>)objRows.get(index).findElements(By.tagName("td"));
childElement=(ArrayList<WebElement>)objCols.get(columnNumber).findElements(By.xpath("//input"));
System.out.println(childElement.get(0).getAttribute("value"));
if(stringToValidate.trim().equalsIgnoreCase(childElement.get(0).getAttribute("value").trim())){
flagTextinColumn=true;
}
}
}
return flagTextinColumn;
}
Method Calling:
fncVerifyTextInColumn(objGrid,hotels,1,"Hotel Name");
I would use cssSelector [id^='hotel_name_'] to locate the element and then getAttribute() retrieve the attribute value
By css = By.cssSelector("[id^='hotel_name_']");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(css));
System.out.println(myDynamicElement.getAttribute("value"));
Notice the regex search of cssSelector here. With ^ I am skipping any dynamic number. Hoping that's the only element with hotel_name_someNumber on the page.
Just do
String attValue = driver.findElement(byAnyMethod).getAttribute("AttributeName");
Hope it helps
I think what you are looking for is this. (I'm assuming you know how to code, you just need a general direction so I'm going to leave out specific code.)
First, find the table the td is in. You might need to use an xPath for this or you'll need to assign an ID to the table so you can locate it.
Then once you have the table, do a FindElements to get the list of TRs under it.
Once you have the TRs, you can loop through them, grab the TDs under that and grab the TD at the index that has the INPUT you want the value of, get the INPUT and then get it's value.
Yep, lots of steps.
A shortcut may be to class all of the inputs you want the value for with a unique class and do a FindElements By className and loop through that list.
I would like to use selenium to select a value in the Month list box for birthday on google page: https://accounts.google.com/SignUp
When I view page code, the code for the list box looks like:
<select id="BirthMonth" name="BirthMonth">
<option value="">Month</option>
<option value="01" >January</option>
<option value="02" >February</option>
......
<option value="12" >December</option>
</select>
However, when I use Selenium driver.findElements(), I cannot find this select and its option elements. It looks like every list box on this page (as well as gender one) cannot be accessed.
Can anyone give some suggestion how Selenium can access to these elements? Thanks
The code is as follows:
driver.get("https://accounts.google.com/SignUp");
List<WebElement> inputElements = driver.findElements(By.xpath("//select[#name]"));
for(WebElement input: inputElements){
if(input.getTagName().equals("select")){
Select selectinput = new Select(input);
List<WebElement> selects = selectinput.getOptions();
}
}
I did not get the select element I want.
EDIT:
I also try to use Select select1 = new Select(driver.findElement(By.tagName("select"))) but still cannot find this BirthMonth list box. It is wired. There is only one listbox which is inside Javascritpt that can be accessed.
Here's a suggestion for how access these elements in Selenium, with a Java example.
It gets a little messy with CSS Selectors (which I generally prefer) because this month field has some fancy widgets on it to help hide your choices for security reasons. So here we go with XPath as our selector mechanism.
Take notice I broke it down - 1st by selecting the month, and 2nd by selecting the month itself. Hope that helps.
public class Google Month Example {
public static void main(String[] args) throws Exception {
// Just picked Firefox for this example
FirefoxDriver driver;
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(7, TimeUnit.SECONDS);
// Head to URL
driver.get("https://accounts.google.com/SignUp");
// Get the first click on the month field to generate the listbox pop-up
driver.findElement(By.xpath(".//*[#id='BirthMonth']/div")).click();
// This is ":a" because each item in this month list is assigned a hex value starting at an index of zero
driver.findElement(By.xpath(".//*[#id=':a']/div")).click();
// Check to see if November got selected
if (!driver.findElement(By.xpath(".//*[#id='BirthMonth']/div[1]")).getText().equals("November")) {
driver.close();
throw new RuntimeException("assertText 'November' failed");
}
// Close browser window
driver.quit();
}
}
Update: I realized you wanted to pass in the Month as an argument.
So swap out from the example above:
driver.findElement(By.xpath(".//*[#id=':a']/div")).click();
for the below code:
String month = "November";
driver.findElement(By
.xpath("//div[#class='goog-menuitem']/div[.='" + month + "']")).click();
Second Update:
So at one point you saw the HTML as:
<select id="BirthMonth" name="BirthMonth">
<option value="">Month</option>
<option value="01" >January</option>
<option value="02" >February</option>
......
<option value="12" >December</option>
</select>
But as I look at it in Chrome Dev Tools right now (pressing F12) after clicking on the Month field I see multiple small structure changes (posted what I see in the of the Gist link).Examples include select now becoming span and value="01" now shown as id=":0" (Why the counting starts at zero and not 1). Hope that explains some of why my example is different.
<select>
<option value=''>-- Select an Option --</option>
#foreach ($options as $option)
<option value='{{ $option->value }}'>{{ $option->name }}</option>
#endforeach
</select>
Select the first dynamic option
$option = $I->grabTextFrom('select option:nth-child(2)');
$I->selectOption("select", $option);
$I->click("Submit");
I've run into the same issue quite often when starting out with Codeception. Using the recommended answer, I created a helper function in my AcceptanceTester class to make this a little easier.
public function selectFromDropdown($selector, $n)
{
$option = $this->grabTextFrom($selector . ' option:nth-child(' . $n . ')');
$this->selectOption($selector, $option);
}
Where $n is the position in the option list.
Then all you have to do is call it like this:
$I->selectFromDropdown('select', 1);
This has been working for me on pages that have several select's that load their option list based on the selected option of the previous select.
sorry i do not have submit button, in my case i have to select the dropdown element and somehow need to tell the codeception to finish the selection.At the moment i can select but that select is not visible as i suppose the selection is not finished somehow.Below is my code to select the element.
$I->selectOption('//*[#class="ng-scope" and #ng-controller="dataIsland"]/*[local- name()="select"]','partlycloudy');
I have a select control on my site. I am using page objects to interact with the page. If I do (with the first 2 lines under my class and the selectByValue in my method)
#FindBy(id="foo")
private Select foo;
foo.selectByValue("myValue");
It fails with a null pointer. I also tried without the #FindBy.
Now if I do this in my method it all works fine and selects the correct item
Select foo = new Select(sDriver.findElement(By.id("foo")));
foo.selectByValue("myValue");
Here is the actual web snippet for that control (edited to protect the innocent)
<select id="foo" name="service_name">
<option selected="selected" value="one">one</option>
<option value="two">two</option>
<option value="three">three</option>
</select>
Let me say that I have a work around for my issue but I don't get why the "normal" path is not working.
Thats because the Select class has this constructor:
Select(WebElement element)
See the Javadoc
So if you do something like this:
#FindBy(id="foo")
private WebElement wannabeSelect;
Select realSelect = new Select(wannabeSelect);
realSelect.selectByValue("myValue");
It should work.
BTW, I am using the same approach as you in the "workaround" because I dont wanna cast new WebElement object when I need Select object. But anyways, the
sDriver.findElement(By.id("foo"));
returns WebElement, so thats why its working. You can also do this:
WebElement wannabeSelect = sDriver.findElement(By.id("foo"));
Select foo = new Select(wannabeSelect);
There are two ways to select the option value:
One:
// Denotes option value - technical name
select.selectByValue(fieldValue);
Two:
// Denotes option text that is actually visible to be selected
select.selectByVisibleText(fieldValue);
Other way I achieved this is by using below method for all my onchange dropdownselection boxes. Pass id and selection and it works
public void onchangedropdownselection(String object, String value) {
WebElement obj = driver.findElement(By.id(object));
obj.sendKeys(value);
obj.sendKeys(Keys.UP);
obj.sendKeys(Keys.DOWN);
}
By doing up and down we are initialzing the script onchange.......