Determining WebElement Clickability in Java and Selenium: Beyond the Basics of isDisplayed, isEnabled, and findElement

There is a common method to test if a WebElement is clickable:

It typically involves something like this:

public static boolean isElementClickable(WebDriver driver, String accessor){

        return driver.findElements(By.xpath(accessor)).size() > 0 && driver.findElement(By.xpath(accessor)).isDisplayed() && driver.findElement(By.xpath(accessor)).isEnabled();
        //isDisplayed(): This method helps avoid the need to parse an element's "style" attribute to check its visibility. It returns false when the element is not present
        //isEnabled(): Generally returns true, except for disabled input elements.
    }

This function has a flaw because it only checks if the Element is clickable at the DOM level. If the element is hidden or overlapped due to CSS issues, one may encounter an Exception like:

org.openqa.selenium.WebDriverException: unknown error: Element is not clickable at point (781, 704). Other element would receive the click:

...

In such cases, one can still interact with the element using:

// Assume 'driver' is a valid WebDriver instance that
// has been properly instantiated elsewhere.
WebElement element = driver.findElement(By.id("example"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);

However, I am curious about how we can determine without actually clicking through executor.executeScript whether a WebElement is visible and not obstructed by another element, ensuring it is perfectly clickable.

If anyone could provide insight on this matter, I would greatly appreciate it as my research has not yielded any definitive answers thus far.

Answer №1

While I typically avoid creating a function that handles all clicks in this manner, if I had to write one it would look something like the code below. Comments within the code explain the process.

public static void clickElement(By locator) throws InterruptedException
{
    try
    {
        // Attempt to wait for the element to be clickable and then click it
        new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(locator)).click();
    }
    catch (TimeoutException e)
    {
        // Element never becomes present
    }
    catch (WebDriverException e)
    {
        // If click is blocked by another element, retry for 10 seconds
        while (true)
        {
            Instant timeOut = Instant.now().plusSeconds(10);
            try
            {
                driver.findElement(locator).click();
                break;
            }
            catch (WebDriverException e2)
            {
                // Ignore additional blocked click exceptions
            }

            if (Instant.now().isAfter(timeOut))
            {
                // If element is still blocked after retries for 10 seconds, fallback to JSE click
                ((JavascriptExecutor) driver).executeScript("arguments[0].click();", driver.findElement(locator));
            }

            // Slight pause between loops
            Thread.sleep(100);
        }
    }
}

Some advice on your function... It is recommended to pass around By instances instead of strings, like so:

By locator = By.id("myId");

This approach makes your functions more flexible and not limited to XPath only. Additionally, consider scraping the page once and then using the stored element to perform checks for visibility and enablement, as shown below:

public static boolean isElementFoundDisplayedEnabled(WebDriver driver, By locator)
{
    List<WebElement> e = driver.findElements(locator);

    return !e.isEmpty() && e.get(0).isDisplayed() && e.get(0).isEnabled();
}

Answer №2

Providing you with facts and insights regarding your query:

  1. In my opinion, using the
    isElementFoundDisplayedEnabled(WebDriver driver, String accessor)
    method may be unnecessary as Selenium already includes the built-in WebDriverWait class. I will elaborate on this further in my response.
  2. The documentation clearly states that isDisplayed() only checks if an element is currently displayed or not, avoiding the need to parse the element's "style" attribute.
  3. Similarly, the documentation explains that isEnabled() checks if an element is currently enabled or not, typically returning true for everything except disabled input elements.
  4. It is important to note that the function
    isElementFoundDisplayedEnabled(WebDriver driver, String accessor)
    may not cover whether a WebElement is actually clickable, leading to potential errors like
    org.openqa.selenium.WebDriverException: unknown error: Element is not clickable at point (781, 704). Other element would receive the click
    .
  5. When encountering the issue of
    Element is not clickable at point (781, 704)
    , resorting to using the JavascriptExecutor click method as mentioned by you can resolve the problem.
  6. To determine if an element is clickable, utilizing the WebDriverWait class with ExpectedConditions set to elementToBeClickable is recommended.
  7. Here is an example:

    WebDriverWait wait2 = new WebDriverWait(driver, 10);
    WebElement ele = wait2.until(ExpectedConditions.elementToBeClickable(By.id("element_id")));
    
  8. The documentation emphasizes that

    Element is Clickable - it is Displayed and Enabled

  9. A closer look at the elementToBeClickable() method clarifies that it returns

    the (same) WebElement once it is clickable (visible and enabled)

Therefore, the solution to your question lies in leveraging WebDriverWait or ExplicitWait

Answer №3

Before proceeding, it is crucial to identify the attribute that determines whether an element is hidden or visible. Once established, you can implement a function similar to this approach.

Consider the following example:

 <input id ="email" style="margin-top: 0px; visibility: visible;" >

Implementation:

public Boolean isVisibleAndClickable(WebElement email, WebDriver driver ){

    Boolean flag = false;
    try{
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(ExpectedConditions.elementToBeClickable(email));

        if(email.isDisplayed()){
            String style = email.getAttribute("style");
            if(style.contains("hidden")){
                System.out.println("Element is hidden");
            }
            else if(style.contains("visible")){
                System.out.println("Element is visible and clickable");
                flag = true;
            }else{
                System.out.println("Element is not displayed");
            }
         }
     } catch(Exception e){
         System.out.println("An exception occurred while waiting for the element"+e.getMessage());
     }

     return flag;
}

Answer №4

If you want to utilize the xpath contains function along with logic operators and ancestor option, you can do so by following a similar pattern:

.//a[@behavior.id='myid']/ancestor::div[contains(@class,'typeClass')]/.//span

This particular line locates the 'span' children within a 'div' based on the class filter, initiated by searching for the 'a' element with the specified behavior ID.

As for ensuring visibility, my preference is always to employ either the Wait or FluentWait options:

public static WebElement xpathVisible(String xpath) {
    return new FluentWait<WebDriver>(driver)
            .withTimeout(IMPLICIT_TIMEOUT, TimeUnit.SECONDS)
            .pollingEvery(RETRY_TIME, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class).until(ExpectedConditions
                    .elementToBeClickable(By.xpath(xpath)));
}

In some cases, it could also be beneficial to utilize certain capabilities of the driver such as elementScrollBehavior to navigate elements from the bottom instead of the top:

capabilities.setCapability("elementScrollBehavior", 1); // 0- from Top,
                                                            // 1 - from
                                                            // bottom

One method I found effective in the past involved:

  1. Identifying a nearby web element.
  2. Sending a specific shortcut like Keys.TAB or Keys.SHIFT+Keys.TAB.
  3. Verifying a property of the element to confirm correct positioning.
  4. Executing a Keys.Enter command.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to Align Paypal Button in the Middle of a Table Cell within a Concealed Form Using HTML and

Currently, I am in the process of developing a payment page that enables payments through Paypal using Instant Payment Notification. The initiation of this process involves sending a POST request to Paypal via a submit button along with multiple hidden for ...

"Is there a way to adjust the range slider to display currency instead of

I stumbled upon this amazing slider on codepen. Can someone guide me on how to adjust it to display a range from €500 to €6000 while keeping the vibrant red background? I've attempted various solutions like: <input id = "range" type = "range ...

I'm having trouble getting this button and icon to align properly. How can I fix this misalignment

Take a look at the HTML code snippet I'm currently working on... <div id="projects"> <H1 class="projects">PROJECTS</H1> <div class="box"></div> <div class="box"></div> <div class="box"></ ...

Adjust the height of each card dynamically based on the tallest card in the row

I am working on a row that looks like this: <div class="row"> <div class="col"> <div class="card"> <div class="card-body"> <h3 class="card-title ...

Leaving an open connection in Android SQLite

When working with a SQLiteDatabase instance, I often utilize getReadableDatabase() or getWritableDatabase() for data manipulation. However, I have noticed that I typically forget to close the database using db.close(). Is this a bad practice? I attempted ...

Tips for gathering data from a dynamic website

After pressing the green button labeled "View Details," a pop-up window appears displaying additional information. How can I extract the data from this pop-up window? I attempted to use Selenium to scrape the information after clicking but encountered an ...

What steps should I take to ensure that jQuery functions remain functional on loaded code?

I have implemented modals on all my pages except for the first one to save time. Here is the script that loads my modals: $(function () { $('#header').load('reusenavbar.php'); $('#loginModal').load('reuseloginmo ...

Ways to display or conceal information depending on the dropdown choice

In my Angular project, I am dealing with a dropdown menu that is followed by some data displayed in a div element. component.html <select class="form-control" id="power" required> <option value="" disabled selected ...

Planning an event that involves using an external webpage?

I was wondering how to automate the process of converting a list of web pages to PDF using an external webpage. The specific external webpage I am referring to is: This webpage has the capability to convert URLs of web pages into PDF files. Is there a P ...

Utilizing the '<' or '>' operator in combination with an if statement within a Repeater component

Is it possible to use an if statement in a repeater like this? <%#Eval("FN").ToString().Count > 0 ? "SB" : "" %> When I try to implement this, I receive an error 73 indicating that the > operator cannot be used. How can I adjust it so that i ...

Designing websites and Creating Visual Content

I have been working in IT for quite some time now, but recently I have started to delve more into web development. My main focus is on HTML 5, CSS 3, JavaScript, jQuery, and responsive design. However, one aspect that I always struggle with is images. I am ...

Is there a more efficient method for horizontally and vertically aligning in this particular scenario using HTML and CSS?

Embarking on my HTML/CSS journey, I am taking on the challenge of creating my very first website. Currently tackling the final CSS project for Codecademy. I've been tinkering with this task for what feels like an eternity and just can't seem to ...

Using Selenium class annotations in Java for Page Objects

Can you assist me with utilizing class(page) annotations in the Page Object pattern? For instance, I have a "Contacts" WebElement in both the upper menu and footer sections, using the same locator. I am aware that I can annotate Footer.class and UpperMenu. ...

Expanding the width of an image beyond its parent <div> without compromising on vertical space

Is it possible to have a child <img> wider than its parent div, while maintaining proportional width and preserving vertical space? Using position:absolute; might move the image out of the normal document flow, but I want to keep the vertical space ...

Eliminating gaps between elements

I recently delved into the world of web design, and although I have a basic understanding of HTML and CSS, I am determined to enhance my skills and knowledge by creating a standard home page. So far, I managed to create a standard navigation bar, and now ...

When executing Parallel Testing and encountering a java.lang.NullPointerException, it is recommended to invoke another

Encountering a challenge while running Parallel Tests using Java, Selenium, and TestNG. Two test methods are searching Google for different keywords, and I am looking to create a third method to avoid duplicating code. public class googleTestClass extends ...

Click on the menu item to save the image of the action

There is an activity in which I need to save the screen image to a specific folder on my device when the menu item "save" is clicked. How can I achieve this? The image displayed in the background is an ImageView and the text is a TextView. I need to merge ...

How to implement mouse hover functionality in C# using Selenium?

When attempting to mouse hover on a menu with multiple sub-menus, I encountered an issue where the suggested actions caused other menus to overlap and hide the intended element. Below is the recommended code snippet for hovering over the desired element: ...

The CSS scrollbar is visible on the screen, but for some reason,

I'm seeking a solution to enable scrolling within a div container that can scroll both horizontally and vertically. body { height: 100%; width: 100%; overflow: hidden; } .wrapper { width: 75%; padding: 0px 5px 0px 8px; top: 20px; whit ...

Establishing a connection to a MySQL database through the use of JPA and Spring, all without the

Currently, I am in the process of learning how to utilize Spring with JPA to establish a connection to a database. My goal is to avoid using persistence.xml and create an entity manager with minimal code. I attempted a solution found on this page () which ...