Friday, August 18Be an Automation Engineer

How to implement fluent wait using explicit wait in protractor?

There are 3 types of waits available in selenium webdriver.

  1. implicit wait – Implicit wait is a global wait. Implicit wait is applicable to all the operations performed by driver.
  2. explicit wait – Explicit wait is a local wait and conditional. It waits for a condition specified with in the time limit provided.
  3. fluent wait – Fluent wait is also a local wait and conditional. Using fluent wait we can control the poll interval and can also suppress exceptions which we don’t want to be thrown.

In protractor we have implicit and explicit waits available by default. But fluent wait is not directly available. Now lets see how we can implement fluent wait using explicit wait in protractor.
In protractor browser.wait is used for explicit wait.

Let’s understand how explicit wait works so that we can easily implement fluent wait.

browser.wait(function(){
return element(by.id('identifier1')).isDisplayed();
}, 2*60*1000);

browser.wait waits for ‘true’ boolean value with in the time limit, that means if it receives true with in the time limit, it breaks out of it. Otherwise it throws WaitTimeOutError after the time limit. In this case 2 minutes is time out that we have set.

Why we need fluent wait if we already have explicit wait?

With core explicit wait we can not control the poll interval. If we want to search for an element for every 2 sec, we can not do it only with browser.wait

Now, let’s see how we can control the poll interval using fluent wait.

browser.wait(function () {
       return browser.wait(function () {
           return element(by.id('identifier1')).isDisplayed();
       }, 2 * 1000)
       .then(function () { return true; }, function (error) { return false; });
}, 20 * 1000);

In the above code we have used two browser.wait methods. The inner browser.wait is for polling interval(2*1000), which is 2 seconds in this case. In the inner browser.wait block we are catching exceptions and returning false(function (error) { return false; }. For outer block we have 20 sec timeout value (2 * 1000).

Problem with above code:
The above code is not exactly the way of implementing the fluent wait. Why because, with in the inner browser.wait block, we don’t have control over the poll interval. That means, with in 2 sec of inner wait, the element.display code may trigger many number of times.

Let’s see how we can avoid the above problem by using below code.

browser.manage().timeouts().implicitlyWait(0);
browser.wait(function () {
       browser.sleep(2000);
       return element(by.id('identifier1')).isDisplayed();
}, 20 * 1000);

Note: We need to set the implicit wait to zero to make sure that implicit wait timeout does not interfere with our polling interval.

In the above code we are making browser to wait for 2 sec for every iteration(poll). So we are controlling poll interval here.

Still there could be a possible chance of getting ‘NoSuchElementError’ instead of ‘WaitTimoutError’ with the above code if the expected element is there in the DOM. To avoid the failure with in time limit we need to catch the exception and return false to make it wait for specific time (20 sec) otherwise the exception will break the wait condition.

Now, Let us see how we can catch the exception and return false;

browser.manage().timeouts().implicitlyWait(0);
browser.wait(function () {
    browser.sleep(2000);
    return element(by.id('identifier1')).isDisplayed()
    .then(
        function (isDisplayed) { 
            return isDisplayed; 
        }, 
        function (error) { 
            return false 
        });
}, 20 * 1000);

In the above code, we are catching the possible errors of element.isDisplayed and returning false. So that the element.isDisplayed will be executed for every 2 seconds and then throws a ‘wait time out error’ if the element is not displayed with in 20 seconds.

Happy Testing!!!

%d bloggers like this: