6

I am having some issues with the way the WebDriverWait and FluentWait is (not) working.

First of all, the requirement: Checking for the visibility of an validation error after submitting a login form.

So, I perform a successful login which leaves me at another page. To check if the login was fine I poll for the validation error which obviously is not there. To do that, I am checking the webelement that is supposed to contain the validation error message for it's visibility. Since it wont be there I am expecting a timeout or no such element exception.

I have tried it like this:

public static WebElement isVisible(By webElementLocator, WebDriver driver) {
    WebElement element = (new WebDriverWait(driver, 1))
                .ignoring(TimeoutException.class, NoSuchElementException.class)
                .until(ExpectedConditions.visibilityOfElementLocated(webElementLocator));
    return element;
}

I am ignoring timeouts and missing elements but get a timeout exception anyway. My question is: WHY?

I have a version of that method where I can pass a WebElement instead of an By-Locator. Looks like this:

public static WebElement isVisible(WebElement webElement, WebDriver driver) {
    WebElement element = (new WebDriverWait(driver, 2))
                .ignoring(TimeoutException.class, NoSuchElementException.class)
                .until(ExpectedConditions.visibilityOf(webElement));
    return element;
}

This, however, results in a longer wait of 20 seconds because (that is my guess) the implicit timeout set by the AjaxElementLocatorFactory I use to retrieve the Webelements overrides that wait instruction in the isVisible Method. This is very unexpected. Am I doing something wrong? This also raises a timeout exception which it should not.

//excerpt of a page object 
public class SomeLoginPage extends ABaseLoginPage {

...



@FindBy(css= "p.form-group.login-toggle > a > span")
    private WebElement loginToggleButton;
    @FindBy(className="login-center-form")
    private WebElement loginForm;
    @FindBy(css="div.alert.alert-danger > span")
    private WebElement loginValidationError;
    By ByloginValidationError = By.cssSelector("div.alert.alert-danger > span");

    public SomeLoginPage(WebDriver driver) {
        super(driver);
        AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(this.driver, 20);
        PageFactory.initElements(factory, this);
    }

    @Override
    public String getValidationErrorMessage() {
        String valErrMsg = "";
        WebElement valErr = DriverUtils.isVisible(ByloginValidationError, driver);
        if(valErr!=null) valErrMsg = valErr.getText();
        return valErrMsg;
    }
}

Am I missing something?

I know I could work around this issues by just catching the Exception the the utility method by that would defeat the purpose of the waiting concept in general. Furthermore I want to avoid try-catch blocks as much as possible.

4 Answers 4

3

FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition. It is not possible to ignore TimeoutException when FluentWait times out, as the concept become meaningless. This is how the API works.

2

Faster and more reliable way to find optionally present elements is find_elements() which returns a LIST of elements located, and this list is empty if none found. This method does NOT wait.

@PaulMuir: To make sure that form was successfully processed before checking for errors, I suggest to WAIT for element which ALWAYS appears on the form when submission was processed (so as soon as form was processed your program can continue), then find_elements() with error messages without waiting. Such steps of operation will be faster and less flaky.

3
  • 1
    I was going to make the same suggestion. My concern though is whether or not the element would exist at the time when the findElements is called. If it would not exist at that time then it would bring back a false negative/positive.
    – Paul Muir
    Jul 29, 2016 at 14:13
  • @PeterSmith after submission of the login for I am immediately forwarded to another page. So i definately have to deal with a timeout or missing element. The main question remains: Why are the exceptions thrown eventhough they are supposed to be ignored? Jul 30, 2016 at 11:16
  • I answered and checked the source-code of fluentWait for you to be 100% sure. You can't ignore the timeouts, period :) Feb 27, 2017 at 21:46
1

To check if the login was fine I poll for the validation error which obviously is not there

I would check for something that is obviously there. This is much easier and faster than waiting for something not to be there. After a login the page always changes. I haven't seen any application that does not display something that you cannot verify off that the login was successful.

After the successful login you can check the error message is not there with something like driver.findElements( By.id("...") ).size() != 0 or with a try/catch just like Selenium itself implements the isDisplayed(). Trying not to use try/catches has no good reason, just use it when needed.

Ignoring:

I think that you get the timeout error even when you are ignoring it because the wait works something like this:

  • While loop for ExpectedConditions (with a try/catch to ignore exceptions)
  • After this try/catch block there is an If the timeout has been met check which Throws the timeout exception

To be 100% sure I checked the FluentWait source-code as can you :). This effect makes a lot of sense, why would you want to continue after the timeout, trying to create an infinite loop?

1
  • I have the same scenario regarding why would you want to continue after the timeout, trying to create an infinite loop?. I have to verify weather text available or not using fluent wait because its depends on the response after submit click. So here use case is if text available within the time then print it . If not available (timeout after given time) then continue rest of things. Here i expect it will handle TimeoutException and i'll be able to execute rest of code but not like that it throws same exception. I'm also feeling it senseless because it doesn't ignore the exception.
    – NarendraR
    Aug 3, 2017 at 5:39
-1

I am writing code based on your requirement only. First of all, the requirement: Checking for the visibility of an validation error after submitting a login form.

public static void main(String[] args)
    {
    FirefoxDriver Driver=new FirefoxDriver();
    //Navigate to your login page
    WebDriverWait wait=new WebDriverWait(Driver, 30);
    wait.until(ExpectedConditions.titleIs("AssertXPath"));
    //Create objects for form fields and login button
    WebElement objUN=Driver.findElement(By.name("txtUserName"));
    WebElement objPWD=Driver.findElement(By.name("txtPassword"));
    WebElement objLogin=Driver.findElement(By.name("Submit"));
    WebElement objClear=Driver.findElement(By.name("clear"));
    if(objUN.equals("Username")
    {
      System.out.println("it's a Valid Username");
      return; // if username is mismatched throws an error
     }
    else
    {
      System.out.println("invalid Username"); 
    }
    if(objPWD.equals("Password")
    {
      System.out.println("Valid password");
      return; // if password is is mismatched throws an error
     }
    else
    {
      System.out.println("Wrong Password"); 
    }
    objLogin.click();
    Thread.sleep(2000);
      if(Brow.getTitle().equals("Enter the next page title"))
    {
        System.out.println("Login sucessfull & Home Page displayed");
    }
    else
    {
        System.out.println("Failed To Login");
        return;
    }
    Brow.close();
    Brow.quit();
    }
    }
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.