Dealing synchronously in Protractor tests

2019-04-13 05:52发布

问题:

I'm trying to write what I think is a fairly simple test in protractor, but it would seem that the minute you try to do anything synchronously, Protractor makes life hard for you! Normally, dealing with locator functions (that return a promise) are not an issue, since any expect statement will automatically resolve any promise statement passed to it before testing the assertion. However, what I'm trying to do involves resolving these locator promises before the expect statement so that I can conditionally execute some test logic. Consider (pseudocode):

// Imagine I have a number of possible elements on the page
// and I wish to know which are on the page before continuing with a test.

forEach(elementImLookingFor){
  if (elementImLookingFor.isPresent) {
    // record the fact that the element is (or isnt) present
  }
}

// Now do something for the elements that were not found

However, in my above example, the 'isPresent' call returns a promise, so can't actually be called in that way. Calling it as a promise (i.e. with a then) means that my forEach block exits before I've recorded if the element is present on the page or not.

I'm drawing a blank about how to go about this, has anyone encountered something similar?

回答1:

I've used bluebird to do the following;

it('element should be present', function(done)
  Promise.cast(elementImLookingFor.isPresent)
    .then(function(present){
      expect(present).toBeTruthy();
    })
    .nodeify(done);
});

If you have a few elements that you want to check the isPresent on you should be able to do the following;

it('check all elements are present', function(done){
  var promises = [element1, element2].map(function(elm){
    return elm.isPresent();
  });

  // wait until all promises resolve
  Promise.all(promises)
    .then(function(presentValues){
      // check that all resolved values is true
      expect(presentValues.every(function(present){
        return present;
      })).toBeTruthy(); 

    })
    .nodeify(done);
});

Hope this helps



回答2:

So elementImLookingFor is a promise returned by element.all, I presume? Or, as stated in the Protractor documentation, an ElementArrayFinder. You can call the method .each() on it and pass it a function that expects things.