Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Protractor from finishing before promise has been resolved

Tags:

protractor

I have some async WebDriverJS processing that is being skipped because the test is completing before they are are being resolve. How do I get protractor to wait ?

e.g.: (both of these tests should fail (potential ticket submitted)

  it('test promise ', function (done) {
      var d = protractor.promise.defer();
      d.fulfill(true)
      d.promise.then(function (item) {
          console.log("fulfill", item);
      });
      expect(d.promise)
          .toBe(false);
      console.log("test done");
  });

  it('test promise with timeout ', function (done) {
      var d = protractor.promise.defer();
      setTimeout(function () {
          console.log("fulfill");
          d.fulfill(true)
      }, 3000);

      d.promise.then(function (item) {
          console.log("fulfill", item);
      });
      expect(d.promise)
          .toBe(false);
      console.log("test done");
  });

Let me know if you need more information ... ?

This will return true.. if you remove the timeout and just set fulfill it will work...

like image 658
Nix Avatar asked Mar 11 '14 16:03

Nix


3 Answers

Protractor side

The fix for this has been merged 11 days ago

You can have it working with createFlow but solution will be much simpler, just call done() after fulfill like this:

it('test promise with setTimeout ', function(done) {
  var d = protractor.promise.defer();
  setTimeout(function() {
    console.log("fulfill");
    d.fulfill('ok');
    done();
  }, 3000);
  expect(d).toBe('ok');
});

Currently on master branch so expect this to be shipped in protractor >= 0.23.0

Web app side (informative)

Protractor doesn't know how to wait for setTimeout

But does know how to wait for $timeout

like image 94
Leo Gallucci Avatar answered Nov 05 '22 03:11

Leo Gallucci


I couldn't get Nix's example to work and so I took Kato's suggestion and did the following:

describe('Tests stuff', function () {

    function do_work() {
        var d = protractor.promise.defer();
        protractor.promise.controlFlow().execute(function () {
            setTimeout(function () {
                console.log("fulfill");
                d.fulfill(true)
            }, 3000);
        });
        return d;
    }

    it('test promise with timeout ', function () {
        protractor.promise.controlFlow().wait(do_work).then(function (done) {
            console.log("test done:" + done);
        });
    });
});

The out put is as expected and the method waits correctly, and then follows the next flow. My output:

Started
fulfill
test done:true

I'm sure there's many other ways to get this to work, however this worked for me.

like image 29
PeterS Avatar answered Nov 05 '22 04:11

PeterS


I need someone to validate this is the correct way to do it.. but I believe the issue was the promise was not being added to the current control flow.

Solution:

it('test promise with timeout ', function (done) {
  var wait = protractor.promise.createFlow(function(flow){
      var d = protractor.promise.defer();
      flow.execute(function(){
          setTimeout(function () {
            console.log("fulfill");
            d.fulfill(true)
           }, 3000);
      });
  });

  expect(wait).toBe(false);
  console.log("test done");
 });
like image 1
Nix Avatar answered Nov 05 '22 03:11

Nix