Using Selenium WebDriver to retrieve the value of an HTML input - java

In the HTML of a web application there is the following code:
<input type="text" name="prettyTime" id="prettyTime" class="ui-state-disabled prettyTime" readonly="readonly">
A string displaying the time is actually shown on the page.
In Selenium WebDriver, I have a WebElement object referring to the <input> using:
WebElement timeStamp = waitForElement(By.id("prettyTime"));
I want to get the value of the WebElement, or, in other words, what is printed on the page. I tried all the WebElement getters and nothing has been retrieving the actual value that the user sees.

Try element.getAttribute("value")
The text property is for text within the tags of an element. For input elements, the displayed text is not wrapped by the <input> tag, instead it's inside the value attribute.
Note: Case matters. If you specify "Value", you'll get a 'null' value back. This is true for C# at least.

You can do it like this:
webelement time = driver.findElement(By.id("input_name")).getAttribute("value");
This will give you the time displaying on the webpage.

For Python bindings it will be:
element.get_attribute('value')

With Selenium 2, I usually write it like this:
WebElement element = driver.findElement(By.id("input_name"));
String elementval = element.getAttribute("value");
Or
String elementval = driver.findElement(By.id("input_name")).getAttribute("value");

As was mentioned before, you could do something like this:
public String getVal(WebElement webElement) {
JavascriptExecutor e = (JavascriptExecutor) driver;
return (String) e.executeScript(String.format("return $('#%s').val();", webElement.getAttribute("id")));
}
But as you can see, your element must have an id attribute, and also, jQuery on your page.

Following ragzzy's answer, I use
public static string Value(this IWebElement element,
IJavaScriptExecutor javaScriptExecutor)
{
try
{
string value = javaScriptExecutor.ExecuteScript("return arguments[0].value", element) as string;
return value;
}
catch (Exception)
{
return null;
}
}
It works quite well and does not alter the DOM.

Use
element.GetAttribute("value");
Even though if you don't see the "value" attribute in the HTML DOM, you will get the field value displayed in the GUI.

If the input value gets populated by a script that has some latency involved (e.g. AJAX call) then you need to wait until the input has been populated.
E.g.
var w = new WebDriverWait(WebBrowser, TimeSpan.FromSeconds(10));
w.Until((d) => {
// Wait until the input has a value...
var elements = d.FindElements(By.Name(name));
var ele = elements.SingleOrDefault();
if (ele != null)
{
// Found a single element
if (ele.GetAttribute("value") != "")
{
// We have a value now
return true;
}
}
return false;
});
var e = WebBrowser.Current.FindElement(By.Name(name));
if (e.GetAttribute("value") != value)
{
Assert.Fail("Result contains a field named '{0}', but its value is '{1}', not '{2}' as expected", name, e.GetAttribute("value"), value);
}

Java users:
To get what is printed on the page, we need to use the getText() method.
getText() method
The getText() method returns the visible inner text of a web element.
getAttribute() method
On the other hand, the getAttribute() method fetches the value of the attribute we wish to retrieve.
Example:
<input name="Title" type="text" value="LambdaTest" /> Welcome to LambdaTest </input>
getText()
driver.findElement(By.name("Title")).getText();
Output of above code => Welcome to LambdaTest
getAttribute():
driver.findElement(By.name("Title")).getAttribute("value");
Output of above code => LambdaTest
driver.findElement(By.name("Title")).getAttribute("type");
Output of above code => text
Source: Difference between getText() And getAttribute() in Selenium WebDriver

This is kind of hacky, but it works.
I used JavascriptExecutor and added a div to the HTML, and changed the text in the div to $('#prettyTime').val()
I then used Selenium to retrieve the div and grab its value. After testing the correctness of the value, I removed the div that was just created.

Related

getAttribute("value") returns 0

I want to click on an element which is from a list. I am using getAttribute("value") to get the text, but it returns 0, hence it is not clicking the element. Please help.
DOM structure
<ol class ="class1">
<li value="foo1" class="class2">
<li value="foo2" class="class2">
</ol>
Xpath:
#FindBy(xpath = "//ol[#class='class1']/li")
List<WebElement> tagList;
I have tried getText() but it returns the text along with unknown character, as the element has icons along with the text.
This is my code
public void selectTag() {
addReservationBtn.click();
tags.click();
for(WebElement li : tagList) {
// System.out.println(li.getAttribute("value"));
if (li.getAttribute("value").equalsIgnoreCase("foo2")) {
li.click();
break;
}
}
As text contains unknown characters so
li.getAttribute("value").equalsIgnoreCase("foo2")
will not work as both string not equal.
You can try contains like
li.getAttribute("value").contains("foo2")
I think reason for your problem may be
1. Wrong xpath or 2. Waits
// get second <li> using correct xpath
#FindBy(xpath = "//ol[#class='class1']/li[2]")
List<WebElement> tagList;
public void selectTag() {
addReservationBtn.click();
tags.click();
// waitforliTextToAppearAfterClick();
if (tagList.get(1).getAttribute("value").trim().equalsIgnoreCase("foo2")) {
tagList.get(1).click();
}
You are using #FindBy which only returns the first element found by the given locator. Use #FindBys to get all the elements found by the given locator.
As the previous answer was wrong I've striked it but kept it for
the clarification of the comments.
You can directly get the second element without using the for loop by
#FindBy(xpath = "//ol[#class='class1']/li[#class='class2']")
The getAttribute() method returns null if there are no attribute found and returns empty when there is an attribute but it doesn't contain any value.

"Invalid Selector Used for Locator " error for xpath locator while using findelements

xpath of Job.JobTitles.Add.JobTitleValidMessage
is:
//input[#id='jobTitle_jobTitle']/following-sibling::span
It gives NullPointerException on 1st line of code. How to solve this?
List<WebElement> job_valid_message = TestBase.findElements("Job.JobTitles.Add.JobTitleValidMessage");
if (job_valid_message.size()==1) {
return !job_valid_message.get(0).isDisplayed();
} else
return true;
HTML source of element
<li> <label for="jobTitle_jobTitle">Job Title <em>*</em></label> <input type="text" name="jobTitle[jobTitle]" maxlength="100" id="jobTitle_jobTitle" class="validation-error"><span for="jobTitle_jobTitle" generated="true" class="validation-error">Required</span> </li>
The correct code should be.
List<WebElement> job_valid_message = TestBase.findElements(By.xpath("//input[#id='jobTitle_jobTitle']/following-sibling::span");
if (job_valid_message.size()>0) {
return true; //message is displayed
} else
return false; //message not displayed
Alternately you can use css span[for='jobTitle_jobTitle' ][class='validation-error'] if you want to access the span directly.
With the assumption that TestBase is a driver controlling some browser, I would use
List<WebElement> job_valid_message = TestBase.findElements(By.cssSelector('span.validation-error');
the class TestBase seems to be your framework class from where you are calling findElements method. Since there is not By definition in the parameter, i can suggest you to check if the parameter is string or By. If it is overloaded with string, what is the default locator definition (like cssSelector, xpath, etc).

How to extract the value of an input field through getAttribute() or executeScript() method?

There is input field which id is condition and getText() and getAttribute() are not working
driver.findElement(By.id("condition")).getText() //is not working..
So I tried in the console
document.getElementById("condition").value //return the value.
So I tried
JavascriptExecutor jse = (JavascriptExecutor) driver;
System.out.println(jse.executeScript("document.getElementById(condition).value");
String value = jse.executeScript("document.getElementById(condition).value").toString();
AssertVerify(value, "15");
Getting following error:
org.openqa.selenium.WebDriverException: JavaScript error (WARNING: The server did not provide any stacktrace information)
How to get use the javascript to get the value and assign to other variable.
Your code trial was near perfect. You need to pass the id attribute of the element within single quotes i.e. '...' as follows:
String value = ((JavascriptExecutor)driver).executeScript("document.getElementById('condition').value").toString();
Update
As you are still unable to retrieve the value through executeScript() method, you need to induce WebDriverWait for the desired element to be clickable and you can use the following solution:
Use getAttribute() to retrieve the text:
String myText = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.id("condition"))).getAttribute("value");
Use executeScript to retrieve the text:
WebElement myElem = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.id("condition")));
String value = ((JavascriptExecutor)driver).executeScript("document.getElementById('condition').value").toString();

How can I loop through list of WebElements and select one WebElement with a condition?

I am using Selenium WebDriver with Java. I am trying to create a method that loops through a list of WebElements to return the first WebElement that contains the text "Ooga Booga", or return null if there are no elements in the list that contains this text.
public class myClass {
private static WebElement element = null;
private static List<WebElement> elements = null;
public static WebElement returnOneElement (WebDriver driver){
elements = driver.findElements(By.cssSelector("someSelector"));
for (WebElement element : elements){
String myText = element.findElement(By.cssSelector("classC")).getText();
if (myText.contains("Ooga Booga")) {
return element;
}
}
return null;
}
This all works fine until I run into an element that does not have this attribute:
String myText = element.findElement(By.cssSelector("classC")).getText();
How can I continue to loop through my List while ignoring any elements that do not have "someDiv" inside of it?
<div class="someSelector">
<div class="classA">
<div class="classB">
</div>
<div class="someSelector">
<div class="classA">
<div class="classB">
<div class="classC">
</div>
I need to search for text inside div "classC".
Use findElement-S method as shown below.
for (WebElement element : elements) {
List<WebElement> mightHaveSomeDiv = element.findElements(By.cssSelector("someDiv"));
if (mightHaveSomeDiv.size() > 0) {
//Can iterate the list if you expect more than one div of type someDiv.
String myText = mightHaveSomeDiv.get(0).getText();
if (myText.contains("Ooga Booga")) {
return element;
}
}
}
Btw, I would recommend to try and break away from static methods like this. It will make your life a living hell later on because of it being static. Everything using it starts to want static.
Anyway, lets break it down. This cssSelector will allow you to grab the child divs by the tagname instead of classname.
By.cssSelector(".someSelector div")
Now that we have a list of WebElement, which are all div elements, lets just look for the text in the div. No need to worry about class attribute
public static WebElement returnOneElement (WebDriver driver){
elements = driver.findElements(By.cssSelector(".someSelector div"));
for (WebElement element : elements){
if(element.getText().contains("Ooga Booga")) {
return element;
}
}
return null;
}
Alternatively, you may find the target directly with xpath locators such as
//div[#class='someSelector']//div[contains(.,'Ooga Booga')]
Be warned though, if you have multiple div that contains the text "Ooga Booga", you will get multiple WebElements, and what you do with it next may not be what you expect. Actually, this warning should also apply to the loop. It will break out of your first div element that contains "Ooga Booga". You will have to adjust the logic if you want exact match.
Here is your answer.. Firstly Declare a parent web locator
WebElement element1 = driver.findElement(By.id("##abc##"));
Now in case you want to perform any action or anything within the locator defined above then you can do it as follows:
element1.findElement(By.xpath(" . //##yourFurtherLocABC")).click();
element1.findElement(By.xpath(" . //##yourFurtherLocXYZ")).getText();
Important = Do remember to keep a . at the beginning of any child elements!

How to verify an attribute is present in an element using Selenium WebDriver?

I have many radio buttons on my screen. When a radio button is selected, it has an attribute of checked. When the radio button is not selected, the checked attribute is not present. I would like to create a method that would pass if the element is not present.
I am using selenium webdriver and java. I know I can retrieve attributes by using getSingleElement(XXX).getAttribute(XXX). I'm just not sure how to verify that an attribute does not exist, and for the test to pass when it doesn't exist (fail if it does exist).
When the radio button is checked
<input id="ctl00_cphMainContent_ctl00_iq1_response_0" type="radio" name="ctl00$cphMainContent$ctl00$iq1$response" value="1" checked="checked">
When the radio button is not checked
<input id="ctl00_cphMainContent_ctl00_iq1_response_0" type="radio" name="ctl00$cphMainContent$ctl00$iq1$response" value="1">
I want the test to pass when the checked attribute is not present
You can create a method to handle it properly. Note this following is in C#/Java mixed style, you need to tweak a bit to compile.
private boolean isAttribtuePresent(WebElement element, String attribute) {
Boolean result = false;
try {
String value = element.getAttribute(attribute);
if (value != null){
result = true;
}
} catch (Exception e) {}
return result;
}
How to use it:
WebElement input = driver.findElement(By.cssSelector("input[name*='response']"));
Boolean checked = isAttribtuePresent(input, "checked");
// do your assertion here
Unfortunately the accepted answer is not valid in the case reported.
For some reason for Cr and FF non-existing attributes return empty string rather than null.
Issue linked: https://github.com/SeleniumHQ/selenium/issues/2525
Look here:
getAttribute(java.lang.String name)
Returns:
The attribute's current value or null if the value is not set.
Use whatever test framework you're using to assert that the value is null
Assert.IsNull(getSingleElement(XXX).getAttribute("checked"));
Checkboxes can tricky sometimes, because the attribute checked may not be followed by an attribute value.
If you're only concerned with the presence of the attribute, a simple check would look like this:
boolean hasAttr_css = driver.findElementsByCssSelector("#input_id[checked]").isEmpty();
For asserting radio button is selected
Assert.assertTrue(element.isSelected());
For asserting radio button is not selected
Assert.assertFalse(element.isSelected());
For asserting an attribute is present in element
Assert.assertEquals(element.getAttribute(attributeName), expectedAttributeValue);
try {
if (webdriver.findElement(By.identificationMethod(value)).getAttribute(value) != null) {
passed = false;
}
} catch (Exception e) {
passed = true;
}
Was the sort of solution I used when I needed to check for element presence, however it must be noted that NullPointer errors were not caught by the NoSuchElement exception.
as none of the answers helped me I would like to share the very simple solution I went with in the end:
static ExpectedCondition<Boolean> isAttributePresent(WebElement element, String attrName) {
JavascriptExecutor executor = (JavascriptExecutor) getDriver();
String script = "return arguments[0].getAttributeNames();";
var attributes = executor.executeScript(script, element);
return input -> ((ArrayList) attributes).contains(attrName);
}
I hope it helps someone. I used it for wait.until(condition) scheme

Categories