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

uncaughtException: fix double EVENT_RUN_END events #4025

Merged
merged 2 commits into from
Sep 26, 2019
Merged
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
2 changes: 1 addition & 1 deletion lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@ Runner.prototype.uncaught = function(err) {
}

// bail
this.emit(constants.EVENT_RUN_END);
this.abort();
};

/**
Expand Down
8 changes: 4 additions & 4 deletions test/integration/fixtures/regression/issue-1327.fixture.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
'use strict';

// we cannot recover gracefully if a Runnable has already passed
// then fails asynchronously
it('test 1', function () {
console.log('testbody1');
process.nextTick(function () {
throw new Error('Too bad');
});
});

it('test 2', function () {
console.log('testbody2');
throw new Error('should not run - test 2');
});

it('test 3', function () {
console.log('testbody3');
throw new Error('OUCH');
throw new Error('should not run - test 3');
});
25 changes: 18 additions & 7 deletions test/integration/fixtures/uncaught-fatal.fixture.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
'use strict';

it('should bail if a successful test asynchronously fails', function(done) {
done();
process.nextTick(function () {
throw new Error('global error');
});
});
describe('fatal uncaught exception', function () {
describe('first suite', function () {
it('should bail if a successful test asynchronously fails', function (done) {
done();
process.nextTick(function () {
throw new Error('global error');
});
});

it('should not actually get run', function () {
it('should not actually get run', function () {
throw new Error('should never throw - first suite');
});
});

describe('second suite', function () {
it('should not actually get run', function () {
throw new Error('should never throw - second suite');
});
});
});
21 changes: 8 additions & 13 deletions test/integration/regression.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,17 @@ var run = require('./helpers').runMocha;
var runJSON = require('./helpers').runMochaJSON;

describe('regressions', function() {
it('issue-1327: should run all 3 specs exactly once', function(done) {
it('issue-1327: should run the first test and then bail', function(done) {
var args = [];
run('regression/issue-1327.fixture.js', args, function(err, res) {
var occurences = function(str) {
var pattern = new RegExp(str, 'g');
return (res.output.match(pattern) || []).length;
};

runJSON('regression/issue-1327.fixture.js', args, function(err, res) {
if (err) {
done(err);
return;
return done(err);
}
expect(res, 'to have failed');
expect(occurences('testbody1'), 'to be', 1);
expect(occurences('testbody2'), 'to be', 1);
expect(occurences('testbody3'), 'to be', 1);
expect(res, 'to have failed')
.and('to have passed test count', 1)
.and('to have failed test count', 1)
.and('to have passed test', 'test 1')
.and('to have failed test', 'test 1');
done();
});
});
Expand Down
21 changes: 7 additions & 14 deletions test/integration/uncaught.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,16 @@ describe('uncaught exceptions', function() {
it('handles uncaught exceptions from which Mocha cannot recover', function(done) {
run('uncaught-fatal.fixture.js', args, function(err, res) {
if (err) {
done(err);
return;
return done(err);
}
assert.strictEqual(res.stats.pending, 0);
assert.strictEqual(res.stats.passes, 1);
assert.strictEqual(res.stats.failures, 1);

assert.strictEqual(
res.failures[0].title,
'should bail if a successful test asynchronously fails'
);
assert.strictEqual(
res.passes[0].title,
'should bail if a successful test asynchronously fails'
);
var testName = 'should bail if a successful test asynchronously fails';
expect(res, 'to have failed')
.and('to have passed test count', 1)
.and('to have failed test count', 1)
.and('to have passed test', testName)
.and('to have failed test', testName);

assert.strictEqual(res.code, 1);
done();
});
});
Expand Down
5 changes: 3 additions & 2 deletions test/unit/runner.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -831,15 +831,16 @@ describe('Runner', function() {
]).and('was called once');
});

it('should notify run has ended', function() {
it('should abort the runner without emitting end event', function() {
expect(
function() {
runner.uncaught(err);
},
'to emit from',
'not to emit from',
runner,
'end'
);
expect(runner._abort, 'to be', true);
});
});

Expand Down