first time poster, long time user reaping the benefits of all these great questions. But I need your help.
What I'm trying to do below is
Navigate to a page
Find all the particular links
Click on the first link
Check to see if an element is displayed, if it is displayed then navigate back to the previous page and click on the next link of the list. If it is NOT displayed then exit out of the method and continue the test script. This is the part where I'm stuck.
The if statement executes as desired whereby if it finds the element then it navigates back to the previous. But where it fails is when it clicks on the second link of the page. It searches for that element even though that element does not exist in that page and does not exit out of the method even though I've explicitly stated return.
I'm having a brain fart and tried all the possible combinations and permuatations I can think of. If there's anyone out there that can help me I'd greatly appreciate the help.
EDIT
Let me edit to clarify my thoughts. I need my method to exit out of the method once inactive.isDisplayed() returns false. But when it navigates to the second page, it continually tries to find the element then eventually fails with a NoSuchElementException. I know the element doesn't exist, that's why I need it to exit out of the method and perform the next step of the test script. I hope this clarify my situation. It's not really a Selenium WebDriver question as it is a java question.
Thanks
public void checkErrors() {
List<WebElement> videos =driver.findElements(By.cssSelector(".row-
title"));
for (int i = 0; i < videos.size(); i++) {
videos = driver.findElements(By.cssSelector(".row-title"));
videos.get(i).click();
if (inactive().isDisplayed() != false) {
driver.navigate().back();
} else {
return;
}
}
return;
}
EDIT:
private WebElement inactive() {
inactive =
driver.findElement(By.cssSelector("#message>p>strong"));
highlightElement(inactive);
return inactive;
}
You might want to check the presence of the message before checking if it's displayed:
public void checkErrors() {
for(int i = 0; ; i++) {
// handle next link
List<WebElement> videos = driver.findElements(By.cssSelector(".row-title"));
if (i >= videos.size())
return;
// click the next link
WebElement video = videos.get(i);
video.click();
// return if the message is missing or hidden
List<WebElement> messages = driver.findElements(By.cssSelector("#message>p>strong"));
if (messages.size() == 0 || !messages.get(0).isDisplayed())
return;
driver.navigate().back();
}
}
Small recommendation to help you here:
As you're not using the WebElement returned by inactive() after you've checked if it's displayed or not, you might as well move the logic for checking whether its displayed to inactive() and return the value of isDisplayed(). For example:
private boolean inactive() {
try {
inactive = driver.findElement(By.cssSelector("#message>p>strong"));
highlightElement(inactive);
return inactive.isDisplayed(); // Element is present in the DOM but may not visible due to CSS etc.
} catch (NoSuchElementException e) {
return false; // Element is not present in the DOM, therefore can't be visible.
}
}
I've been researching this error for a while and have tried many things and nothing seems to work...
while(!driver.findElements(By.className("next")).isEmpty()) {
//elements = driver.findElements(By.xpath("//a[#class='name']"));
elements = findDynamicElements("//a[#class='name']");
for (WebElement e : elements) {
userName = e.getText(); //<--EXCEPTION HERE
check_visitor_profile(userName);//<--WE LEAVE THE PAGE HERE
Thread.sleep(3000); //<--NO TRY/CATCH BLOCK FOR READABILITY
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
elements = findDynamicElements("//a[#class='name']");
}
driver.findElement(By.xpath("VisitsNext")).click();
}
protected List<WebElement> findDynamicElements(String path) {
List<WebElement> result;
String xPath = path;
new WebDriverWait(driver, 25).until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath(xPath)));
//new WebDriverWait(driver, 25).until(elementIdentified(By.id(path)));
try {
result = driver.findElements(By.xpath(xPath));
return result;
}
catch(WebDriverException e) {
return null;
}
);
}
My code craps out on the first line of the for loop where userName is assigned. I've seen on this forum that you should use 'presenceOfElementLocated' and explicitly wait for the element to come back but that doesn't work either. I used 'presenceOfAllElementsLocatedBy' for a list but I have a method that uses 'presenceOfElementLocated' which doesn't work either.
I know stuff like the Thread.sleep and the implicitlyWait line is probably unnecessary at this point but I've literally tried everything and it doesn't work...
The error occurs because when I call 'check_visitor_profile' it leaves the page - when it comes back the elements are out of place so I have to find them again. Which I do but it still throws the exception.
Any Ideas?
Thanks.
The problem might occur because you are changing elements in the middle of the loop. It will cause you trouble even without the StaleElementReferenceException. Use a for loop instead of the for each loop
elements = findDynamicElements("//a[#class='name']");
int size = elements.size();
for (int i = 0 ; i < size ; ++i) {
elements = findDynamicElements("//a[#class='name']");
userName = elements.get(i).getText();
check_visitor_profile(userName);
}
Handle the exception explicitly as the element is no longer attached to the DOM or has changed at that moment you call "check_visitor_profile"
See the link below might help
catch(StateElementException e){
System.out.println("StaleElement dealt with since you successfully left page ");
}
http://docs.seleniumhq.org/exceptions/stale_element_reference.jsp
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 using the PageObject/PageFactory design pattern for my UI automation. Using Selenium 2.0 WebDriver, JAVA, I randomly get the error: org.openqa.selenium.StaleElementReferenceException: Element is no longer attached to the DOM, when I attempt logic like this:
#FindBy(how = HOW.ID, using = "item")
private List<WebElement> items
private void getItemThroughName(String name) {
wait(items);
for(int i = 0; i < items.size(); i++) {
try {
Thread.sleep(0500);
} catch (InterruptedException e) { }
this.wait(items);
if(items.get(i).getText().contains(name)) {
System.out.println("Found");
break;
}
}
}
The error randomly happens at the if statement line, as you can see I've tried a couple things to avoid this, like sleeping a small amount of time, or waiting for the element again, neither works 100% of the time
First if you really have multiple elements on the by with the ID of "item" you should log a bug or talk to the developers on the site to fix that. An ID is meant to be unique.
As comments on the question already implied you should use an ExplicitWait in this case:
private void getItemThroughName(String name) {
new WebDriverWait(driver, 30)
.until(ExpectedConditions.presenceOfElementLocated(
By.xpath("id('item')[.='" + name + "']")
));
// A timeout exception will be thrown otherwise
System.out.println("Found");
}
Is there a way how to test if an element is present? Any findElement method would end in an exception, but that is not what I want, because it can be that an element is not present and that is okay. That is not a fail of the test, so an exception can not be the solution.
I've found this post: Selenium C# WebDriver: Wait until element is present.
But this is for C#, and I am not very good at it. What would the code be in Java? I tried it out in Eclipse, but I didn't get it right into Java code.
This is the code:
public static class WebDriverExtensions{
public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds){
if (timeoutInSeconds > 0){
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}
return driver.FindElement(by);
}
}
Use findElements instead of findElement.
findElements will return an empty list if no matching elements are found instead of an exception.
To check that an element is present, you could try this
Boolean isPresent = driver.findElements(By.yourLocator).size() > 0
This will return true if at least one element is found and false if it does not exist.
The official documentation recommends this method:
findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead.
Use a private method that simply looks for the element and determines if it is present like this:
private boolean existsElement(String id) {
try {
driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
return false;
}
return true;
}
This would be quite easy and does the job.
You could even go further and take a By elementLocator as a parameter, eliminating problems if you want to find the element by something other than an id.
I found that this works for Java:
WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);
public static WebElement FindElement(WebDriver driver, By by, int timeoutInSeconds)
{
WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
wait.until( ExpectedConditions.presenceOfElementLocated(by) ); //throws a timeout exception if element not present after waiting <timeoutInSeconds> seconds
return driver.findElement(by);
}
I had the same issue. For me, depending on a user's permission level, some links, buttons and other elements will not show on the page. Part of my suite was testing that the elements that should be missing, are missing. I spent hours trying to figure this out. I finally found the perfect solution.
It tells the browser to look for any and all elements based specified. If it results in 0, that means no elements based on the specification was found. Then I have the code execute an *if statement to let me know it was not found.
This is in C#, so translations would need to be done to Java. But it shouldn’t be too hard.
public void verifyPermission(string link)
{
IList<IWebElement> adminPermissions = driver.FindElements(By.CssSelector(link));
if (adminPermissions.Count == 0)
{
Console.WriteLine("User's permission properly hidden");
}
}
There's also another path you can take depending on what you need for your test.
The following snippet is checking to see if a very specific element exists on the page. Depending on the element's existence I have the test execute an if else.
If the element exists and is displayed on the page, I have console.write let me know and move on. If the element in question exists, I cannot execute the test I needed, which is the main reasoning behind needing to set this up.
If the element does not exist and is not displayed on the page, I have the else in the if else execute the test.
IList<IWebElement> deviceNotFound = driver.FindElements(By.CssSelector("CSS LINK GOES HERE"));
// If the element specified above results in more than 0 elements and is displayed on page execute the following, otherwise execute what’s in the else statement
if (deviceNotFound.Count > 0 && deviceNotFound[0].Displayed){
// Script to execute if element is found
} else {
// Test script goes here.
}
I know I'm a little late on the response to the OP. Hopefully this helps someone!
Try this:
Call this method and pass three arguments:
WebDriver variable. Assuming driver_variable as the driver.
The element which you are going to check. It should provide a from By method. Example: By.id("id")
Time limit in seconds.
Example: waitForElementPresent(driver, By.id("id"), 10);
public static WebElement waitForElementPresent(WebDriver driver, final By by, int timeOutInSeconds) {
WebElement element;
try{
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); // Nullify implicitlyWait()
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
element = wait.until(ExpectedConditions.presenceOfElementLocated(by));
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); // Reset implicitlyWait
return element; // Return the element
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
This works for me:
if(!driver.findElements(By.xpath("//*[#id='submit']")).isEmpty()){
// Then click on the submit button
}
else{
// Do something else as submit button is not there
}
You can make the code run faster by shorting the Selenium timeout before your try-catch statement.
I use the following code to check if an element is present.
protected boolean isElementPresent(By selector) {
selenium.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
logger.debug("Is element present"+selector);
boolean returnVal = true;
try{
selenium.findElement(selector);
} catch (NoSuchElementException e) {
returnVal = false;
} finally {
selenium.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
}
return returnVal;
}
Write the following function/methods using Java:
protected boolean isElementPresent(By by){
try{
driver.findElement(by);
return true;
}
catch(NoSuchElementException e){
return false;
}
}
Call the method with the appropriate parameter during the assertion.
If you are using rspec-Webdriver in Ruby, you can use this script, assuming that an element should really not be present, and it is a passed test.
First, write this method first from your class RB file:
class Test
def element_present?
begin
browser.find_element(:name, "this_element_id".displayed?
rescue Selenium::WebDriver::Error::NoSuchElementError
puts "this element should not be present"
end
end
Then, in your spec file, call that method.
before(:all) do
#Test= Test.new(#browser)
end
#Test.element_present?.should == nil
If your element is not present, your spec will pass, but if the element is present, it will throw an error, and the test failed.
Personally, I always go for a mixture of the above answers and create a reusable static utility method that uses the size() > 0 suggestion:
public Class Utility {
...
public static boolean isElementExist(WebDriver driver, By by) {
return driver.findElements(by).size() > 0;
...
}
This is neat, reusable, maintainable, etc.—all that good stuff ;-)
public boolean isElementDisplayed() {
return !driver.findElements(By.xpath("...")).isEmpty();
}
This should do it:
try {
driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
//do what you need here if you were expecting
//the element wouldn't exist
}
I would use something like (with Scala [the code in old "good" Java 8 may be similar to this]):
object SeleniumFacade {
def getElement(bySelector: By, maybeParent: Option[WebElement] = None, withIndex: Int = 0)(implicit driver: RemoteWebDriver): Option[WebElement] = {
val elements = maybeParent match {
case Some(parent) => parent.findElements(bySelector).asScala
case None => driver.findElements(bySelector).asScala
}
if (elements.nonEmpty) {
Try { Some(elements(withIndex)) } getOrElse None
} else None
}
...
}
so then,
val maybeHeaderLink = SeleniumFacade getElement(By.xpath(".//a"), Some(someParentElement))
The simplest way I found in Java was:
List<WebElement> linkSearch= driver.findElements(By.id("linkTag"));
int checkLink = linkSearch.size();
if(checkLink!=0) {
// Do something you want
}
To find if a particular Element is present or not, we have to use the findElements() method instead of findElement()...
int i = driver.findElements(By.xpath(".......")).size();
if(i=0)
System.out.println("Element is not present");
else
System.out.println("Element is present");
This is worked for me...
You can try implicit wait:
WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));
Or you can try explicit wait one:
IWebDriver driver = new FirefoxDriver();
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("someDynamicElement"));
});
Explicit will check if the element is present before some action. Implicit wait could be called in every place in the code. For example, after some Ajax actions.
More you can find at SeleniumHQ page.
I am giving my snippet of code. So, the below method checks if a random web element 'Create New Application' button exists on a page or not. Note that I have used the wait period as 0 seconds.
public boolean isCreateNewApplicationButtonVisible(){
WebDriverWait zeroWait = new WebDriverWait(driver, 0);
ExpectedCondition<WebElement> c = ExpectedConditions.presenceOfElementLocated(By.xpath("//input[#value='Create New Application']"));
try {
zeroWait.until(c);
logger.debug("Create New Application button is visible");
return true;
} catch (TimeoutException e) {
logger.debug("Create New Application button is not visible");
return false;
}
}
In 2022 this can now be done without an annoying delay, or affecting your current implicit wait value.
First bump your Selenium driver to latest (currently 4.1.2).
Then you can use getImplicitWaitTimeout then set timeout to 0 to avoid a wait then restore your previous implicit wait value whatever it was:
Duration implicitWait = driver.manage().timeouts().getImplicitWaitTimeout();
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(0));
final List<WebElement> signOut = driver.findElements(By.linkText("Sign Out"));
driver.manage().timeouts().implicitlyWait(implicitWait); // Restore implicit wait to previous value
if (!signOut.isEmpty()) {
....
}
Try the below code using the isDispplayed() method to verify if the element is present or not:
WebElement element = driver.findElements(By.xpath(""));
element.isDispplayed();
There could be multiple reasons due to which you might observe exceptions while locating a WebElement using Selenium driver.
I would suggest you to apply the below suggestions for different scenarios:
Scenario 1: You just want to find out if a certain WebElement is present on the screen or not. For example, the Save button icon will only appear until the form is fully filled and you may want to check if Save button is present or not in your test.
Use the below code -
public Boolean isElementLoaded(By locator){
return !getWebElements(this.driver.findElements(locator), locator).isEmpty();
}
Scenario 2: You want to wait before a WebElement becomes visible in the UI
public List<WebElement> waitForElementsToAppear(By locator) {
return wait.until(visibilityOfAllElementsLocatedBy(by));
}
Scenario 3: Your test is flaky because the WebElement becomes stale sometimes and gets detached from the DOM.
protected final List<Class<? extends WebDriverException>> exceptionList =
List.of(NoSuchWindowException.class,
NoSuchFrameException.class,
NoAlertPresentException.class,
InvalidSelectorException.class,
ElementNotVisibleException.class,
ElementNotSelectableException.class,
TimeoutException.class,
NoSuchSessionException.class,
StaleElementReferenceException.class);
public WebElement reactivateWebElement(By by, WebElement element){
try {
wait.ignoreAll(exceptionList)
.until(refreshed(visibilityOf(element)));
logger.info(("Element is available.").concat(BLANK).concat(element.toString()));
} catch (WebDriverException exception) {
logger.warn(exception.getMessage());
} return this.driver.findElement(by);
}