ashish chauhan
ashish chauhan

Reputation: 385

How promises are getting resolved in Protractor?

I have a doubt, it is written that : Finding web elements is asynchronous, whether it’s a single element or a collection, so the result is a promise. So if this is the case , the how below code snippet is working:

describe('the contact list', () => {
 it('with filter: should find existing ' +
 'contact "Craig Service"', () => {
   let tbody = element(by.tagName('tbody'));
   let trs = tbody.all(by.tagName('tr'));
   let craigService = trs.filter(elem => {
   return elem.all(by.tagName('td')).get(1).getText()
     .then(text => {
       return text === 'Craig Service';
     });
   });

Isn't trs needs to be resolved using then().. ,before we are moving to the next line where we are using filter function( craigService)? If that is being handled by Protractor promise -manager, can we use the same strategy for getting the text of an element using gettext()..and later using it without using then()..?

Upvotes: 2

Views: 72

Answers (1)

Sergey Pleshakov
Sergey Pleshakov

Reputation: 8948

If that is being handled by Protractor promise -manager

Protractor promise manager (AKA SELENIUM_PROMISE_MANAGER) is removed starting from protractor 6. So forget about it

Finding web elements is asynchronous

In my own words, finding web elements with a purpose of manipulating with it (click(), getText() etc) is asynchronous and thus returns a Promise, which need to be resolved. However what you have on this line

let trs = tbody.all(by.tagName('tr'));

is just an elementArrayFinder declaration. It doesn't return promise, and thus it has a synchronous nature. So you can declare this element, long time before you even open a browser

If you intend to work with protractor a lot, bookmark this protractor API page. On this page, they say what every command returns. If that does not have promise.Promise or something like that, it doesn't need to be resolved (exception is browser.get which I happen to know is a promise too, but they don't mention that)

Answering your quesion

Isn't trs needs to be resolved

As per protractor page element() doesn't return a Promise, as well as element.all() so NO, they don't need to be resolved

Now when you know how to find out if you work with promises or not, lets talk how to resolve Promises

  1. Good old .then() syntax (not really good, but old indeed)
element(by.css('.class')).getText().then(function(text){
  console.log(text)
})

Now when you know this method, erase that from your memory. This is extra information which will make your code not readable and extremely hard to debug. Just look at this Promise Hell and you'll understand what I'm talking about

  1. async/await This is as good as copy/paste on your computer. God bless creators of both, I can't imagine my life without them. So the same code from #1 now looks like this
let text = await element(by.css('.class')).getText();
console.log(text)

Doesn't it make a lot more sense when you look at the snippet? For another example see this thread. Basically await says to javascript 'stop, resolve promise, return it's value'

To summarize, if you resolve your snippet's promises with async/await you'll get

describe('the contact list', () => {
  it('with filter: should find existing contact "Craig Service"', async () => { // pay attention to this async
    let tbody = element(by.tagName('tbody'));
    let trs = tbody.all(by.tagName('tr'));
    let craigService = await trs.filter(async elem => { // async again
      let text = await elem.all(by.tagName('td')).get(1).getText()
      return text === 'Craig Service'
    });

Upvotes: 1

Related Questions