errors
Version:
A comprehensive, robust, yet lightweight set of error utilities for node.js enabling you to do errors more effectively.
305 lines (245 loc) • 10.1 kB
JavaScript
var errors = require('..')
, http = require('http')
, should = require('should');
describe('errors export structure', function() {
it('should contain find() method', function() {
errors.should.be.a('object').and.have.property('find');
errors.find.should.be.a('function');
});
it('should contain a create method', function() {
errors.create.should.be.a('function');
errors.create.should.have.length(1);
});
it('should contain HttpError', function() {
errors.HttpError.should.be.a('function');
var httpError = new errors.HttpError();
httpError.should.an.instanceOf(Error);
httpError.code.should.be.above(599);
});
it('should not leak to global.code', function() {
should.not.exist(global.code);
});
for (var code in http.STATUS_CODES) {
it('should contain ' + http.STATUS_CODES[code] + ' Error', function() {
var errorName = 'Http' + code + 'Error'
, errorInstance = new errors[errorName]();
errors[errorName].should.be.a('function');
errorInstance.should.be.an.instanceOf(errors.HttpError);
errorInstance.code.should.equal(code);
errorInstance.message.should.equal(http.STATUS_CODES[code]);
errorInstance.status.should.equal(code);
});
}
});
var FatalError = errors.create({
name: 'FatalError',
defaultMessage: 'A Fatal Error Occurred.'
});
var FatalDBError = errors.create({
name: 'FatalDBError',
parent: FatalError,
defaultMessage: 'A Fatal Database Error Occurred.'
});
var FatalDBTransactionError = errors.create({
name: 'FatalDBTransactionError',
parent: FatalDBError,
defaultMessage: 'A Fatal Database Transaction Error Occurred.'
});
var fatalError = new FatalError()
, fatalDBError = new FatalDBError()
, fatalDBTransError = new FatalDBTransactionError();
describe('errors inheritance', function() {
it('FatalError extends Error', function() {
errors.FatalError.should.equal(FatalError);
FatalError.should.be.a('function');
fatalError.should.be.an.instanceOf(Error);
fatalError.code.should.be.above(599);
fatalError.message.should.equal('A Fatal Error Occurred.');
fatalError.status.should.equal(500);
});
it('FatalDBError extends FatalError', function() {
errors.FatalDBError.should.equal(FatalDBError);
FatalDBError.should.be.a('function');
fatalDBError.should.be.an.instanceOf(FatalError);
fatalDBError.should.not.be.an.instanceOf(FatalDBTransactionError);
fatalDBError.code.should.be.above(599);
fatalDBError.code.should.not.equal(new FatalError().code);
fatalDBError.message.should.equal('A Fatal Database Error Occurred.');
fatalDBError.status.should.equal(500);
});
it('FatalDBTransactionError extends FatalDBError', function() {
errors.FatalDBTransactionError.should.equal(FatalDBTransactionError);
FatalDBTransactionError.should.be.a('function');
fatalDBTransError.should.be.an.instanceOf(FatalDBError);
fatalDBTransError.code.should.be.above(599);
fatalDBTransError.code.should.not.equal(new FatalDBError().code);
fatalDBTransError.message.should.equal('A Fatal Database Transaction Error Occurred.');
fatalDBTransError.status.should.equal(500);
});
});
describe('errors.find()', function() {
it('should find existing error by code', function() {
errors.find(fatalDBError.code).should.equal(FatalDBError);
});
it('should find existing error by name', function() {
errors.find(fatalDBError.name).should.equal(FatalDBError);
});
it('should not find error for non-existing code', function() {
require('should').not.exist(errors.find(9999));
});
it('should not find error for non-existing name', function() {
require('should').not.exist(errors.find('FatalDDBError'));
});
});
describe('errors unique error code generation', function() {
it('should create unique error codes', function() {
(fatalError.code).should.not.equal(fatalDBError.code);
(fatalDBError.code).should.not.equal(fatalDBTransError.code);
});
it('should not hammer existing error code', function() {
var FileNotFoundError = errors.create({
name: 'FileNotFoundError',
code: fatalDBTransError.code + 1
});
var IOError = errors.create({
name: 'IOError'
});
var fnfError = new FileNotFoundError()
, ioError = new IOError();
(fnfError.code).should.not.equal(ioError.code);
ioError.code.should.be.above(fatalDBTransError.code);
});
});
describe('default error message handling', function() {
var FileEncodingError = errors.create({
name: 'FileEncodingError',
defaultMessage: 'File encoding is invalid and cannot be read.'
});
var feError = new FileEncodingError();
it('should use default message when none specified', function() {
feError.message.should.eql('File encoding is invalid and cannot be read.');
});
it('should allow default message overriding', function() {
var err = new FileEncodingError('dude, the encoding is bad');
err.message.should.eql('dude, the encoding is bad');
});
});
describe('scoped creation', function() {
var MalformedInputError = errors.create({
name: 'MalformedInputError',
scope: exports
});
it('should exist in exports', function() {
require('should').exist(exports.MalformedInputError);
exports.MalformedInputError.should.equal(MalformedInputError);
});
it('should find error in exports', function() {
errors.find('MalformedInputError').should.equal(MalformedInputError);
var err = new MalformedInputError();
errors.find(err.code).should.equal(MalformedInputError);
});
});
describe('errors.stacks()', function() {
var err = new errors.Http413Error();
it('should enable stack traces', function() {
errors.stacks(true);
err.toString().should.include(err.stack);
});
it('should return current value of stacks', function() {
errors.stacks().should.equal(true);
});
it('should disable stack traces', function() {
errors.stacks(false);
err.toString().should.not.include(err.stack);
});
it('should return current value of stacks', function() {
errors.stacks().should.equal(false);
});
});
describe('errors.title()', function() {
it('should allow title to be settable', function() {
errors.title('My Title');
errors.title().should.equal('My Title');
});
});
describe('options style constructor', function() {
var IdentifiableError = errors.create('IdentifiableError'),
err = new IdentifiableError({message: 'Error with ref ID',
status: 501, refID: 'a1b2c3'});
it('should contain refID property', function() {
err.refID.should.equal('a1b2c3');
});
it('should have overridden status', function() {
err.status.should.equal(501);
});
it('toString() should output refID', function() {
err.toString().should.include('refID: a1b2c3');
});
it('toJSON() should include refID', function() {
err.toJSON().should.include({refID: 'a1b2c3'});
});
it('should have overriden message', function() {
err.toString().should.include(': Error with ref ID');
});
it('should not allow overriding of stack', function() {
(function() {new IdentifiableError({stack: 'fail'});}).should.throw();
});
it('should not allow overriding of name', function() {
(function() {new IdentifiableError({name: 'fail'});}).should.throw();
});
it('should not allow overriding of code', function() {
(function() {new IdentifiableError({code: 601});}).should.throw();
});
});
describe('status code override', function() {
var CustomHttpError = errors.create({name: 'CustomHttpError', status: 409}),
err = new CustomHttpError();
it('should have status of 409', function() {
err.status.should.equal(409);
});
it('should include 409 status in toJSON()', function() {
err.toJSON().should.include({status: 409});
});
it('should allow overriding in constructor', function() {
new CustomHttpError({status:411}).status.should.equal(411);
});
});
describe('errors.isError()', function(){
var legitError = new errors.HttpError();
it('should return true for legit errors', function() {
errors.isError(legitError).should.be.ok;
});
it('should return false for other objects', function() {
errors.isError({}).should.not.be.ok;
});
});
describe('native error to JSON', function() {
var NativeError = errors.create({name: 'NativeError'}),
typeError = new TypeError("Invalid type"),
useStacks = errors.stacks();
errors.stacks(false);
it('should include basic error attrs', function() {
var err = errors.errorToJSON(typeError);
err.should.include({name: 'TypeError', message: 'Invalid type'});
err.should.not.have.property('stack');
});
it('should include stack', function() {
errors.stacks(true);
var err = errors.errorToJSON(typeError);
err.should.have.property('stack');
err.stack.should.equal(typeError.stack);
});
it('should remap error attrs', function() {
errors.stacks(true);
var err = errors.errorToJSON(typeError, {'theStack': ['stack']});
err.should.have.property('theStack');
err.theStack.should.equal(typeError.stack);
});
it('should map nested object properties', function() {
var typeError = new TypeError("Invalid type");
typeError['causes'] = {'unknown': 'unknown native cause'};
var err = errors.errorToJSON(typeError, {'cause': ['causes.unknown']});
err.cause.should.equal('unknown native cause');
});
errors.stacks(useStacks);
});