Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding promise support to runnables (and thus tests). #329

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions lib/runnable.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,15 @@ Runnable.prototype.run = function(fn){
, finished
, emitted;

// timeout
// timeout: set the timer even if this.async isn't true, since we don't know
// ahead of time for the promisey case
if (this.async) {
if (ms) {
this.timer = setTimeout(function(){
this.timer = setTimeout(function(){
if (!finished) {
done(new Error('timeout of ' + ms + 'ms exceeded'));
self.timedOut = true;
}, ms);
}
}
}, ms);
}

// called multiple times
Expand Down Expand Up @@ -152,11 +153,25 @@ Runnable.prototype.run = function(fn){
}

// sync
var result;
try {
if (!this.pending) this.fn.call(ctx);
this.duration = new Date - start;
fn();
if (!this.pending) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this part would be a lot nicer if we did something like toCallback(result) below, lots of nested conditionals are really confusing to read

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm will give it a shot at factoring it out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like?

  function toCallback(result) {
    if (result && typeof result.then === 'function') {
      result.then(
        function(){
          done();
        },
        done
      );
    } else {
      done();
    }
  }

  // sync
  try {
    if (!this.pending) {
      toCallback(this.fn.call(ctx));
    } else {
      done();
    }
  } catch (err) {
    done(err);
  }

var result = this.fn.call(ctx);

if (result && typeof result.then === "function") {
result.then(
function(){
done(); // don't pass through any non-error fulfillment values
},
done // pass through any errors
);
} else {
done();
}
} else {
done();
}
} catch (err) {
fn(err);
done(err);
}
};
67 changes: 67 additions & 0 deletions test/runnable.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,5 +176,72 @@ describe('Runnable(title, fn)', function(){
})
})

describe('when fn returns a promise', function(){
describe('when the promise is fulfilled with no value', function(){
var fulfilledPromise = {
then: function (fulfilled, rejected) {
process.nextTick(fulfilled);
}
};

it('should invoke the callback', function(done){
var test = new Runnable('foo', function(){
return fulfilledPromise;
});

test.run(done);
})
})

describe('when the promise is fulfilled with a value', function(){
var fulfilledPromise = {
then: function (fulfilled, rejected) {
process.nextTick(function () {
fulfilled({});
});
}
};

it('should invoke the callback', function(done){
var test = new Runnable('foo', function(){
return fulfilledPromise;
});

test.run(done);
})
})

describe('when the promise is rejected', function(){
var expectedErr = new Error('fail');
var rejectedPromise = {
then: function (fulfilled, rejected) {
process.nextTick(function () {
rejected(expectedErr);
});
}
};

it('should invoke the callback', function(done){
var test = new Runnable('foo', function(){
return rejectedPromise;
});

test.run(function(err){
err.should.equal(expectedErr);
done();
});
})
})
})

describe('when fn returns a non-promise', function(){
it('should invoke the callback', function(done){
var test = new Runnable('foo', function(){
return { then: "i ran my tests" };
});

test.run(done);
})
})
})
})