0

Hey All I have an issue that I am facing. I want to create a method that will get element id, and wait until it will be clickable. (the issue is since the element is intercepted, I do not want to user wait clickable). the issue is that the element is seen after a while and clickable after another. I printed to consul the times of pulling and saw it is not printed, meaning it not event once try to pull.

public static void waitForElementSeenAndClick (String elementId)
    {

        WebDriver driver2 = WebDriverMgr.getDriver();

        Wait wait = new FluentWait(driver2)
                .withTimeout(FLUENT_WAIT_MAX, TimeUnit.SECONDS)
                .pollingEvery(FLUENT_WAIT_PULLING, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class,
                        Exception.class);

        wait.until(new Function<WebDriver , Boolean>() {
            public Boolean apply (WebDriver driver2) {

                WebElement element = driver2.findElement(By.id(elementId));
                System.out.println("Try to click_1");
                element.click();
                if(element.isDisplayed()) {
                    System.out.println("Try to click_2");
                    element.click();
                    return true;
                }
                System.out.println("Try to click_3");
                return  false;
            }

        });
    }

This is what I get from consul (The id is: "header-account-logout" )

ERROR: no such element: Unable to locate element: {"method":"css selector","selector":"#header\-account\-logout"}
  (Session info: chrome=77.0.3865.120)
For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/no_such_element.html
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'

Try to click 1 not printed at all Try to click 2 not printed at all Try to click 3 not printed at all Its not entered to the loop and not try to pull

JeffC
  • 22,180
  • 5
  • 32
  • 55
Bastian
  • 1,089
  • 7
  • 25
  • 74

2 Answers2

0

Below is the way I handle this situation in projects. I wait for clickable using ExpectedConditions which is nice and clean. (FluentWait isn't needed in most cases, it just requires more inputs). The wait and click is inside of a try-catch so that we can catch WebDriverException which is when Selenium attempts to click an element but another element is in the way, as you are seeing. If this happens, we just loop again and try the click until the timeout specified. I've also added in StaleElementReferenceException because I find it helpful.

public static void click(By locator, int timeOut)
{
    WebDriver driver = WebDriverMgr.getDriver();
    Instant now = Instant.now();
    while (Instant.now().isBefore(now.plusSeconds(timeOut)))
    {
        try
        {
            new WebDriverWait(driver, timeOut).until(ExpectedConditions.elementToBeClickable(locator)).click();

            return;
        }
        catch (WebDriverException e)
        {
            // do nothing, loop again
        }
    }

    throw new Exception("Not able to click element <" + locator + "> within " + timeOut + "s.");
}

Instant Java docs

Note 1: Don't pass in just the ID as a String. When you do that, you can only use that method for locators with IDs... then you have to write a different method for CSS selectors, one for XPath, and so on. Instead, just pass in a By class and you can write one method that handles ALL locator types. You would call it like

click(By.id("..."));

Note: I don't have an IDE right now so this should be close, at least enough to get you headed in the right direction.

JeffC
  • 22,180
  • 5
  • 32
  • 55
  • Thanks I copied your code I have only to issues in the IDE: in the WebDriverException - > Identifier expected in the StaleElementReferenceException -> Identifier expcted and in throw new Exception("Not able to click element <" + locator + "> within " + timeOut + "s."); -> Unhandled exception – Bastian Oct 24 '19 at 10:45
  • Try now. I put this code into my IDE and fixed up some issues. I've removed the stale element exception catch because it will be caught by the more general `WebDriverException`. (The separation makes sense in C# where I first wrote this). – JeffC Oct 24 '19 at 13:19
  • Sorry still not work, It is not waiting for a second. and not know why, I currently have in code 19 waiting functions, for each page unique wait since selenium sometime wait and sometime not. for each page selenium acts differently – Bastian Oct 27 '19 at 09:51
0

Add to the .ignoring of the Fluent WebDriverException.class, it will catch any type of WebDriver exceptions and therefore the fluent wait mechanism will affect also the element locating exception.

ValorHeart
  • 35
  • 6