1'use strict'; 2 3const errcode = require('../index'); 4const expect = require('expect.js'); 5 6describe('errcode', () => { 7 describe('string as first argument', () => { 8 it('should throw an error', () => { 9 expect(() => { errcode('my message'); }).to.throwError((err) => { 10 expect(err).to.be.a(TypeError); 11 }); 12 }); 13 }); 14 15 describe('error as first argument', () => { 16 it('should accept an error and do nothing', () => { 17 const myErr = new Error('my message'); 18 const err = errcode(myErr); 19 20 expect(err).to.be(myErr); 21 expect(err.hasOwnProperty(err.code)).to.be(false); 22 }); 23 24 it('should accept an error and add a code', () => { 25 const myErr = new Error('my message'); 26 const err = errcode(myErr, 'ESOME'); 27 28 expect(err).to.be(myErr); 29 expect(err.code).to.be('ESOME'); 30 }); 31 32 it('should accept an error object and add code & properties', () => { 33 const myErr = new Error('my message'); 34 const err = errcode(myErr, 'ESOME', { foo: 'bar', bar: 'foo' }); 35 36 expect(err).to.be.an(Error); 37 expect(err.code).to.be('ESOME'); 38 expect(err.foo).to.be('bar'); 39 expect(err.bar).to.be('foo'); 40 }); 41 42 it('should create an error object without code but with properties', () => { 43 const myErr = new Error('my message'); 44 const err = errcode(myErr, { foo: 'bar', bar: 'foo' }); 45 46 expect(err).to.be.an(Error); 47 expect(err.code).to.be(undefined); 48 expect(err.foo).to.be('bar'); 49 expect(err.bar).to.be('foo'); 50 }); 51 52 it('should set a non-writable field', () => { 53 const myErr = new Error('my message'); 54 55 Object.defineProperty(myErr, 'code', { 56 value: 'derp', 57 writable: false, 58 }); 59 const err = errcode(myErr, 'ERR_WAT'); 60 61 expect(err).to.be.an(Error); 62 expect(err.stack).to.equal(myErr.stack); 63 expect(err.code).to.be('ERR_WAT'); 64 }); 65 66 it('should add a code to frozen object', () => { 67 const myErr = new Error('my message'); 68 const err = errcode(Object.freeze(myErr), 'ERR_WAT'); 69 70 expect(err).to.be.an(Error); 71 expect(err.stack).to.equal(myErr.stack); 72 expect(err.code).to.be('ERR_WAT'); 73 }); 74 75 it('should to set a field that throws at assignment time', () => { 76 const myErr = new Error('my message'); 77 78 Object.defineProperty(myErr, 'code', { 79 enumerable: true, 80 set() { 81 throw new Error('Nope!'); 82 }, 83 get() { 84 return 'derp'; 85 }, 86 }); 87 const err = errcode(myErr, 'ERR_WAT'); 88 89 expect(err).to.be.an(Error); 90 expect(err.stack).to.equal(myErr.stack); 91 expect(err.code).to.be('ERR_WAT'); 92 }); 93 94 it('should retain error type', () => { 95 const myErr = new TypeError('my message'); 96 97 Object.defineProperty(myErr, 'code', { 98 value: 'derp', 99 writable: false, 100 }); 101 const err = errcode(myErr, 'ERR_WAT'); 102 103 expect(err).to.be.a(TypeError); 104 expect(err.stack).to.equal(myErr.stack); 105 expect(err.code).to.be('ERR_WAT'); 106 }); 107 108 it('should add a code to a class that extends Error', () => { 109 class CustomError extends Error { 110 set code(val) { 111 throw new Error('Nope!'); 112 } 113 } 114 115 const myErr = new CustomError('my message'); 116 117 Object.defineProperty(myErr, 'code', { 118 value: 'derp', 119 writable: false, 120 configurable: false, 121 }); 122 const err = errcode(myErr, 'ERR_WAT'); 123 124 expect(err).to.be.a(CustomError); 125 expect(err.stack).to.equal(myErr.stack); 126 expect(err.code).to.be('ERR_WAT'); 127 128 // original prototype chain should be intact 129 expect(() => { 130 const otherErr = new CustomError('my message'); 131 132 otherErr.code = 'derp'; 133 }).to.throwError(); 134 }); 135 136 it('should support errors that are not Errors', () => { 137 const err = errcode({ 138 message: 'Oh noes!', 139 }, 'ERR_WAT'); 140 141 expect(err.message).to.be('Oh noes!'); 142 expect(err.code).to.be('ERR_WAT'); 143 }); 144 }); 145 146 describe('falsy first arguments', () => { 147 it('should not allow passing null as the first argument', () => { 148 expect(() => { errcode(null); }).to.throwError((err) => { 149 expect(err).to.be.a(TypeError); 150 }); 151 }); 152 153 it('should not allow passing undefined as the first argument', () => { 154 expect(() => { errcode(undefined); }).to.throwError((err) => { 155 expect(err).to.be.a(TypeError); 156 }); 157 }); 158 }); 159}); 160