diff --git a/gulpfile.js b/gulpfile.js index a0d08c9..345881a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -65,7 +65,7 @@ gulp.task('release', ['bump'], function (done) { done() return } - var pkg = require('./package.json') + var pkg = require('./package') var version = 'v' + pkg.version var releaseType = getBumpType() var commitMsg = 'Releasing ' + releaseType + ' version: ' + version diff --git a/lib/ConnectSequence.js b/lib/ConnectSequence.js index ea037ce..8823582 100644 --- a/lib/ConnectSequence.js +++ b/lib/ConnectSequence.js @@ -159,8 +159,10 @@ function appendIf (filter, middleware) { this.append(function (req, res, next) { if (filter(req)) { middleware(req, res, next) + return } else { next() + return } }) } diff --git a/lib/errors/CustomError.js b/lib/errors/CustomError.js new file mode 100644 index 0000000..cab0e41 --- /dev/null +++ b/lib/errors/CustomError.js @@ -0,0 +1,54 @@ +'use strict' + +// var PrivateMethodError = require('./PrivateMethodError') +// var ProtectedMethodError = require('./ProtectedMethodError') + +module.exports = CustomError + +CustomError.prototype = Object.create(Error.prototype) +CustomError.prototype.constructor = CustomError +CustomError.prototype.setMessage = setMessage +CustomError.prototype.createStackTrace = createStackTrace + +/** + * CustomError + * @class + * @mixin + * @property {String} message The error message + * @property {String} stack The error stack trace + * + * @constructor + * @param {String} [msg] The error message + */ +function CustomError (msg) { + // Error.call(this, msg) + this.setMessage(msg) + this.createStackTrace() +} + +/** + * Set the error message from the given argument or from the class property DEFAULT_ERROR_MESSAGE + * @method + */ +function setMessage (msg) { + if (msg && typeof msg === 'string') { + this.message = msg + } else if (this.constructor.name !== 'CustomError') { + this.message = this.constructor.DEFAULT_ERROR_MESSAGE + } else { + this.message = undefined + } +} + +/** + * Set the the correct stack trace for this error + * @method + * @returns {undefined} + * @throws {PrivateMethodError} + */ +function createStackTrace () { + var stack = new Error().stack + var splited = stack.split('\n') + var modifiedStack = splited[0].concat('\n', splited.splice(3).join('\n')) + this.stack = modifiedStack +} diff --git a/lib/errors/MissingArgumentError.js b/lib/errors/MissingArgumentError.js index 22c66fc..9c4ca16 100644 --- a/lib/errors/MissingArgumentError.js +++ b/lib/errors/MissingArgumentError.js @@ -1,9 +1,14 @@ 'use strict' -var PrivateMethodError = require('./PrivateMethodError') +var CustomError = require('./CustomError') module.exports = MissingArgumentError +MissingArgumentError.DEFAULT_ERROR_MESSAGE = 'One or more argument are missing' + +MissingArgumentError.prototype = Object.create(CustomError.prototype) +MissingArgumentError.prototype.constructor = MissingArgumentError + /** * MissingArgumentError * @class @@ -14,67 +19,5 @@ module.exports = MissingArgumentError * @param {String} [msg] The error message */ function MissingArgumentError (msg) { - // Error.call(this, msg) - if (msg && typeof msg === 'string') { - this.message = msg - } else { - this.message = MissingArgumentError.DEFAULT_ERROR_MESSAGE - } - this.createStackTrace() -} - -MissingArgumentError.DEFAULT_ERROR_MESSAGE = 'One or more argument are missing' - -MissingArgumentError.prototype = Object.create(Error.prototype) -MissingArgumentError.prototype.constructor = MissingArgumentError -MissingArgumentError.prototype.createStackTrace = createStackTrace - -/** - * Set the the correct stack trace for this error - * @method - * @private - * @returns {undefined} - * @throws {PrivateMethodError} - */ -function createStackTrace () { - privatize() - var stack = new Error().stack - var splited = stack.split('\n') - var modifiedStack = splited[0].concat('\n', splited.splice(3).join('\n')) - this.stack = modifiedStack -} - -/** - * Throws a PrivateMethodError if the third level of a new stack trace differs of the first - * @function - * @inner - * @returns {undefined} - * @throws {PrivateMethodError} - */ -function privatize () { - var trace = new Error().stack - var here = getFileCall(trace, 1) - var caller = getFileCall(trace, 3) - if (here !== caller) { - throw new PrivateMethodError() - } -} - -/** - * Get the file path of the caller at a given stack level - * @function - * @inner - * @param {String} trace A given stack trace - * @param {Number} level A given stack level to get the file path at this level - * @returns {String} The file path for this level - */ -function getFileCall (trace, level) { - var firstLineOfStack = trace.split('\n')[level] - var splitted = firstLineOfStack.split('(') - firstLineOfStack = splitted.splice(1).join('') - splitted = firstLineOfStack.split(')') - firstLineOfStack = splitted.join('') - splitted = firstLineOfStack.split(':') - firstLineOfStack = splitted.slice(0, -2).join('') - return firstLineOfStack + CustomError.call(this, msg) } diff --git a/lib/errors/PrivateMethodError.js b/lib/errors/PrivateMethodError.js index 28c85ef..c7bcb62 100644 --- a/lib/errors/PrivateMethodError.js +++ b/lib/errors/PrivateMethodError.js @@ -1,12 +1,13 @@ 'use strict' +var CustomError = require('./CustomError') + module.exports = PrivateMethodError PrivateMethodError.DEFAULT_ERROR_MESSAGE = 'This is a private method' -PrivateMethodError.prototype = Object.create(Error.prototype) +PrivateMethodError.prototype = Object.create(CustomError.prototype) PrivateMethodError.prototype.constructor = PrivateMethodError -PrivateMethodError.prototype.createStackTrace = createStackTrace /** * PrivateMethodError @@ -15,63 +16,8 @@ PrivateMethodError.prototype.createStackTrace = createStackTrace * @property {String} stack The error stack trace * * @constructor - * @param {String} msg The error message + * @param {String} msg A custom error message */ function PrivateMethodError (msg) { - if (msg && typeof msg === 'string') { - this.message = msg - } else { - this.message = PrivateMethodError.DEFAULT_ERROR_MESSAGE - } - this.createStackTrace() -} - -/** - * Set the the correct stack trace for this error - * @method - * @private - * @returns {undefined} - * @throws {PrivateMethodError} - */ -function createStackTrace () { - privatize() - var stack = new Error().stack - var splited = stack.split('\n') - var modifiedStack = splited[0].concat('\n', splited.splice(3).join('\n')) - this.stack = modifiedStack -} - -/** - * Throws a PrivateMethodError if the third level of a new stack trace differs of the first - * @function - * @inner - * @returns {undefined} - * @throws {PrivateMethodError} - */ -function privatize () { - var trace = new Error().stack - var here = getFileCall(trace, 1) - var caller = getFileCall(trace, 3) - if (here !== caller) { - throw new PrivateMethodError() - } -} - -/** - * Get the file path of the caller at a given stack level - * @function - * @inner - * @param {String} trace A given stack trace - * @param {Number} level A given stack level to get the file path at this level - * @returns {String} The file path for this level - */ -function getFileCall (trace, level) { - var firstLineOfStack = trace.split('\n')[level] - var splitted = firstLineOfStack.split('(') - firstLineOfStack = splitted.splice(1).join('') - splitted = firstLineOfStack.split(')') - firstLineOfStack = splitted.join('') - splitted = firstLineOfStack.split(':') - firstLineOfStack = splitted.slice(0, -2).join('') - return firstLineOfStack + CustomError.call(this, msg) } diff --git a/tests/errors/CustomError.spec.js b/tests/errors/CustomError.spec.js new file mode 100644 index 0000000..bf87267 --- /dev/null +++ b/tests/errors/CustomError.spec.js @@ -0,0 +1,103 @@ +'use strict' + +var path = require('path') +var chai = require('chai') + +var CustomError = require(path.resolve('./lib/errors/CustomError')) + +var describe = global.describe +var it = global.it +var expect = chai.expect + +describe('CustomError', function () { + it('should be a function', function () { + expect(CustomError).to.be.a('function') + }) + + it("should not have a 'DEFAULT_ERROR_MESSAGE' static constant property (child classes should)", function () { + expect(CustomError).to.not.have.a.property('DEFAULT_ERROR_MESSAGE') + }) + + describe('.prototype', function () { + it('should be a function', function () { + expect(CustomError.prototype).to.be.a('OBJECT') + }) + + it('should be an instance of Error', function () { + expect(CustomError.prototype).to.be.an.instanceof(Error) + }) + + describe('.constructor()', function () { + it('should be an instance of CustomError', function () { + var err = new CustomError() + expect(CustomError.prototype).to.be.an.instanceof(Error) + expect(err).to.be.an.instanceof(CustomError) + }) + + it("should have a 'name' property of type 'String'", function () { + var msg = "'arg' is missing" + var err = new CustomError(msg) + expect(err).to.be.a.property('name') + expect(err.message).to.be.a('String') + }) + + it("should have a 'message' property of type 'String'", function () { + var msg = "'arg' is missing" + var err = new CustomError(msg) + expect(err).to.be.a.property('message') + expect(err.message).to.be.a('String') + expect(err.message).to.equal(msg) + }) + + it("should have a 'stack' property of type 'String'", function () { + var msg = "'arg' is missing" + var err = new CustomError(msg) + expect(err).to.be.a.property('stack') + expect(err.stack).to.be.a('String') + }) + + it("should have a 'createStackTrace' property of type 'function'", function () { + var err = new CustomError('yo') + expect(err).to.have.a.property('createStackTrace') + expect(err.createStackTrace).to.be.a('function') + }) + + describe('when giving a non-string argument', function () { + it('should not fail', function () { + var func = function () { return new CustomError(func) } + var obj = function () { return new CustomError({ foo: 'bar' }) } + var arr = function () { return new CustomError([ 'foo', 'baz' ]) } + + expect(func).to.not.throw() + expect(obj).to.not.throw() + expect(arr).to.not.throw() + }) + }) + + describe('when called without argument', function () { + it('should not have a default error message (child classes should)', function () { + var err = new CustomError() + expect(err.message).to.not.be.a('String') + expect(err.message).to.be.undefined + }) + }) + + describe('when called without argument from a child class', function () { + it('should set the child class DEFAULT_ERROR_MESSAGE', function () { + var err + var ChildError = function ChildError (msg) { + CustomError.call(this, msg) + } + ChildError.prototype = Object.create(CustomError.prototype) + ChildError.prototype.constructor = ChildError + ChildError.DEFAULT_ERROR_MESSAGE = 'child error' + err = new ChildError() + expect(err).to.be.an('object') + expect(err).to.be.an.instanceof(ChildError) + expect(err.message).to.be.a('string') + expect(err.message).to.equal(ChildError.DEFAULT_ERROR_MESSAGE) + }) + }) + }) + }) +}) diff --git a/tests/errors/MissingArgumentError.spec.js b/tests/errors/MissingArgumentError.spec.js index 4bf76cd..32b84a7 100644 --- a/tests/errors/MissingArgumentError.spec.js +++ b/tests/errors/MissingArgumentError.spec.js @@ -2,9 +2,11 @@ var path = require('path') var chai = require('chai') +var CustomError = require(path.resolve('./lib/errors/CustomError')) var MissingArgumentError = require(path.resolve('./lib/errors/MissingArgumentError')) var describe = global.describe +var beforeEach = global.beforeEach var it = global.it var expect = chai.expect @@ -12,69 +14,80 @@ describe('MissingArgumentError', function () { it('should be a function', function () { expect(MissingArgumentError).to.be.a('function') }) - it("should has a 'DEFAULT_ERROR_MESSAGE' static constant property", function () { - expect(MissingArgumentError).to.be.a.property('DEFAULT_ERROR_MESSAGE') + + it("should have a 'DEFAULT_ERROR_MESSAGE' static constant property", function () { + expect(MissingArgumentError).to.have.a.property('DEFAULT_ERROR_MESSAGE') }) describe('.prototype', function () { - it('should be a function', function () { - expect(MissingArgumentError.prototype).to.be.a('OBJECT') + it('should be an object', function () { + expect(MissingArgumentError.prototype).to.be.an('object') }) - it('should be an instance of Error', function () { - expect(MissingArgumentError.prototype).to.be.an.instanceof(Error) + + it('should be an instance of CustomError', function () { + expect(MissingArgumentError.prototype).to.be.an.instanceof(CustomError) + }) + + describe('.constructor', function () { + it('should be a function', function () { + expect(MissingArgumentError.prototype.constructor).to.be.a('function') + }) + + it("should have a 'name' property w/ the value 'MissingArgumentError'", function () { + expect(MissingArgumentError.prototype.constructor).to.be.a.property('name') + expect(MissingArgumentError.prototype.constructor.name).to.equal('MissingArgumentError') + }) }) describe('.constructor()', function () { - it('should be an instance of Error', function () { + it('should be an instance of MissingArgumentError', function () { var err = new MissingArgumentError() - expect(MissingArgumentError.prototype).to.be.an.instanceof(Error) expect(err).to.be.an.instanceof(MissingArgumentError) }) - it("should has a 'name' property of type 'String'", function () { - var msg = "'arg' is missing" - var err = new MissingArgumentError(msg) - expect(err).to.be.a.property('name') - expect(err.message).to.be.a('String') - }) - it("should has a 'message' property of type 'String'", function () { + + it("should have a 'message' property of type 'String'", function () { var msg = "'arg' is missing" var err = new MissingArgumentError(msg) expect(err).to.be.a.property('message') expect(err.message).to.be.a('String') }) - it("should has a 'stack' property of type 'String'", function () { + + it("should have a 'stack' property of type 'String'", function () { var msg = "'arg' is missing" var err = new MissingArgumentError(msg) - expect(err).to.be.a.property('stack') + expect(err).to.have.a.property('stack') expect(err.stack).to.be.a('String') }) - it('should not fail if an bad type is given instead of a string as first argument', function () { - var err - var func = function () { err = new MissingArgumentError(func) } - var obj = function () { err = new MissingArgumentError({ foo: 'bar' }) } - var arr = function () { err = new MissingArgumentError([ 'foo', 'baz' ]) } - expect(func).to.not.throw('TypeError') - expect(err.message).to.be.a('String') + describe('when a non-string argument is given', function () { + var err0, err1, err2 + var func, obj, arr - expect(obj).to.not.throw('TypeError') - expect(err.message).to.be.a('String') + beforeEach(function () { + func = function () { err0 = new MissingArgumentError(func) } + obj = function () { err1 = new MissingArgumentError({ foo: 'bar' }) } + arr = function () { err2 = new MissingArgumentError([ 'foo', 'baz' ]) } + }) - expect(arr).to.not.throw('TypeError') - expect(err.message).to.be.a('String') - }) - it('should fails if we call the private createStackTrace method', function () { - var func = function () { - var err = new MissingArgumentError(func) - var t = err.createStackTrace() - console.log(t) - } - expect(func).to.throw(Error) + it('should not fail', function () { + expect(func).to.not.throw() + expect(obj).to.not.throw() + expect(arr).to.not.throw() + }) + + it('should define the "message" property as a String', function () { + expect(err0.message).to.be.a('String') + expect(err1.message).to.be.a('String') + expect(err2.message).to.be.a('String') + }) }) - it('should has a default error message if no argument is given', function () { - var err = new MissingArgumentError() - expect(err.message).to.be.a('String') - expect(err.message).to.be.equal(MissingArgumentError.DEFAULT_ERROR_MESSAGE) + + describe('when no argument is given', function () { + it('should set the default error message', function () { + var err = new MissingArgumentError() + expect(err.message).to.be.a('String') + expect(err.message).to.be.equal(MissingArgumentError.DEFAULT_ERROR_MESSAGE) + }) }) }) }) diff --git a/tests/errors/PrivateMethodError.spec.js b/tests/errors/PrivateMethodError.spec.js index 7f07e3a..12bc06e 100644 --- a/tests/errors/PrivateMethodError.spec.js +++ b/tests/errors/PrivateMethodError.spec.js @@ -2,9 +2,11 @@ var path = require('path') var chai = require('chai') +var CustomError = require(path.resolve('./lib/errors/CustomError')) var PrivateMethodError = require(path.resolve('./lib/errors/PrivateMethodError')) var describe = global.describe +var beforeEach = global.beforeEach var it = global.it var expect = chai.expect @@ -12,16 +14,29 @@ describe('PrivateMethodError', function () { it('should be a function', function () { expect(PrivateMethodError).to.be.a('function') }) - it("should has a 'DEFAULT_ERROR_MESSAGE' static constant property", function () { - expect(PrivateMethodError).to.be.a.property('DEFAULT_ERROR_MESSAGE') + + it("should have a 'DEFAULT_ERROR_MESSAGE' static constant property", function () { + expect(PrivateMethodError).to.have.a.property('DEFAULT_ERROR_MESSAGE') }) describe('.prototype', function () { it('should be an object', function () { expect(PrivateMethodError.prototype).to.be.a('object') }) - it('should be an instance of Error', function () { - expect(PrivateMethodError.prototype).to.be.an.instanceof(Error) + + it('should be an instance of CustomError', function () { + expect(PrivateMethodError.prototype).to.be.an.instanceof(CustomError) + }) + + describe('.constructor', function () { + it('should be a function', function () { + expect(PrivateMethodError.prototype.constructor).to.be.a('function') + }) + + it("should have a 'name' property w/ the value 'PrivateMethodError'", function () { + expect(PrivateMethodError.prototype.constructor).to.be.a.property('name') + expect(PrivateMethodError.prototype.constructor.name).to.equal('PrivateMethodError') + }) }) describe('.constructor()', function () { @@ -29,51 +44,50 @@ describe('PrivateMethodError', function () { var err = new PrivateMethodError() expect(err).to.be.an.instanceof(PrivateMethodError) }) - it("should has a 'name' property of type 'String'", function () { - var msg = 'i am private' - var err = new PrivateMethodError(msg) - expect(err).to.be.a.property('name') - expect(err.message).to.be.a('String') - }) - it("should has a 'message' property of type 'String'", function () { + + it("should have a 'message' property of type 'String'", function () { var msg = 'i am private' var err = new PrivateMethodError(msg) expect(err).to.be.a.property('message') expect(err.message).to.be.a('String') }) - it("should has a 'stack' property of type 'String'", function () { + + it("should have a 'stack' property of type 'String'", function () { var msg = 'i am private' var err = new PrivateMethodError(msg) - expect(err).to.be.a.property('stack') + expect(err).to.have.a.property('stack') expect(err.stack).to.be.a('String') }) - it('should not fail if an bad type is given instead of a string as first argument', function () { - var err - var func = function () { err = new PrivateMethodError(func) } - var obj = function () { err = new PrivateMethodError({ foo: 'bar' }) } - var arr = function () { err = new PrivateMethodError([ 'foo', 'baz' ]) } - expect(func).to.not.throw('TypeError') - expect(err.message).to.be.a('String') + describe('when a non-string argument is given', function () { + var err0, err1, err2 + var func, obj, arr - expect(obj).to.not.throw('TypeError') - expect(err.message).to.be.a('String') + beforeEach(function () { + func = function () { err0 = new PrivateMethodError(func) } + obj = function () { err1 = new PrivateMethodError({ foo: 'bar' }) } + arr = function () { err2 = new PrivateMethodError([ 'foo', 'baz' ]) } + }) - expect(arr).to.not.throw('TypeError') - expect(err.message).to.be.a('String') - }) - it('should fails if we call the private createStackTrace method', function () { - var func = function () { - var err = new PrivateMethodError(func) - var t = err.createStackTrace() - console.log(t) - } - expect(func).to.throw(Error) + it('should not fail', function () { + expect(func).to.not.throw() + expect(obj).to.not.throw() + expect(arr).to.not.throw() + }) + + it('should define the "message" property as a String', function () { + expect(err0.message).to.be.a('String') + expect(err1.message).to.be.a('String') + expect(err2.message).to.be.a('String') + }) }) - it('should has a default error message if no argument is given', function () { - var err = new PrivateMethodError() - expect(err.message).to.be.a('String') - expect(err.message).to.be.equal(PrivateMethodError.DEFAULT_ERROR_MESSAGE) + + describe('when no argument is given', function () { + it('should set the default error message', function () { + var err = new PrivateMethodError() + expect(err.message).to.be.a('String') + expect(err.message).to.be.equal(PrivateMethodError.DEFAULT_ERROR_MESSAGE) + }) }) }) })