diff --git a/lib/runner.js b/lib/runner.js index ba4d7df97c..a2f5ea3696 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -532,7 +532,10 @@ Runner.prototype.runTests = function(suite, fn) { if (err instanceof Pending) { test.pending = true; self.emit('pending', test); - } else if (retry < test.retries()) { + return next(); + } + + if (retry < test.retries()) { var clonedTest = test.clone(); clonedTest.currentRetry(retry + 1); tests.unshift(clonedTest); @@ -540,22 +543,22 @@ Runner.prototype.runTests = function(suite, fn) { // Early return + hook trigger so that it doesn't // increment the count wrong return self.hookUp('afterEach', next); - } else { - self.fail(test, err); } - self.emit('test end', test); - if (err instanceof Pending) { - return next(); - } - - return self.hookUp('afterEach', next); + self.fail(test, err); + } else { + test.state = 'passed'; } - - test.state = 'passed'; - self.emit('pass', test); - self.emit('test end', test); - self.hookUp('afterEach', next); + // Run the actual emit that the test passed after the forEach hooks, + // so they can still fail a test. And it's not already reported as + // passed. + self.hookUp('afterEach', function() { + if (test.state === 'passed') { + self.emit('pass', test); + } + self.emit('test end', test); + next(); + }); }); }); } diff --git a/test/integration/fixtures/hooks/afterEach.hook.error.js b/test/integration/fixtures/hooks/afterEach.hook.error.js index 9d28632fa3..83b37f5f1c 100644 --- a/test/integration/fixtures/hooks/afterEach.hook.error.js +++ b/test/integration/fixtures/hooks/afterEach.hook.error.js @@ -6,7 +6,7 @@ describe('spec 1', function () { it('should be called because error is in after each hook', function () { console.log('test 1'); }); - it('should not be called', function () { + it('should be called because error is in after each hook', function () { console.log('test 2'); }); }); diff --git a/test/integration/fixtures/hooks/afterEach.hook.failure.js b/test/integration/fixtures/hooks/afterEach.hook.failure.js new file mode 100644 index 0000000000..408e1ad9e1 --- /dev/null +++ b/test/integration/fixtures/hooks/afterEach.hook.failure.js @@ -0,0 +1,16 @@ +describe('spec 1', function () { + afterEach(function () { + this.test.error(new Error('something went wrong')); + }); + it('should be set to failure in the afterEach', function () { + console.log('test 1'); + }); + it('should be set to failure in the afterEach', function () { + console.log('test 2'); + }); +}); +describe('spec 2', function () { + it('should succeed', function () { + console.log('test 3'); + }); +}); diff --git a/test/integration/hook.err.js b/test/integration/hook.err.js index ca1a8fe1bb..46acc6e5aa 100644 --- a/test/integration/hook.err.js +++ b/test/integration/hook.err.js @@ -51,7 +51,7 @@ describe('hook error handling', function() { it('should verify results', function() { assert.deepEqual( lines, - ['test 1', 'after', 'test 3'] + ['test 1', 'after', 'test 2', 'after', 'test 3'] ); }); }); @@ -77,8 +77,11 @@ describe('hook error handling', function() { '1.2 before each', '1.2 test 1', '1.2 after each', - '1 after each', - 'root after each', + 'root before each', + '1 before each', + '1.2 before each', + '1.2 test 2', + '1.2 after each', '1.2 after', '1 after', '2.1 before', diff --git a/test/integration/hooks.js b/test/integration/hooks.js index 4236c7f82d..376e536bcf 100644 --- a/test/integration/hooks.js +++ b/test/integration/hooks.js @@ -41,4 +41,21 @@ describe('hooks', function() { done(); }); }); + + describe('afterEach sets tests to fail', function() { + var res; + before(function(done) { + run('hooks/afterEach.hook.failure.js', args, function(err, result) { + res = result; + done(err); + }); + }); + + it('afterEach can set a test to fail', function() { + assert.equal(res.pending, 0); + assert.equal(res.passing, 1); + assert.equal(res.failing, 2); + assert.equal(res.code, 2); + }); + }); }); diff --git a/test/integration/multiple.done.js b/test/integration/multiple.done.js index 8bcedf6332..ae86ea2478 100644 --- a/test/integration/multiple.done.js +++ b/test/integration/multiple.done.js @@ -16,7 +16,7 @@ describe('multiple calls to done()', function() { it('results in failures', function() { assert.equal(res.stats.pending, 0); - assert.equal(res.stats.passes, 1); + assert.equal(res.stats.passes, 0); assert.equal(res.stats.failures, 1); assert.equal(res.code, 1); });