From ae3f0e7d279105fca71fdec6d6d8d017858098c8 Mon Sep 17 00:00:00 2001 From: Pierre Colle Date: Thu, 26 Oct 2017 18:54:17 +0200 Subject: [PATCH 1/4] make errors more expressives --- lib/errors/componentnotfound.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/errors/componentnotfound.js b/lib/errors/componentnotfound.js index 7a69a38..2c2a051 100644 --- a/lib/errors/componentnotfound.js +++ b/lib/errors/componentnotfound.js @@ -4,17 +4,32 @@ * @api public */ function ComponentNotFoundError(message) { - Error.call(this); - Error.captureStackTrace(this, arguments.callee); - this.message = message; - this.code = 'COMPONENT_NOT_FOUND'; + // from https://stackoverflow.com/a/17936621/824979 + const temp = Error.apply(this, arguments); + temp.name = this.name = 'ComponentNotFoundError'; + temp.code = this.code = 'COMPONENT_NOT_FOUND_CUSTOM'; + this.message = temp.message; + if(Object.defineProperty) { + // getter for more optimizy goodness + Object.defineProperty(this, 'stack', { + get: function() { + return temp.stack + }, + configurable: true // so you can change it if you want + }) + } else { + this.stack = temp.stack + } + this.name = "ComponentNotFoundError"; } /** * Inherit from `Error`. */ -ComponentNotFoundError.prototype.__proto__ = Error.prototype; +const IntermediateInheritor = function () {}; +IntermediateInheritor.prototype = Error.prototype +ComponentNotFoundError.prototype = new IntermediateInheritor() /** * Expose `ComponentNotFoundError`. From a4fc2ab15b5eb8d085c538f03637c359fc238abb Mon Sep 17 00:00:00 2001 From: Pierre Colle Date: Fri, 3 Nov 2017 14:01:15 +0100 Subject: [PATCH 2/4] consider defineProperty is std js --- lib/errors/componentnotfound.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/errors/componentnotfound.js b/lib/errors/componentnotfound.js index 2c2a051..3e79654 100644 --- a/lib/errors/componentnotfound.js +++ b/lib/errors/componentnotfound.js @@ -7,19 +7,14 @@ function ComponentNotFoundError(message) { // from https://stackoverflow.com/a/17936621/824979 const temp = Error.apply(this, arguments); temp.name = this.name = 'ComponentNotFoundError'; - temp.code = this.code = 'COMPONENT_NOT_FOUND_CUSTOM'; + temp.code = this.code = 'COMPONENT_NOT_FOUND'; this.message = temp.message; - if(Object.defineProperty) { - // getter for more optimizy goodness - Object.defineProperty(this, 'stack', { - get: function() { - return temp.stack - }, - configurable: true // so you can change it if you want - }) - } else { - this.stack = temp.stack - } + Object.defineProperty(this, 'stack', { + get: function() { + return temp.stack + }, + configurable: true + }) this.name = "ComponentNotFoundError"; } From 1e8cf79919d49c2cc4520fce428fe5815ea52795 Mon Sep 17 00:00:00 2001 From: Pierre Colle Date: Fri, 3 Nov 2017 14:12:10 +0100 Subject: [PATCH 3/4] unit test for error stack --- test/container.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/container.test.js b/test/container.test.js index b723c9c..e3bd4a6 100644 --- a/test/container.test.js +++ b/test/container.test.js @@ -27,6 +27,8 @@ describe('Container', function() { it('should fail with error', function() { expect(error).to.be.an.instanceOf(Error); expect(error.message).to.equal("Unable to create component 'unknown' required by 'unknown'"); + expect(error.code).to.equal("COMPONENT_NOT_FOUND"); + expect(error.stack.split("\n")[0]).to.equal("ComponentNotFoundError: Unable to create component 'unknown' required by 'unknown'") }); }); From 475581bccd2cfda62af34076055a489b2f10b4e5 Mon Sep 17 00:00:00 2001 From: Pierre Colle Date: Fri, 3 Nov 2017 14:33:53 +0100 Subject: [PATCH 4/4] more coverage --- lib/errors/componentcreate.js | 20 +++++++--- lib/errors/componentnotfound.js | 1 - lib/errors/interfacenotfound.js | 19 +++++++--- test/container.test.js | 66 ++++++++++++++++++++++++++++++++- 4 files changed, 93 insertions(+), 13 deletions(-) diff --git a/lib/errors/componentcreate.js b/lib/errors/componentcreate.js index ab54015..74f14c4 100644 --- a/lib/errors/componentcreate.js +++ b/lib/errors/componentcreate.js @@ -4,17 +4,25 @@ * @api public */ function ComponentCreateError(message) { - Error.call(this); - Error.captureStackTrace(this, arguments.callee); - this.message = message; - this.code = 'COMPONENT_CREATE_ERROR'; + // from https://stackoverflow.com/a/17936621/824979 + const temp = Error.apply(this, arguments); + temp.name = this.name = 'ComponentCreateError'; + temp.code = this.code = 'COMPONENT_CREATE_ERROR'; + this.message = temp.message; + Object.defineProperty(this, 'stack', { + get: function() { + return temp.stack + }, + configurable: true + }) } /** * Inherit from `Error`. */ -ComponentCreateError.prototype.__proto__ = Error.prototype; - +const IntermediateInheritor = function () {}; +IntermediateInheritor.prototype = Error.prototype; +ComponentCreateError.prototype = new IntermediateInheritor(); /** * Expose `ComponentCreateError`. diff --git a/lib/errors/componentnotfound.js b/lib/errors/componentnotfound.js index 3e79654..41610bc 100644 --- a/lib/errors/componentnotfound.js +++ b/lib/errors/componentnotfound.js @@ -15,7 +15,6 @@ function ComponentNotFoundError(message) { }, configurable: true }) - this.name = "ComponentNotFoundError"; } /** diff --git a/lib/errors/interfacenotfound.js b/lib/errors/interfacenotfound.js index 0847d15..432f74d 100644 --- a/lib/errors/interfacenotfound.js +++ b/lib/errors/interfacenotfound.js @@ -4,17 +4,26 @@ * @api public */ function InterfaceNotFoundError(message, iface) { - Error.call(this); - Error.captureStackTrace(this, arguments.callee); - this.message = message; - this.code = 'INTERFACE_NOT_FOUND'; + // from https://stackoverflow.com/a/17936621/824979 + const temp = Error.apply(this, arguments); + temp.name = this.name = 'InterfaceNotFoundError'; + temp.code = this.code = 'INTERFACE_NOT_FOUND'; + this.message = temp.message; + Object.defineProperty(this, 'stack', { + get: function() { + return temp.stack + }, + configurable: true + }) this.interface = iface; } /** * Inherit from `Error`. */ -InterfaceNotFoundError.prototype.__proto__ = Error.prototype; +const IntermediateInheritor = function () {}; +IntermediateInheritor.prototype = Error.prototype; +InterfaceNotFoundError.prototype = new IntermediateInheritor(); /** diff --git a/test/container.test.js b/test/container.test.js index e3bd4a6..5f14471 100644 --- a/test/container.test.js +++ b/test/container.test.js @@ -73,7 +73,71 @@ describe('Container', function() { }); }); - + describe('unknown interface', function() { + + describe('created without a parent', function() { + var error; + + before(function(done) { + container.create('$unknown') + .then(function(obj) { + done(new Error('should not create object')); + }) + .catch(function(err) { + error = err; + done(); + }); + }) + + it('should fail with error', function() { + expect(error).to.be.an.instanceOf(Error); + expect(error.message).to.equal("Cannot find component implementing interface '$unknown' required by 'unknown'"); + expect(error.code).to.equal("INTERFACE_NOT_FOUND"); + expect(error.stack.split("\n")[0]).to.equal("InterfaceNotFoundError: Cannot find component implementing interface '$unknown' required by 'unknown'") + }); + }); + + describe('created with a parent', function() { + var error; + + before(function(done) { + container.create('$unknown', { id: 'main' }) + .then(function(obj) { + done(new Error('should not create object')); + }) + .catch(function(err) { + error = err; + done(); + }); + }) + + it('should fail with error', function() { + expect(error).to.be.an.instanceOf(Error); + expect(error.message).to.equal("Cannot find component implementing interface '$unknown' required by 'main'"); + }); + }); + + describe('created with a parent, lacking an id', function() { + var error; + + before(function(done) { + container.create('$unknown', {}) + .then(function(obj) { + done(new Error('should not create object')); + }) + .catch(function(err) { + error = err; + done(); + }); + }) + + it('should fail with error', function() { + expect(error).to.be.an.instanceOf(Error); + expect(error.message).to.equal("Cannot find component implementing interface '$unknown' required by 'unknown'"); + }); + }); + + }); describe.skip('async component', function() { var container = new Container(); container.use(require('./fixtures/sources/async'));