Kyle
Kyle

Reputation: 1183

Resolve promise conditionally

I'm using the automated testing framework, Protractor.

I've come to find that Protractor frequently makes use of promises to asynchronously resolve code evaluation.

Question: How can I manually resolve a promise to a specific value, once a condition is met?


Update: 09/08/2017

Sorry, I was just a bit unclear on promises. I was able to get this working correctly now with:

// match variable
var match = false;

// get all elements with `div` tag
var scanElements = element.all(by.css('div')).each(function(el) {
    // get text content of element
    el.getText().then(function(text) {
        // split words into array based on (space) delimeter
        var sp = text.split(' ');
        for (var i = 0; i < sp.length; i++) {
            if (sp[i] == 'Stack Overflow') {
                match = true;
            }
        }
    });
});

// on complete
scanElements.then(function() {
    if (match) {
        console.log('Status: Found match!');
    }
    else {
        console.log('Status: No match');
    }
});

Upvotes: 1

Views: 413

Answers (3)

Xotabu4
Xotabu4

Reputation: 3091

In your exact example you can use .getText() on ElementArrayFinder -

// calling .getText() exactly on ElementArrayFinder returns promise
let hasStackOverflow = $$('div').getText().then(texts=> {
    // texts would be array of strings
    return texts.includes('Your Text exact match')
})

hasStackOverflow.then(has=> {
    if (has) {
        console.log('Status: Found match!');
    }
    else {
        console.log('Status: No match');
    }
})

Upvotes: 0

Shyam Babu
Shyam Babu

Reputation: 1079

There is no issue here according to the documentation the return type of element.all().each() is null after it iterates through everything.

A promise that will resolve when the function has been called on all the ElementFinders. The promise will resolve to null.

Edit 1: Is filter a valid option?

element.all(by.css('div'))
    .filter(function(element) {
       return element.getText().then(function(text) {
         var sp = text.split(' ');
         for ( var i =0; i< sp.length; i++) {
           if(sp[0] == 'protractor') return true;
         }
         return false;
       });
     }).first();

Will first filter and then return first element that matches

Upvotes: 1

FCin
FCin

Reputation: 3915

You should use map instead of each. If you look at the source code, this is how each is implemented:

each(fn: (elementFinder?: ElementFinder, index?: number) => any): wdpromise.Promise<any> {
  return this.map(fn).then((): any => {
    return null;
  });
}

So, as you can see it internally uses map and hides the result by returning null. It is also pointed out in the documentation.

Also rename element to something else just to avoid ambiguity with protractor's element object.

Upvotes: 1

Related Questions