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). #1036

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
38 changes: 25 additions & 13 deletions lib/runnable.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,14 @@ Runnable.prototype.run = function(fn){

if (ctx) ctx.runnable(this);

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

// called multiple times
function multiple(err) {
Expand Down Expand Up @@ -179,12 +178,25 @@ Runnable.prototype.run = function(fn){
return;
}

// sync
// sync, or promise-returning
try {
if (!this.pending) this.fn.call(ctx);
this.duration = new Date - start;
fn();
if (!this.pending) {
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 @@ -205,5 +205,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);
})
})
})
})