user3738928
user3738928

Reputation: 23

Passing Protractor ElementFinder to deferred.fulfill() results in a promise containing a null value

I am calling deferred.fulfill() with a Protractor elementfinder as a parameter. When placing a breakpoint on the fulfill I can see that the elementfinder "solutionElement" is not null. The promise is resolved and my "then" callback is executed. However the value of "myElement" in the callback is null.

If I don't pass the elementfinder to the fulfill and instead use some other value(i.e. the "cnt" var) the "myElement" variable resolves to the actual value of "cnt".

I'm wondering if the issue is related to the fact that my fulfill call is within a then callback, but I don't understand for sure.

Any help/advice would be appreciated. Thank You

it('Should select when clicked',function() {
      sb.getSolutionElementIndexByName("test").then(function(myElement) {
         myElement.click();
      });
});



SbPageObject.prototype.getSolutionElementIndexByName = function(name){
    var deferred = protractor.promise.defer();
    var cnt = 0;
    var notFulFilled = true;
    var allSolutions = this.allSolutions;

    allSolutions.count().then(function(solCnt){
        allSolutions.each(function (solutionElement) {
            solutionElement.element(by.className("sb-solution-name")).getText().
                then(function (solutionText) {

                    if (solutionText === name) {
                        console.log("*****Fullfiled");
                        deferred.fulfill(solutionElement);
                        notFulFilled = false;
                    }
                    //if this is the last element and it's still not a match, reject promise
                    else if (cnt + 1 == solCnt){
                        deferred.reject(new Error ("Solution " + name + " was not found."));
                    }
                    cnt++;
                });
        });
    });
    return deferred.promise;
};

Upvotes: 2

Views: 3067

Answers (1)

Andres D
Andres D

Reputation: 8900

I usually use the map, filter, action/assert pattern. It looks something like this:

element.all(locator).map(function(elm, index) {
  // Get the value you are interested in finding and return the element too.
  return {
    elm: elm,
    text: elm.getText(),
    index: index
  };
}).then(function(list) {
  // Find your text here. Otherwise fail.
  for(var i = 0; i<list.length; i++) {
    if(list[i].text === name) {
      return list[i].elm;
    }
  }
  throw new Error('Solution not found');
}).then(function(elm) {
  // Perform an action on the element you found.
  elm.click();
});

Map will fully resolve all the promises before the results are passed to the next then in the chain.

Upvotes: 4

Related Questions