diff --git a/lib/runner.js b/lib/runner.js index e65cffdd1b..d896e1b9ae 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -25,6 +25,7 @@ module.exports = Runner; * - `suite` (suite) test suite execution started * - `suite end` (suite) all tests (and sub-suites) have finished * - `test` (test) test execution started + * - `test verify` (test) test body complete but status not yet decided * - `test end` (test) test completed * - `hook` (hook) hook execution started * - `hook end` (hook) hook complete @@ -262,16 +263,26 @@ Runner.prototype.parents = function(){ Runner.prototype.runTest = function(fn){ var test = this.test - , self = this; + , self = this + , continue_fn; + + continue_fn = function(test_err) { + try { + self.emit('test verify'); + } catch (e) { + if(!test_err) test_err = e; + } + fn(test_err); + }; try { test.ctx.test(test); test.on('error', function(err){ self.fail(test, err); }); - test.run(fn); + test.run(continue_fn); } catch (err) { - fn(err); + continue_fn(err); } }; diff --git a/test/runner.js b/test/runner.js index 20a0afb812..946d734628 100644 --- a/test/runner.js +++ b/test/runner.js @@ -23,6 +23,64 @@ describe('Runner', function(){ }) }) + describe('.runTest()', function(){ + // make a test-like object that runs the given function + var make_test = function(fn) { + return { + ctx: {test: function() {} }, + run: fn, + on: function() {} + }; + }; + + it('should call the "test verify" hook on success', function(done){ + var test = make_test(function(done) { done(); }); + var called = false; + runner.test = test; + runner.on('test verify', function() { called = true; }); + runner.runTest(function(e) { + (e == undefined).should.be.true; // should.not.exist(e) doesn't seem to work? + called.should.be.true; + done(); + }); + }); + + it('should call the "test verify" hook on failure', function(done) { + var test = make_test(function(done) { throw new Error("boo!"); }); + var called = false; + runner.test = test; + runner.on('test verify', function() { called = true; }); + runner.runTest(function(e) { + e.message.should.equal("boo!"); + called.should.be.true; + done(); + }); + }); + + it('should allow "test verify" to fail the test', function(done) { + var test = make_test(function(done) { done(); }); + var called = false; + runner.test = test; + runner.on('test verify', function() { throw new Error("verify failure");}); + runner.runTest(function(e) { + e.message.should.equal("verify failure"); + done(); + }); + }); + + it('should not allow "test verify" to shadow the reason for a failed test', function(done) { + var test = make_test(function(done) { throw new Error("test failure"); }); + var called = false; + runner.test = test; + runner.on('test verify', function() { called = true; throw new Error("verify failure");}); + runner.runTest(function(e) { + e.message.should.equal("test failure"); + called.should.be.true; + done(); + }); + }); + }) + describe('.checkGlobals(test)', function(){ it('should emit "fail" when a new global is introduced', function(done){ runner.checkGlobals();