From 367fb9f0489487eaf98b9c952d2b47c3c6f06efc Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Fri, 22 Aug 2014 19:08:40 -0400 Subject: [PATCH] Fail when test resolution method is overspecified Users may register `Runnable`s as asynchronous in one of two ways: - Via callback (by defining the body function to have an arity of one) - Via promise (by returning a Promise object from the body function) When both a callback function is specified *and* a Promise object is returned, the `Runnable`'s resolution condition is ambiguous. Practically speaking, users are most likely to make this mistake as they transition between asynchronous styles. Currently, Mocha silently prefers the callback amd ignores the Promise object. Update the implementation of the `Runnable` class to fail immediately when the test resolution method is over-specified in this way. --- lib/runnable.js | 9 +++++++-- test/acceptance/overspecified-async.js | 8 ++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 test/acceptance/overspecified-async.js diff --git a/lib/runnable.js b/lib/runnable.js index 26962935bf..d5be6b8a7f 100644 --- a/lib/runnable.js +++ b/lib/runnable.js @@ -181,7 +181,8 @@ Runnable.prototype.run = function(fn){ , start = new Date , ctx = this.ctx , finished - , emitted; + , emitted + , result; // Some times the ctx exists but it is not runnable if (ctx && ctx.runnable) ctx.runnable(this); @@ -213,7 +214,7 @@ Runnable.prototype.run = function(fn){ this.resetTimeout(); try { - this.fn.call(ctx, function(err){ + result = 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]') { @@ -224,6 +225,10 @@ Runnable.prototype.run = function(fn){ } done(); }); + + if (result && typeof result.then === 'function') { + return done(new Error('Asynchronous resolution method is overspecified. Specify a callback *or* return a Promise, not both.')); + } } catch (err) { done(err); } diff --git a/test/acceptance/overspecified-async.js b/test/acceptance/overspecified-async.js new file mode 100644 index 0000000000..2844920379 --- /dev/null +++ b/test/acceptance/overspecified-async.js @@ -0,0 +1,8 @@ +describe('overspecified asynchronous resolution method', function() { + it('should fail when multiple methods are used', function(done) { + setTimeout(done, 0); + + // uncomment + // return { then: function() {} }; + }); +});