I'm trying to create a explicit wait method in my framework to handle the user's input. The method is supposed to handle all types of search: id, xpath, and css.
However, When I tried testing this method, the error is returning an odd error
Method of explicit wait
public static void isDisplaying(String variable){
wait = new WebDriverWait(driver,3);
System.out.println("Looking for: " + variable);
if (driver.findElement(By.id(variable)).isDisplayed()){
System.out.println("Found variable via id");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(variable)));
} else if (driver.findElement(By.xpath(variable)).isDisplayed()) {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(variable)));
System.out.println("Found variable via xpath");
} else if (driver.findElement(By.cssSelector(variable)).isDisplayed()){
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(variable)));
System.out.println("Found variable via css");
} else {
System.out.println(variable +" is not displayed.");
}
}
Error that I'm receiving:
org.openqa.selenium.NoSuchElementException: Unable to locate element: #\/\/div\[\#id\=\'slideOut\-nav\'\]\/ul\/li\[2\]\/a
I have no clue why it is returning the value with all those back and forward slashes. My guess is that the application failed as soon as it tried searching the xpath string using id. But shouldn't it be moving to the next else if statement? How should I handle such issue, if this is indeed the issue?
When I simply locate the element and clicking, it works fine and returns the correct path:
//div[#id='slideOut-nav']/ul/li[2]/a
I've been stuck on this issue for a loooooong time so any help would greatly be appreciated!!
The call to driver.findElement(By.id(variable)) is bound to throw exceptions immediately if the element is not found.
Try replacing calls to driver.findElement() with driver.findElements() because this call does not throw exceptions but it returns an empty list of webelements when the call fails.
If you are really looking at building a generic method, then you should first parse the variable contents to see if it represents xPath or css and finally fall back to using id (or) name.
You can take a look at this implementation for reference.
I am not sure what your function is intended to do. You are checking to see if the element is displayed and if it is then wait for it to be displayed. If an element is displayed, it's already visible.
Instead of passing a String around, pass a locator, By. Passing a locator reduces having to check all the different locator types.
I've added a return type of boolean to your function so you can reuse it. It waits for up to 3 seconds for the element to be visible. If it doesn't timeout, the element is visible and it returns true. If it does time out, the element is not visible and returns false. You can reduce your code to the below.
public static boolean isDisplaying(By locator)
{
try
{
new WebDriverWait(driver, 3).until(ExpectedConditions.visibilityOfElementLocated(locator));
return true;
}
catch (TimeoutException e)
{
return false;
}
}
You would call it like
System.out.println(isDisplaying(By.xpath("//div[#id='slideOut-nav']/ul/li[2]/a")));
or
System.out.println(isDisplaying(By.id("someId")));
public void waitUntilElementclickable(WebElement element){
//Waits Until Element is Clickable on screen
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(element));
}
Related
I need to check if an element is present on page in Java Selenium. Unfortunately all of the explanations on searches are doing it with FindElements(By) but I have a structure of passing the WebElement directly to the method as my elements are already sent by PageFactory.
So I have a structure as follows:
public static void verifyElementPresentStatus(WebElement targetElement, String elementName) {
Boolean elementPresent = MISSING PART
StepLogger.subVerification(elementName + " should be present");
Assert.assertTrue(
elementPresent,
ValidationHelper.getPresentValidation(elementName)
);
}
and call the method like
ExpectationHelper.verifyElementPresentStatus(
Pages.HomePage().homeHeader,
Pages.HomePageConstants().pageHeaderText
);
Anyone knows a way to do that?
You cannot write a method that accepts a WebElement as an argument and check whether it exists or not in all cases. This is because the only case where you can have a reference to a WebElement object which doesn't exist is if it was previously existed and then later removed from the DOM (a "stale element"). In order to determine if an element exists or not for the first time, you can only do that by accepting a By argument instead if a WebElement. This way you can use findElements and check that count > 0.
According to the documentation of WebElement interface, all its method calls
will do a freshness check to ensure that the element
reference is still valid. This essentially determines whether or not
the element is still attached to the DOM. If this test fails, then an
StaleElementReferenceException is thrown, and all future calls to this
instance will fail.
Since you receive a webElement without any validation, consider doing a neutral method call (without any side effects) to check element for StaleElementReferenceException. For example, you can call getSize() method. Your method logic should look then something like this.
public static void verifyElementPresentStatus(WebElement targetElement, String elementName) {
Boolean elementPresent = true;
try {
elementPresent = targetElement.getSize();
} catch (StaleElementReferenceException e) {
elementPresent = false;
}
StepLogger.subVerification(elementName + " should be present");
Assert.assertTrue(elementPresent, ValidationHelper.getPresentValidation(elementName));
}
Need to assert that there is no such element in the webpage,
When tried with fieldValueBox.isDisplayed(); instead of "false" its throwing "NoSuchElementFound" exception.
Right now i was using 'try catch' and making decision in 'catch'
If the element is not on the page, then you will get 'NoSuchElementFound' exception. You can try checking that the number of elements with the locator is zero:
private boolean elementNotOnPage(){
boolean elementIsNotOnPage = false;
List<WebElement> element = driver.findElements(yourLocator);
if(element.size() == 0){
elementIsNotOnPage = true;
}
return elementIsNotOnPage;
}
The isDisplayed() method returns a boolean based on an existing element. Meaning, if you want to check if an element, which exists, is displayed on the webpage or not (as in, not hidden or anything), this method will work properly.
In your case, its possible that the fieldValueBox does not exist. Because of this, the isDisplayed() method is going to try to return a boolean on a non-existing object.
A try catch is going to help you here, so that's one correct way. There are a few other ways, check:
WebDriver: check if an element exists?
How do I verify that an element does not exist in Selenium 2
As you are trying to assert that there is no such element in the webpage you have :
fieldValueBox.isDisplayed();
Now if you look into the Java Docs of isDisplayed() method it's associated to the Interface WebElement. So before you invoke isDisplayed() method first you have to locate/search the element then only you can invoke isDisplayed(), isEnabled(), isSelected() or any other associated methods.
Of-coarse, in your previous steps when you tried to find/locate the desired WebElement through either findElement(By by) or findElements(By by) method NoSuchElementFound exception was raised. When findElement(By by) or findElements(By by) method raises NoSuchElementFound exception ofcoarse the following line of fieldValueBox.isDisplayed(); won't be executed.
Solution
A possible solution for your problem would be to invoke findElement(By by) within a try-catch {} block as follows :
try {
WebElement fieldValueBox = driver.findElement(By.id("element_id"));
bool displayed = fieldValueBox.isDisplayed();
//use the bool value of displayed variable
} catch (NoSuchElementException e) {
//perform other tasks
}
I am new to the site. I am trying to select/click on elements on http://autotask.net. I have tried to find element using the following methods:
driver.find_element_by_css_selector('#HREF_btnPrint > img:nth-child(1)')
driver.find_element_by_xpath('browser.find_element_by_xpath('/html/body/form[1]/div[2]/div[1]/ul/li[2]/a/img')
...but it gives me the exception in the Title.
I can find elements fine on the logon page(i.e. 'username' 'password' fields), but once I log in - selenium can't find any elements on the page.
I've only been learning/coding python for a few weeks now and I know nothing about Java. If you need more information, please let me know - Thanks.
I'm not sure about the python syntax, so I will use Java instead. I think there are 2 possible cases, first your driver look into the DOM structure while the page is loading. The other one is the web driver doesn't points at the root of DOM. I usually have the wait method to wait until the page finish loading, and switch to the default content before looking for some elements.
First, I pass both WebDriver, Element id, and Element name through constructor. Then I have waitUntilReady() that implement the logic to check the existing of element within specific timeout.
public void waitUntilReady() {
WebDriverWait waiter = new WebDriverWait(getWebDriver(), 30);
waiter.withMessage("\"" + getElementName() + "\" is not ready in 30 seconds")
.until(new Predicate<WebDriver>() {
#Override
public boolean apply(WebDriver input) {
/* isReady() returns true if all elements
* that you need to test are available.
* Note that if you have javascript, you
* should have some hidden field to tell
* you that the whole page has loaded. */
return isReady();
}
});
}
as well as switch to default content before find the element
WebElement getWebElement() {
WebElement webElement;
try {
getWebDriver().switchTo().defaultContent();
webElement = getWebDriver().findElement(By.id(elementId));
} catch (NoSuchElementException ex) {
getLogger().log(Level.SEVERE, "Element id '" + elementId + "' does not exist");
throw ex;
}
return webElement;
}
If it doesn't work, you can have <body id="container">, then use driver.findElementById("container").findElementById("your target element")
I am very beginner with Selenium and Java to write tests.
I know that I can use the code below to try to click on a web element twice (or as many time as I want):
for(int i=0;i<2;i++){
try{
wait.until(wait.until(ExpectedConditions.visibilityOfElementLocated
(By.xpath("//button[text()='bla bla ..']"))).click();
break;
}catch(Exception e){ }
}
but i was wondering if there is anything like passing a veriable to the wait function to make it do it ith times itself, something like:
wait.until(wait.until(ExpectedConditions.visibilityOfElementLocated
(By.xpath("//button[text()='bla bla ..']"),2)).click();
For example in here 2 may mean that try to do it two times if it fails, do we have such a thing?
Take a look at FluentWait, I think this will cover your use case specifying appropriate timeout and polling interval.
https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/FluentWait.html
If you can't find something in the set of ExpectedConditions that does what you are wanting you can always write your own.
The WebDriverWait.until method can be passed either a com.google.common.base.Function or com.google.common.base.Predicate. If you create your own Function implementation then it's good to note that any non-null value will end the wait condition. For Predicate the apply method simply needs to return true.
Armed with that I do believe there's very little you can't do with this API. The feature you're asking about probably does not exist out of the box, but you have full capability to create it.
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Function.html
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Predicate.html
Best of Luck.
Untested Snippet
final By locator = By.xpath("");
Predicate<WebDriver> loopTest = new Predicate<WebDriver>(){
#Override
public boolean apply(WebDriver t) {
int tryCount = 0;
WebElement element = null;
while (tryCount < 2) {
tryCount++;
try {
element = ExpectedConditions.visibilityOfElementLocated(locator).apply(t);
//If we get this far then the element resolved. Break loop.
break;
} catch (org.openqa.selenium.TimeoutException timeout) {
//FIXME LOG IT
}
}
return element != null;
}
};
WebDriverWait wait;
wait.until(loopTest);
I'm testing a web application using Selenium WebDriver and I was wondering which is the proper method to check if the elements are present or displayed. I usually assert that all elements are present on the page but it also checks the hidden elements which in this case would also be necessary to check if the elements are displayed only when some action is done. For example I click a link and other fields and labels are displayed, while they were hidden before. In this case I should both check if the elements are present and also if they are or not displayed before and after some other element is clicked.
I was wondering which is the proper way to do this. Is it too much to check all the elements on the page ( assuming that I have some buttons, text-fields, labels, links etc. in the page)?
For the purpose of discussion I want to include some code snippets. To check that elements are present on the page I use the following snippet:
public boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
}
To check if an element is displayed I use the following snippet:
public boolean isElementDisplay(By by) {
if (driver.findElement(by).isDisplayed()) {
return true;
} else
return false;
}
One purpose of testing this application is to check if the elements exists and are displayed correctly. Am I doing the right thing here? Please give me your point of view. I've recently started working with Selenium WebDriver and being the only one in my company who does this...I don't have anyone to turn to. Any answer is appreciated.
There are no problems with it, except if you call your "checkIfDisplayed" method on an element that doesn't exist in the first place, it will throw an exception. I would modify it to this:
public boolean checkIfDisplayed(By by) {
if (isElementPresent(by) {
if (driver.findElement(by).isDisplayed()) {
return true;
} else
return false;
} else
return false;
}
(This may not be code that compiles, I am a C# man, but you should see what I mean)
It may have a slight performance hit, but overall what you are doing is perfectly fine anyway.
To check for element's existence I'd rather use
public boolean isElementPresent(By by)
{
return driver.findElements(by).size() > 0
}
I don't really get the idea behind your checkIfDisplayed function. It returns the result returned by WebElemet's isDisplayed() method without adding any new functionality...
EDIT
So far Arran provided the best answer. Just to modify it a little bit:
public boolean checkIfDisplayed(By by)
{
List<WebElemet> elements = driver.findElements(by);
return ((elements.size() > 0) && (elements[0].isDisplayed()));
}
I believe however that it would be better to call isElementPresent and isDisplayed separately. In this way you will know why the test failed (if it was caused by element's existence or visibility)
I use the same approach (I mean the same methods). But it is important to understand two things.
Some element can be present but not visible.
So for the purpose to verify whether element is present we can call the method
public boolean isElementPresent(By locatorKey) {
try {
driver.findElement(locatorKey);
return true;
} catch (NoSuchElementException e) {
return false;
}
But the drawback of isElementPresent method it can point out elements in DOM model that are not visible on the page and consequently are not accesssible with webDriver. So in that case additional check helps us:
driver.findElement(By.xpath(....)).isDisplayed()
Hope things come clear now)
I'd say your first method looks just fine.
The 2nd thus will give you trouble if the findElement-call will give you no result.
You should add a check if there is an element found and then check if it's displayed:
try {
final WebElement elem = driver.findElement(by);
elem.isDisplayed();
return true;
} catch (NoSuchElementException nse) {
return false;
}
Also note: You are ignore the possibility that more than one element matches the criteria given by the by instance. See the findElemts() method.
You can also combine both the methods as per your requirement as follows,
if(driver.findElements(By.LOCATOR).size()>0)
{
if(driver.findElement(By.LOCATOR).isDisplayed())
{ print "Element is present and displayed"; }
else
{ print "Element is present but not displayed"; }
}
else
{ print "Element is not present"; }