const OError = require('..') const { expectError } = require('./support') class CustomError1 extends OError { constructor (options) { super({ message: 'failed to foo', ...options }) } } class CustomError2 extends OError { constructor (options) { super({ message: 'failed to bar', ...options }) } } describe('OError', () => { it('handles a custom error type with a cause', () => { function doSomethingBadInternally () { throw new Error('internal error') } function doSomethingBad () { try { doSomethingBadInternally() } catch (err) { throw new CustomError1({ info: { userId: 123 } }).withCause(err) } } try { doSomethingBad() expect.fail('should have thrown') } catch (e) { expectError(e, { name: 'CustomError1', klass: CustomError1, message: 'CustomError1: failed to foo: internal error', firstFrameRx: /doSomethingBad/ }) expect(OError.getFullInfo(e)).to.deep.equal({ userId: 123 }) const fullStack = OError.getFullStack(e) expect(fullStack).to.match( /^CustomError1: failed to foo: internal error$/m ) expect(fullStack).to.match( /^caused by: Error: internal error$/m ) } }) it('handles a custom error type with nested causes', () => { function doSomethingBadInternally () { throw new Error('internal error') } function doBar () { try { doSomethingBadInternally() } catch (err) { throw new CustomError2({ info: { database: 'a' } }).withCause(err) } } function doFoo () { try { doBar() } catch (err) { throw new CustomError1({ info: { userId: 123 } }).withCause(err) } } try { doFoo() expect.fail('should have thrown') } catch (e) { expectError(e, { name: 'CustomError1', klass: CustomError1, message: 'CustomError1: failed to foo: failed to bar: internal error', firstFrameRx: /doFoo/ }) expect(OError.getFullInfo(e)).to.deep.equal({ userId: 123, database: 'a' }) const fullStack = OError.getFullStack(e) expect(fullStack).to.match( /^CustomError1: failed to foo: failed to bar: internal error$/m ) expect(fullStack).to.match( /^caused by: CustomError2: failed to bar: internal error$/m ) expect(fullStack).to.match( /^caused by: Error: internal error$/m ) } }) it('handles a custom error without info', () => { try { throw new CustomError1({}) } catch (e) { expect(OError.getFullInfo(e)).to.deep.equal({}) let infoKey = Object.keys(e).find(k => k === 'info') expect(infoKey).to.not.exist } }) })