Protractor - How to use async/await



  • I am completely new to protractor, and I came across the async/await.

    Using:

    • node version 8.9.4
    • protractor version 5.3.0. Is it necessary to use async/await in all your script? And how to use with page object.

    Here's the code I tried

    test1.js

        describe("first protractor test",function(){
        var originalTimeout;
        async beforeEach(function(){
             await browser.waitForAngularEnabled(false); //false to remove error for angular page not found
             await browser.get("https://54.75.182.9/ems",5000);     //34.22.196.20 another url
             originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
             jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
    
    });
    
    afterEach(function(){
    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
    });
    
    var home_page=require('./home_page.js');
    it("first test- login test",function(){
            home_page.enterUser();
            home_page.enterPwd();
            
            var transact=home_page.clickLoginfunction();  // that ref is used here
            transact.clickReport();
            transact.clickTransact();
            transact.selectOption();
            transact.clickSearch();
            transact.clickViewDetails();
            transact.getNGtext();
    });
    

    });

    
    <p><strong>transact.js</strong></p>
    <pre class="lang-js prettyprint-override"><code>     var transact_page= function(){
        
        //browser.pause();
        
        this.clickReport=function(){
        await  element(by.xpath("//a[contains(.,'Reports')]")).click();
        };
        
        this.clickTransact=function(){
            await element(by.xpath("//a[contains(.,'Transaction History')]")).click();
        };
        
        this.selectOption=function(){
            await element(by.model("searchTypeEntity")).$('[value="Contact"]').click();
        };
    
        this.clickSearch=function(){
            await element(by.id("searchTransBtn")).click();
        };
        
        this.clickViewDetails=function(){
            await element(by.xpath("//a[contains(.,'View Details')]")).click();
        };
        
        this.getNGtext=function(){
            return await element(by.model("val")).getText();
            
        
        };
        
        };  
        module.exports=new transact_page();
    
    
    
    
          **homepage.js** 
          require('./transact.js');  // mentioning beforehand
          var home_page=function(){
        
        this.enterUser=function(){
            await element(by.id("username")).sendKeys("admin");
        };
    
        this.enterPwd=function(){
            await element(by.id("password")).sendKeys("admin");
        };
        
        this.clickLoginfunction=function(){
            await element(by.id("login")).click();
            await browser.driver.sleep(10000);
            return require('./transact.js');  // this will return a ref to that particular page
        };
        
        };
          module.exports=new home_page // need this so that its object can be used in other classes eg. main 
    


  • Where to use async-await in Protractor scripts?

    Async/await statements are only required in places where promise resolution is occurring before moving to the next statement so yes, it is only required for asynchronous promise returning statements.

    Why use async-await in Protractor scripts?

    WebDriverJS (and thus, Protractor) APIs are entirely asynchronous. All functions return promises., which are managed by a control flow.

    Disabling the Control Flow

    In the future, the control flow is being removed. Instead of the control flow, we can synchronize the selenium commands with promise chaining or ES7 feature async-await.

    The latest Node.js provides native async/await, which means we can get the stable e2e test without using control flow in a javascript test.

    Note: To write and run native async/await test, the node.js version should be greater than or equal to 8.0, and Jasmine version should be greater than or equal to 2.7.

    Async-Await in Page Objects:

    The page object is just a design pattern to better structure automation whereas async await is a waiting mechanism for promises to be resolved and make javaScript code appear more synchronous without using '.then'.

    Code in Page object before Async-Await

     clickOnSelectCustomer: function () {
       browser.wait(EC.elementToBeClickable(customersTextBox), Medium_Wait()).then(function () {
          actions.Click(customersTextBox, 'Clicking on Customer Name Textbox')
        })
      },
    

    Code in Page object after Async-Await

        async clickOnSelectCustomer () {
         await browser.wait(EC.elementToBeClickable(customersTextBox), Medium_Wait())
         actions.Click(customersTextBox, 'Clicking on Customer Name Textbox')
       },
    

    Simpler Error-Handling

    If a promise resolves normally, then await promise returns the result. But in case of a rejection, it throws the error, just if there were a throw statement at that line.

    In real situations, the promise may take some time before it rejects. So await will wait, and then throw an error.

    We can catch that error using try..catch, the same way as a regular throw:

    async function f() {
    
      try {
        let response = await fetch('http://no-such-url');
      } catch(err) {
        alert(err); // TypeError: failed to fetch
      }
    }
    
    f();
    

    Without using '.then' and nested code,async-await make the code more linear which is easier to understand and write which in turn makes it easier to maintain as well.

    Protractor Official Documentation On Async/Await



Suggested Topics