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));
}
I'm trying to check the clickability of a non-input text element (which can only be viewed but not edited). I have a test that where I want to assert that the view only text element (Ex: First Name) displayed on page can not be clicked.
I have tried using the isEnabled() method to check if the view only text element is enabled or not but the assertion is not happening correctly.
This is Bobcat Selenium code
Step definition code:
#Then("^I should verify that the First Name is not clickable$")
public void iShouldVerifyThatTheFirstNameIsNotClickable() {
assertEquals("Error: First Name is clickable", true,
fullName.verifyClick());
}
Page Object code:
public boolean verifyClick() {
if (firstName.isEnabled()) {
return true;
}
else {
return false;
}
}
Expected result: Since firstName is a view only element, the result of the verifyClick() method should be false so my #Then("^I should verify that the First Name is not clickable$") result should fail since the assertion is failing.
Actual result: #Then("^I should verify that the First Name is not clickable$") result is success.
There is a part of the selenium Java bindings that could be useful to you here. In ExpectedConditions you'll find a function called elementToBeClickable(). This returns a boolean that's false whenever the element is not clickable for any reason, and true when it can receive a click. So you just want to wait and see if that function returns true. Selenium handles that as well with the WebDriverWait class.
So you'll need to import both of those, and then you can do something like this:
//setting the timeout for our wait to be 20 seconds (you can use whatever you want)
WebDriverWait myWaitVar = new WebDriverWait(driver,20);
try {
WebElement myElement = myWaitVar.until(ExpectedConditions.elementToBeClickable(firstName)));
//assert test failed!
}
catch(timeoutException timeout) {
//whatever you want to do when the element is not clickable
}
unable to locate the hidden element in div
<div id="divDuplicateBarcodeCheck" class="spreadsheetEditGui" style="z-
index: 1200; width: 640px; height: 420px; top: 496.5px; left: 640px;
display:block"> ==$0
I want to locate the display element, but the element is hidden, i have written the code for it too.
String abc=d.findElement(By.xpath("//div[#id='divDuplicateBarcodeCheck']/"))
.getAttribute("display");
System.out.println(abc);
Thread.sleep(3000);
if(abc.equalsIgnoreCase("block"))
{
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
}
else
{ System.out.println("Barcode selected");}
There is no such attribute as display. It's part of style attribute.
You can either find the element and get its attribute style:
String style = d.findElement(By.xpath("//div[#id='divDuplicateBarcodeCheck']")).getAttribute("style");
if(style.contains("block")) {
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
} else {
System.out.println("Barcode selected");}
}
OR you can find this element directly with cssSelector (it's also possible with xpath):
WebElement abc = d.findElement(By.cssSelector("div[id='divDuplicateBarcodeCheck'][style*='display: block']"))
Note, that above will throw NoSuchElementException if the element was not found. You can use try-catch block to perform similar operations just like you did in if-else statement like this:
try {
d.findElement(By.cssSelector("div[id='divDuplicateBarcodeCheck'][style*='display: block']"));
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
} catch (NoSuchElementException e) {
System.out.println("Barcode selected");
}
If I'm getting you correct you are trying to archive checking if an element is displayed or not. You could do something like this using plain selenium and java:
// the #FindBy annotation provides a lazy implementation of `findElement()`
#FindBy(css = "#divDuplicateBarcodeCheck")
private WebElement barcode;
#Test
public void example() {
driver.get("http://some.url");
waitForElement(barcode);
// isDisplay() is natively provided by type WebElement
if (barcode.isDisplayed()) {
// do something
} else {
// do something else
}
}
private void waitForElement(final WebElement element) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOf(element));
}
Your Test (an end-to-end UI test!) should not stick to an implementation detail like display:none or display:block. Imagine the implementation will be changed to remove the element via javascript or something. A good selenium test should always try represent a real users perspective as good as possible. Means if the UI will still behave the same your test should still be successful. Therefore you should do a more general check - is an element displayed or not.
This is one of the basic functionalities of Seleniums WebElement interface, or to be even more precise its isDisplayed() method.
Quote from the Selenium Java Docs:
boolean isDisplayed()
Is this element displayed or not?
This method avoids the problem of having to
parse an element's "style" attribute.
Returns:
Whether or not the element is displayed
Furthermore I would recommend to write some small helper methods for things like that, in my experience it's a common use case you'll face more often.
helper method could for instance look something like this:
boolean isElementVisible(final By by) {
return driver.findElement(by).isDisplayed();
}
boolean isElementVisible(final WebElement element) {
return element.isDisplayed();
}
If you are using some Selenium abstractions like FluentLenium or Selenide things will become even more convenient because they provide things like assertion extensions and custom matchers for well known assertion libraries like assertJ, hamcrest, junit.
For instance with FluentLenium and AssertJ (a stack that i can personally recommend) the answer for your problem is looking as easy as this:
// check if element is displayed
assertThat(el("#divDuplicateBarcodeCheck")).isDisplayed();
// check if element is not displayed
assertThat(el("#divDuplicateBarcodeCheck")).isNotDisplayed();
Some more thoughts:
You should also use CSS selectors if possible instead of xPath selectors. CSS selectors are less fragile, it will speed up your tests and are better readable.
You should have a look at implicit waits instead of using Thread sleeps (bad practice). you can again implement helper methods like this by yourself, e.g:
void waitForElement(final WebElement element) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOf(element));
}
void waitForElement(final By by) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(by));
}
void waitForElementIsInvisible(final By by) {
final WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.invisibilityOfElementLocated(by));
}
or (what i would recommend) use a library for that, for instance Awaitility
If your are looking for a more extended example you can have a look here:
java example with plain selenium
example using fluentlenium and a lot of other helpful stuff
Seems there is an extra / at the end of the xpath which you need to remove. Additionally, you need to induce WebDriverWait for visibilityOfElementLocated(). So effectively your line of code will be:
String abc = new WebDriverWait(d, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//label[contains(.,'Leave Balance')]//following::div[#id='applyleave_leaveBalance']"))).getAttribute("style");
System.out.println(abc);
if(abc.contains("block"))
{
d.findElement(By.id("duplicateBarcodeCheck")).click();
System.out.println("duplicate barcode Close");
}
else
{
System.out.println("Barcode selected");
}
Virtually, if() block is still an overhead and you can achieve the same with:
try {
new WebDriverWait(d, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//label[contains(.,'Leave Balance')]//following::div[#id='applyleave_leaveBalance']"))).click();
System.out.println("duplicate barcode Close");
} catch (NoSuchElementException e) {
System.out.println("Barcode selected");
}
Q1. I want to locate the display element, but the element is hidden, i have written the code for it too.
A1. As per your below code:
<div id="divDuplicateBarcodeCheck" class="spreadsheetEditGui" style="z-
index: 1200; width: 640px; height: 420px; top: 496.5px; left: 640px;
display:block"> ==$0
It doesn't look hidden, the problem is that your using incorrect xpath and element getter.
Use:
String abc = d.findElement(By.xpath("//div[#id='divDuplicateBarcodeCheck']"))
.getCssValue("display");
Instead of:
=> .getAttribute("display");
Alternative method using JavascriptExecutor:
JavascriptExecutor jse = (JavascriptExecutor) d;
String displayProperty = (String) jse.executeScript("return
document.getElementById('divDuplicateBarcodeCheck').style.display");
System.out.println("Display property is: "+displayProperty);
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));
}
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);
}