I'm running Selenium on a site that changes the value of a disabled input text box using jquery. Looking at the HTML, the value of the input box continues to say "Not Available" even though the value is obviously changed.
I can get the current value using Firebug with
$("#inputid").val()
but I get the value "Not Available when I've used my selenium code:
driver.findElement(By.id("inputid")).getAttribute("value");
Any suggestions on how to get this value in Selenium? I want to avoid trying to use something like JavascriptExecutor but if that's the best solution it would be good to know.
I don't have access to the jQuery code so I can't help you there. Sorry :-/
If the value is changed by jQuery due to some DOM events, chances are your Selenium test is going to check for the new value too fast. You can get the value after it changes away from "Not Available" with something like this:
WebDriverWait wait = new WebDriverWait(driver,10);
String value = wait.until(new ExpectedCondition<String>() {
public String apply(WebDriver driver) {
String value = driver.findElement(By.id("inputid")).getAttribute("value");
if value.equals("Not Available")
return null;
return value;
}
});
(Disclaimer: It's been ages since I've written Java code so I may have goofed in the code above.) The wait.until call will run the apply method until it returns something else than null. It will wait for at most 10 seconds. The value returned by wait.until will be the value that was last returned by the apply that terminated the end. In other words, it will return the new value of the element.
You say
Looking at the HTML, the value of the input box continues to say "Not Available" even though the value is obviously changed.
Yes, that's a quirk of the DOM. When you change the value of the input field, the value attribute on the element that represent the input field does not change. What changes is the value property on the element. This is why you have to do $("#inputid").val(), not $("#inputid").attr('value').
Related
I want to check several attributes of element (for example, is element displayed and that it's content is not empty) and I also want to know is there any simple way to this, because now I have code like this:
result= adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS).isDisplayed()
&& !(adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS).getAttribute("innerText").equals(""));
And I want something like this (this is obviously not working code):
result= adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS)
.isDisplayed() &&
.getAttribute("innerText").equals(""));
Is there any possibility to simplify my code?
Make a WebElement variable and reuse, no need to find the element again:
WebElement elm = adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS);
result = elm.isDisplayed() && (!elm.getText().equals(""));
Note that I've also replaced the innerText with getText() method call.
I have just noticed that Appium & Selenium is taking at least 2 minutes to find element when element is not there.
I want to reduce that time for search.
Code is :
if(!driver.findElements(By.id(AppConstants.notificationcount)).isEmpty())
{
// DO SOMETHING
}
else
{
System.out.println("No Element available");
}
Now most of time my element not available so I want appium to check it and redirect quickly to ELSE part , but it is taking long time , Any solution?
Have you checked your implicit wait time?
It is 0 by default, but maybe you are setting it somewhere to a value > 2 mins:
driver.manage().timeouts().implicitlyWait(timeInSeconds, TimeUnit.SECONDS);
If your implicit wait time is bigger than 0 and you are searching for an element with
driver.findElements(...);
but your Element does NOT exist, then Selenium will wait the WHOLE specified time!
Selenium only does not wait, when at least one element is found. In this case it will search the page once and return immediately with the list of elements found.
So findElements() is without restriction great to check the existence of an element, but only good for checking non-existence when you specified a very low implicit wait time (or the default 0).
If you absolutely need an implicit wait time > 0 for whatever reason, then you can create your own method that handles this like in this solution.
In your case you could set implicit wait time to 0 right before your posted code:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
// then follows your code:
if(!driver.findElements(By.id(AppConstants.notificationcount)).isEmpty())
{
// DO SOMETHING
}
else
{
System.out.println("No Element available");
}
If you need an implicit wait time other than 0 elsewhere then just set it back to the original value after your piece of code.
The quicker way to check is store the elements in a list and then check if it is empty
List<WebElement> elements = driver.findElements(By.id("AppConstants.notificationcount"));
if (elements.isEmpty()) {
System.out.println("No Element available");
}else{
elements.get(0).click();//if present click the element
}
Hope this helps you.
I'm using HtmlUnit to scrape data and I'm getting used to the syntax of XPath.
However I've run into a problem.
I have an element that I need to pull that varies between pages, sometimes it is a "span" element and sometimes it is an "a" element (a link). The reason being simply sometimes the item I am scraping has a link and sometimes it is just plain text (to state the obvious).
What is the same however is an attribute called "data-reactid", which always has a set value of, let's just say 99.
I've been reading and messing around, and have been trying things like this:
HtmlElement element = (HtmlElement) myPage.getFirstByXPath("//#data-reactid='99'");
System.out.println(element.getTextContent());
I am getting the following error:
java.lang.ClassCastException: java.lang.Boolean cannot be cast to com.gargoylesoftware.htmlunit.html.HtmlElement
Why getFirstByXPath() is returning a boolean is beyond me.
So my question is, how can I access an element by a specified attribute and value, when I do not know what type the element will be?
Thanks!
It's giving you a boolean because your XPath is asking for a boolean. Your XPath,
//#data-reactid='99'
is asking the question "does there exist a data-reactid attribute anywhere in my document with a value of 99?"
What you want is a predicate -- that is, "select elements where this logical condition is true". For all elements (we'll use a * wildcard since we don't know the name) that have a #data-reactid of 99:
//*[#data-reactid = '99']
As of now I am getting the count of the number of matching results using listChanges.size() . How do I directly get the count without loading getChanges in the list?
By getChanges = By.xpath("//td[contains(#class,'blob-code blob-code-addition') or contains(#class,'blob-code blob-code-deletion')]");
List<WebElement> listChanges = driver.findElements(getChanges);
I found this(Count function in XPath) and I tried the below which does not work!
Integer getCount = By.xpath(count("//td[contains(#class,'blob-code blob-code-addition') or contains(#class,'blob-code blob-code-deletion')]"));
Looks like I have to do something like this.
Integer getCount = By.xpath("count(//td[contains(#class,'blob-code blob-code-addition') or contains(#class,'blob-code blob-code-deletion')])");
But the right hand side returns an object of type By
As alex says, size() is the way to go. However I do have another suggestion for you.
Even though the proper way to find the element counts is to use WebDriver api with findElements() as per my knowledge. Another way is to execute javascript by using executeScript() and with proper script. I am not sure if javascript and xpath can be mixed together to accomplish this since xpath execution through javascript is not multi-browser right now. See this. However, I do think using cssSelector with javascript can make it lot easier to accomplish. See the following code :
String cssQuery = ".blob-code-addition, .blob-code-deletion";
String script = "return document.querySelectorAll('" + cssQuery + "').length;";
Object count = ((JavascriptExecutor)driver).executeScript(script);
System.out.println(count);
Print
26
You cannot get the count using XPath, because an xpath expression in selenium has to correspond to an actual element on a page.
The way you are doing it via findElements() + size() is how you have to count elements using the selenium webdriver.
I'm using the Play Framework and have a question about templates:
I want to use list as a for loop with from and to variables:
#{list pages:results.startPage..results.endPage, as:'page'}
${page}
#{/list}
Both results.startPage and results.endPage have valid values. I don't
receive an error message, however no output is displayed. What am I
doing wrong?
Thanks
EDIT: After spending the time writing a big answer, there is a bug in your code!
In your #list tag, you should have items, and not pages. Your code should read.
#{list items:results.startPage..results.endPage, as:'page'}
${page}
#{/list}
For those interested in how the Groovy Range variable works, below is a description, rather than me delete the long answer!
I think you are using the range method in the wrong way. The Groovy Range construct for the for loop, allows you to loop from one value to another value. This is generally a integer or a string, and not a List.
So, if you do the following, it will print 0 to 10
#{list items:0..10, as:'i'}
${i}
#{/list}
However, the values can be set in your controller. So if you want to use a start and end variable set in your controller (assume they are set to 0 and 10), you can do the following.
#{list items:start..end, as:'i'}
${i}
#{/list}
My controller to test that construct is as follows, and it works fine.
public static void index() {
int start = 0;
int end = 10;
render(start, end);
}
This will print the same 0 to 10. Even if I send these variables through encapsulated in a class, it still works fine.
Are you sure that startPage and endPage are integer values?