Checking for `driver.findElement(...)` in an IF statement throws `NoSuchElementException` - java

I'm getting NoSuchElementException when running the following code.
if (driver.findElement(By.xpath("//*[#id='gr2']")).isDisplayed()) {
Thread.sleep(5000);
driver.findElement(By.xpath("//*[#id='balInqTableStep2']/td/table/tbody/tr/td/table/tbody/tr[3]/td[4]/input[2]")).click();
}
else {
test.log(LogStatus.FAIL,"Please configure Gift Slabs for this site. Contact business.");
test.log(LogStatus.FAIL,"Second time wallet credit is not done");
}

NoSuchElementException exception means there is not element present on the page.
isDisplayed method assumes that element is already present on the page and so throws you exception when element is not present.
you can either make sure that element is present before calling webdriver method and you can write your own method to handle this for you.
following code snippet might help you
public boolean isDisplayed(By identifier){
boolean isElementDisplayed = false;
try{
WebElement element = driver.findElement(identifier);
isElementDisplayed = element.isDisplayed()
}catch (NoSuchElementException){
return false;
}
return isElementDisplayed;
}
and you can call it like this
isDisplayed(By.xpath("//*[#id='gr2']")

Always when you call driver.findElement(By.xpath("//*[#id='gr2']")) and the element is not present in the DOM, it's gonna throw a NoSuchElementException.
There is an alternative to avoid the code throwing the exception, calling the method findElements, instead of findElement.
E.g.:
List<WebElement> elements = driver.findElements(By.xpath("//*[#id='gr2']"));
if(!elements.isEmpty() && elements.get(0).isDisplayed()) {
Thread.sleep(5000);
driver.findElement(By.xpath("//*[#id='balInqTableStep2']/td/table/tbody/tr/td/table/tbody/tr[3]/td[4]/input[2]")).click();
}
else {
test.log(LogStatus.FAIL,"Please configure Gift Slabs for this site. Contact business.");
test.log(LogStatus.FAIL,"Second time wallet credit is not done");
}
Hope it works for you.

Related

Selenium click function is not getting Fail

The below code is written for click function.
public void click(By element) {
try {
driver.findElement(element).click();
}
catch (AssertionError e) {
System.out.println("Element " + element + " not found on page");
return;
}
}
The below code is written for calling the click function in my test case.
#Test(priority = 1)
public void accept_cookies_dialog() throws Exception {
try {
click(By.id(propObjctRepo.getProperty("id_cookieCta")));
} catch (Exception e) {
addErrorlogs(e, "Not found accpet cookie dialog.");
}
}
My concern is, In every case either the element present or not the test case is getting pass. I am doing something wrong, Please suggest me the solution.
Instead of using try/catch block, you can directly use assertions to check if the element is present on the page or not. If the list size of the element is greater than zero then the element is present on the page else it is not. By this, if the element is not present on the page, assertion will fail and so will the test case.
You can do it like:
Assert.assertTrue(driver.findElements(By.id(propObjctRepo.getProperty("id_cookieCta"))).size()>0);
And then below this you can click the element, so if and only if the assertion passes, your code will reach the click method else your test case will fail.

Selenium- exception instead of boolean value

I write a code where I have found the result element visible or not, but I have received an exception.
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']"}
Here is my code
wd.navigate().refresh();
Thread.sleep(7000);
boolean airbnb = wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed();
assertFalse(airbnb, "Airbnb Add will not show After clicking Add one times");
Is there any suggestion why element not found showing? if element not found then it should be false I am not sure where I mistake?
To avoid an exception, and expensive use of try - catch, you can locate the element using findElements. If the result list is not empty you can check if the existed element is displayed or not
List<WebElement> elements = wd.findElements(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']"));
assertFalse(elements.size() > 0 && elements.get(0).isDisplayed(), "Airbnb Add will not show After clicking Add one times");
Either use try- catch block or use throws Exception to catch the NoSuchElementException
public void methodName() throws Exception
{
if(wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed())
{
System.out.println("Element displayed");
}
}
or
try
{
if(wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed())
{
System.out.println("Element displayed");
}
}
catch(NoSuchElementException e)
{
System.out.println("Element is not displayed");
}
Since you do not expect the element to be there the following code would throw an exception :
boolean airbnb = wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed();
and your assert statement would not even be reached.
You can actually place an expected exception in your code instead of asserting as(in Junit):
#Test(expected = NoSuchElementException.class)
public void youtTest() {
// do whatever you're doing
Thread.sleep(7000);
wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']"));
}
in TestNG the syntax is somehwat like :
#Test(expectedExceptions = { NoSuchElementException.class })
This is the issue with Selenium, you need to use try catch block something like below
try
{
if(wd.findElement(By.xpath(".//*[#class='airbnb-wide-block-search-btn js-airbnb-search-btn']")).isDisplayed())
{
//Your code
}
}
catch (Exception e)
{
//Your code
}
Let me put it this way: IsDisplayed will work on Object of Type WebElement.
here is the clarification
findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead.
found on findElement

How do I determine if a WebElement exists with Selenium?

I know I could use (driver.findElements(By.xpath("Xpath Value")).size() != 0);
However, I am using a Page Object Model, whose entire purpose is to predefine the WebElements in a separate class, so I don't have to "FindElements By" in my test classes.
Here's what I currently have
if (objPage.webElement.isEnabled()){
System.out.println("found element");
}else{
System.out.println("element not found");
}
However, this tries to identify the possibly non-existent WebElement. When it is not present, I get:
No Such Element" exception.
Best practice is to do what you originally suggested. Use .findElements() and check for .size != 0, or you can also use my preference, .isEmpty(). You can create a utility function like the below to test if an element exists.
public boolean elementExists(By locator)
{
return !driver.findElements(locator).isEmpty();
}
You could also build this into a function in your page object.
You can use isDisplayed() to check whether or not an element is visible. It’s trivial enough to write a method which will do what you want. Something like:
public boolean isElementDisplayed(WebElement element) {
try {
return element.isDisplayed();
} catch(NoSuchElementException e) {
return false;
}
}

Which is the correct way to check if an element is present or displayed on a page with Selenium WebDriver using Java?

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"; }

Test if an element is present using Selenium WebDriver

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);
}

Categories