Skip to content

Commit

Permalink
Added a flag (-R, --rejections) to make the test fail if an unhandled…
Browse files Browse the repository at this point in the history
… Promise rejection happened during its execution (#658)

* Changed the npm scripts so they can be run in Windows (some tests keep failing though)

* Removed duplicate object key

* Added a flag (-R, --rejections) to make the test fail if an unhandled Promise rejection happened during its execution

* Added runner.js test case to cover the -R flag
  • Loading branch information
DanReyLop authored and geek committed Nov 7, 2016
1 parent 2849fb1 commit f1094c9
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 5 deletions.
10 changes: 8 additions & 2 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ internals.options = function () {
description: 'file pattern to use for locating tests',
default: null
},
rejections: {
alias: 'R',
type: 'boolean',
description: 'fail test on unhandled Promise rejections',
default: null
},
reporter: {
alias: 'r',
type: 'string',
Expand Down Expand Up @@ -343,7 +349,6 @@ internals.options = function () {
};

const defaults = {
verbose: false,
paths: ['test'],
coverage: false,
debug: false,
Expand All @@ -357,6 +362,7 @@ internals.options = function () {
'lint-errors-threshold': 0,
'lint-warnings-threshold': 0,
parallel: false,
rejections: false,
reporter: 'console',
shuffle: false,
silence: false,
Expand Down Expand Up @@ -390,7 +396,7 @@ internals.options = function () {
const keys = ['assert', 'colors', 'context-timeout', 'coverage', 'coverage-exclude',
'coverage-path', 'debug', 'dry', 'environment', 'flat', 'globals', 'grep',
'lint', 'lint-errors-threshold', 'lint-fix', 'lint-options', 'lint-warnings-threshold',
'linter', 'output', 'parallel', 'pattern', 'reporter', 'shuffle', 'silence',
'linter', 'output', 'parallel', 'pattern', 'rejections', 'reporter', 'shuffle', 'silence',
'silent-skips', 'sourcemaps', 'threshold', 'timeout', 'transform', 'verbose'];
for (let i = 0; i < keys.length; ++i) {
if (argv.hasOwnProperty(keys[i]) && argv[keys[i]] !== undefined && argv[keys[i]] !== null) {
Expand Down
17 changes: 17 additions & 0 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ internals.defaults = {
output: process.stdout, // Stream.Writable or string (filename)
parallel: false,
progress: 1,
rejections: false,
reporter: 'console',
shuffle: false,

Expand Down Expand Up @@ -517,6 +518,7 @@ internals.protect = function (item, state, callback) {
let isFirst = true;
let timeoutId;
let countBefore = -1;
let failedWithUnhandledRejection = false;

if (state.options.assert && state.options.assert.count) {
countBefore = state.options.assert.count();
Expand All @@ -531,6 +533,11 @@ internals.protect = function (item, state, callback) {
const finish = function (err, cause) {

clearTimeout(timeoutId);
setImmediate(() => process.removeListener('unhandledRejection', promiseRejectionHandler));
if (failedWithUnhandledRejection) {
return;
}

if (state.options.assert && state.options.assert.count) {
item.assertions = state.options.assert.count() - countBefore;
}
Expand Down Expand Up @@ -623,6 +630,16 @@ internals.protect = function (item, state, callback) {
domain.on('error', onError);
domains.push(domain);

const promiseRejectionHandler = function (reason) {

finish(reason, 'unhandledRejection');
failedWithUnhandledRejection = true;
};

if (state.options.rejections) {
process.on('unhandledRejection', promiseRejectionHandler);
}

setImmediate(() => {

domain.enter();
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
"lab": "./bin/lab"
},
"scripts": {
"test": "./bin/_lab -fL -t 100 -m 3000",
"test": "node ./bin/_lab -fL -t 100 -m 3000",
"posttest": "npm run lint-md",
"test-cov-html": "./bin/_lab -fL -r html -m 3000 -o coverage.html",
"lint": "./bin/_lab -d -f -L",
"test-cov-html": "node ./bin/_lab -fL -r html -m 3000 -o coverage.html",
"lint": "node ./bin/_lab -d -f -L",
"lint-md": "eslint --config hapi --rule 'strict: 0, eol-last: 0' --plugin markdown --ext md ."
},
"license": "BSD-3-Clause"
Expand Down
20 changes: 20 additions & 0 deletions test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -1019,4 +1019,24 @@ describe('CLI', () => {
done();
});
});

it('passes even with an unhandled Promise rejection in the code under test', (done) => {

RunCli(['test/cli_reject_promise/reject_promise.js'], (error, result) => {

expect(error).to.not.exist();
expect(result.code).to.equal(0);
done();
});
});

it('fails with an unhandled Promise rejection if the specified flag is set', (done) => {

RunCli(['test/cli_reject_promise/reject_promise.js', '-R'], (error, result) => {

expect(error).to.not.exist();
expect(result.code).to.equal(1);
done();
});
});
});
28 changes: 28 additions & 0 deletions test/cli_reject_promise/reject_promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

// Load modules

const Code = require('code');
const _Lab = require('../../test_runner');


// Declare internals

const internals = {};


// Test shortcuts

const lab = exports.lab = _Lab.script();
const describe = lab.describe;
const it = lab.it;
const expect = Code.expect;


describe('Test Promises', () => {

it('handles a Promise rejection', ( done ) => {
Promise.reject(new Error('Rejection!'));
done();
});
});
20 changes: 20 additions & 0 deletions test/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -1824,4 +1824,24 @@ describe('Runner', () => {
});
});
});

it('fails with an unhandled Promise rejection if the specified flag is set', (done) => {

const script = Lab.script();
script.test('handles a Promise rejection', (done) => {

Promise.reject(new Error('Rejection!'));
setImmediate(done);
});

Lab.execute(script, { rejections: true }, null, (err, notebook) => {

expect(err).not.to.exist();
expect(notebook.tests).to.have.length(1);
expect(notebook.failures).to.equal(1);
expect(notebook.tests[0].err.toString()).to.contain('Rejection!');
done();
});

});
});

0 comments on commit f1094c9

Please sign in to comment.