1

Sources: Selenium WebDriver, Chrome 73V, ChromeDriver, Java , testNG, CRM application , Eclipse

I am working on web application which is kind of CRM, loaded with tons of UI elements. One test case works today and fail tomorrow. FYI, I used fluent wait for my test cases.

I checked all the xpaths and they are good. On top of this I executed with Debug mode and tests are passing on debug mode. They are randomly flaky and un-stable , I am not sure what to do to make them stable? I don't want to use thread.sleep , off course.

Below code (just for the idea) I used to click few elements of the page , sometime Action class works sometime doesn't and sometime Click function works sometime doesn't, not sure how to handle such weird scenario?

driver.findElement(By.name("submit")).sendKeys(Keys.ENTER);

OR

driver.findElement(By.name("submit")).sendKeys(Keys.RETURN);

OR

driver.findElement(By.name("submit")).click();

OR

WebElement webElement = driver.findElement(By.id("Your ID Here"));
Actions builder = new Actions(driver);
builder.moveToElement(webElement).click(webElement);
builder.perform();

OR

WebElement webElement = driver.findElement(By.id("Your ID here"));
JavascriptExecutor executor = (JavascriptExecutor) driver;
executor.executeScript("arguments[0].click();", webElement);

Thanks for your comments, Please see below, this is my fluent wait:

  public static boolean waitForElementToBeVisibleOrClickable (WebDriver driver, WebElement element) {

    boolean webElement = false;

    try {
        driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
        wait = new WebDriverWait(driver, 30)
                .ignoring(NoSuchElementException.class, 
        StaleElementReferenceException.class)
                .pollingEvery(200);
        wait.until(ExpectedConditions.visibilityOf(element));
        **OR** 
        wait.until(ExpectedConditions.elementToBeClickable(element));
        Log.info("Element is visible");
        webElement = true;
    } catch (Exception e) {
        Log.error("Element is not visible");
        webElement = false;
    } finally {
        driver.manage().timeouts().implicitlyWait(45, TimeUnit.SECONDS);
    }
    return webElement;
}
Mike ASP
  • 2,013
  • 2
  • 17
  • 24
  • If the tests always pass in debug it's a timing issue. Post the the code you are using to wait for the element before clicking on it. – Guy Sep 05 '19 at 05:17
  • most probably some sync issue. Make sure you're waiting for the element to be clickable. – yudi2312 Sep 05 '19 at 05:30
  • please see my edited code above, thanks again. – Mike ASP Sep 05 '19 at 05:58
  • @MikeASP is this Oracle CRM (most probably Oracle Fusion) application or Salesforce CRM? Just trying to understand more since I too have faced such issues in both Oracle and Salesforce CRM automation. – Sachin Ramdhan Boob Sep 05 '19 at 13:48
  • @SachinRamdhanBoob yes u r right, I will not be that explicit here but you got the idea. thanks , Please let me know if you have any work around. – Mike ASP Sep 05 '19 at 15:22
  • Part 1 - @MikeASP Unfortunately I could not find any elegant way to this issue. I created custom expected conditions classes to perform each operation - click, input text etc... Each expected condition class would keep trying the operation until it does not succeed (used ignore exceptions just like you did, I in fact ignored the super class in Selenium exception - WebDriverException) After all this, I still faced issue where - even if click function is pass without exception, the element actually did not undergo click !! – Sachin Ramdhan Boob Sep 06 '19 at 13:13
  • Part 2 - @MikeASP For such cases, I created a method that performs click on element1 and then verifies element2 presence/visibility to prove that element1 was successfully clicked. If not, then it will repeat the operation on element1 in loop with some threshold value... With all this extra code, I could reduce the Thread.sleep() usage but could not completely eliminate. As per my observation, these applications do lot of on-the-fly changes in their UI elements using javascript libraries, which is causing this instability. – Sachin Ramdhan Boob Sep 06 '19 at 13:22
  • @MikeASP I observed that many elements have a fancy wrapper element (but they are non standard html elements). For example – Sachin Ramdhan Boob Oct 08 '21 at 18:06

2 Answers2

1

You defined method to wait, but you don't actually use it. You are locating the element using driver and immediately click it. You should also modify the wait to use it while locating the element, not afterwards

public WebElement waitForElement(By by) {
    return wait.until(ExpectedConditions.visibilityOfElementLocated(by));
}

waitForElement(By.name("submit")).click();
Guy
  • 46,488
  • 10
  • 44
  • 88
  • No man, you missed the point. I clearly mentiioned '(just for the idea)' , I am doing like this for my actual step: if (waitForElementToBeVisible(driver, webElement)) { if (webElement != null) { logger.info("WebElement " + webElement + " is not Null visible on the Page."); waitForElementToBeClickable(driver, webElement); logger.info("WebElement " + webElement + " is Clickable on the Page."); TestExtentLog.loggerInfo(pageClassWebElement, "Clickable"); webElement.click(); } – Mike ASP Sep 05 '19 at 15:17
0

You need to take care of the couple of things:

You can find a relevant discussion in How to click a hyperlink without any link text

  • If the element is within a <form> tag, as an alternative you can use the submit() method.

You can find a detailed discussion in Selenium: submit() works fine, but click() does not

  • As per the documentation, Do not mix implicit and explicit waits! Doing so can cause unpredictable wait times. For example, setting an implicit wait of 10 seconds and an explicit wait of 15 seconds could cause a timeout to occur after 20 seconds.

You can find a detailed discussion in How to properly configure Implicit / Explicit Waits and pageLoadTimeout through Selenium?


Solution

Instead of using fluent wait you can induce WebDriverWait in conjunction with ExpectedConditions and an optimized code block will be:

public static boolean waitForElementToBeVisibleOrClickable (WebDriver driver, WebElement element) {

    try {
            driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
            new WebDriverWait(driver, 30).until(ExpectedConditions.elementToBeClickable(element));
            System.out.println("Element is clickable now");
    } catch (TimeoutException e) {
            System.out.println("Element isn't clickable");
    } finally {
            driver.manage().timeouts().implicitlyWait(45, TimeUnit.SECONDS);
    }
    return element;
}
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Sir, you did not observe my above code I am using this only - wait.until(ExpectedConditions.elementToBeClickable(element)); thanks for your comment. – Mike ASP Sep 05 '19 at 15:20
  • @MikeASP It's difficult to construct a canonical answer without the relevant HTML and error stack trace. However I took an honest attempt to answer your question folloing your code attempts and provided the relevant references. I would be curious to know what happens when you use the code block in place of yours :) – undetected Selenium Sep 05 '19 at 15:29
  • @ DebanjanB - I appreciate your reply man. It's CRM app which is not able to flush out Stale elements on time. – Mike ASP Sep 08 '19 at 21:21
  • @MikeASP I still think _fluent wait_ is not the solution you are looking at but you want to handle the _stale elements_ which can can be done through simple _WebDriverWait_. I just tried to answer your question preserving your innovation. – undetected Selenium Sep 08 '19 at 21:26