From 0f2391f45dbf66b620e807cf5682c645d87fc019 Mon Sep 17 00:00:00 2001 From: Matt Ginzton Date: Tue, 9 Jun 2015 11:11:26 -0700 Subject: [PATCH] Ban mixing of promise and async APIs in `it` handler. If the `it` handler accepts a `done` argument, it is using the async API, and must not return a promise. Closes #1734. --- lib/runnable.js | 5 ++++- test/runnable.js | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/runnable.js b/lib/runnable.js index 399c18db10..127ae1d795 100644 --- a/lib/runnable.js +++ b/lib/runnable.js @@ -227,7 +227,7 @@ Runnable.prototype.run = function(fn){ this.resetTimeout(); try { - this.fn.call(ctx, function(err){ + var ret = this.fn.call(ctx, function(err){ if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); if (null != err) { if (Object.prototype.toString.call(err) === '[object Object]') { @@ -238,6 +238,9 @@ Runnable.prototype.run = function(fn){ } done(); }); + if (ret && typeof ret.then === 'function') { + done(new Error('runnable accepted "done" but returned promise')); + } } catch (err) { done(utils.getError(err)); } diff --git a/test/runnable.js b/test/runnable.js index 2508a5fa25..93f2968988 100644 --- a/test/runnable.js +++ b/test/runnable.js @@ -406,5 +406,18 @@ describe('Runnable(title, fn)', function(){ test.run(done); }) }) + + describe('when fn had a done argument and returns a promise', function(){ + it('should consider this an error', function(done){ + var test = new Runnable('foo', function(done){ + return { then: function(){} }; + }); + + test.run(function(err) { + err.should.be.ok; + done(); + }); + }) + }) }) })