getAttribute("value") returns 0 - java

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.

Related

How to take value by attribute using Jsoup Java?

I am taking the HTML code from website and then I would like to take the value "31 983" from attribute using Jsoup:
<span class="counter nowrap">31 983</span>
The code below is almost ready, but do not take this value. Could you please help me?:
public class TestWebscrapper {
private static WebDriver driver;
#BeforeClass
public static void before() {
System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
driver = new ChromeDriver();
}
#Test
public void typeAllegroUserCodeIntoAllegroPageToAuthenticate() {
String urlToAuthencicateToTypeUserCode="https://www.test.pl/";
driver.get(urlToAuthencicateToTypeUserCode);
Document doc = Jsoup.parse(driver.getPageSource());
//how to take below value:
System.out.println(doc.attr("counter nowrap"));
}
#AfterClass
public static void after() {
driver.quit();
}
}
I was trying to use doc.attr, but does not help.
Jsoup uses CSS selectors to find elements in HTML source. To achieve what you want use:
// select the first element containing given classes
Element element = doc.select(".counter.nowrap").first();
// get the text from this element
System.out.println(element.text());
I'm afraid in your case there may be many elements containing classes counter and nowrap so you may have to iterate over them or try different selector to address directly the one you want. It's hard to tell without webpage URL.
Answering you original question, how to select by attribute:
Element element = doc.select("span[class=counter nowrap]").first();
or just:
Element element = doc.select("[class=counter nowrap]").first();

"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).

Selenium Webdriver - Java - How to click checkbox based on product

I would like to click checkbox based on link text. There are several checkbox in the page so using the link text I wanted to find value of the checkbox so that I can click on the checkbox
Note # All values are dynamically generated
Can you please help correct the code to include this logic. Thanks
driver.get(new URI(driver.getCurrentUrl()).resolve("/admin/lms/tag").toString());
String tag_name = sheet1.getRow(j).getCell(0).getStringCellValue();
driver.findElement(By.linkText(tag_name)).click();
WaituntilElementpresent.isExist();
String tag_value = sheet1.getRow(j).getCell(1).getStringCellValue();
driver.findElement(By.cssSelector("a[href*='"+tag_value+"']")).click();
WaituntilElementpresent.isExist();
String product = sheet1.getRow(j).getCell(2).getStringCellValue();
WaituntilElementpresent.isExist();
driver.findElement(By.cssSelector("input[name='products[]'][value='11']")).click();
https://i.stack.imgur.com/mOBY2.png
You could use an xpath like this:
//tr[.//*[text()='OPIOIDMORTEPID']]//input
this means to locate the td that has this exact text and find the input from it.
If you want to use partial text then:
//tr[.//*[contains(text(), 'MORTEPID')]]//input
You can do it with the following strategy:
find the link by using the link text
get the parent tr element
from there, find the input element of the checkbox
click on the checkbox
This can be done as follows:
WebElement link = driver.findElement(By.linkText("OPIOIDMORTEPID"));
WebElement trElement = link.findElement(By.xpath("../.."));
WebElement checkboxElement = trElement.findElement(By.tagName("input"));
checkboxElement.click();
Check this out:
Get a list of checkbox WebElements that have a common locator i.e. a common class name or tag name (this WebElement would have to have the text or be a parent of the element that has the text).
List<WebElement> checkBoxElements = webDriver.findElements(By.cssSelector("checkbox"));
Iterate through the list and check if the WebElement has the text you are looking for. If it does, click it!
for (WebElement e : checkBoxElements) {
if (e.getText().contains("Something dynamic")) {
e.click();
}
}
Be happy that this works.
I would write this section as a function so that it's reusable.
public static void selectByProductName(String value)
{
driver.findElement(By.xpath("//tr[//a[text()='" + value + "']]/td/input")).click();
}
and then call it like
selectByProductName("OPIOIDMORTEID");

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!

Using Selenium WebDriver to retrieve the value of an HTML input

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.

Categories