o-error.test.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. const OError = require('..')
  2. const { expectError } = require('./support')
  3. class CustomError1 extends OError {
  4. constructor (options) {
  5. super({ message: 'failed to foo', ...options })
  6. }
  7. }
  8. class CustomError2 extends OError {
  9. constructor (options) {
  10. super({ message: 'failed to bar', ...options })
  11. }
  12. }
  13. describe('OError', () => {
  14. it('handles a custom error type with a cause', () => {
  15. function doSomethingBadInternally () {
  16. throw new Error('internal error')
  17. }
  18. function doSomethingBad () {
  19. try {
  20. doSomethingBadInternally()
  21. } catch (err) {
  22. throw new CustomError1({ info: { userId: 123 } }).withCause(err)
  23. }
  24. }
  25. try {
  26. doSomethingBad()
  27. expect.fail('should have thrown')
  28. } catch (e) {
  29. expectError(e, {
  30. name: 'CustomError1',
  31. klass: CustomError1,
  32. message: 'CustomError1: failed to foo: internal error',
  33. firstFrameRx: /doSomethingBad/
  34. })
  35. expect(OError.getFullInfo(e)).to.deep.equal({ userId: 123 })
  36. const fullStack = OError.getFullStack(e)
  37. expect(fullStack).to.match(
  38. /^CustomError1: failed to foo: internal error$/m
  39. )
  40. expect(fullStack).to.match(
  41. /^caused by: Error: internal error$/m
  42. )
  43. }
  44. })
  45. it('handles a custom error type with nested causes', () => {
  46. function doSomethingBadInternally () {
  47. throw new Error('internal error')
  48. }
  49. function doBar () {
  50. try {
  51. doSomethingBadInternally()
  52. } catch (err) {
  53. throw new CustomError2({ info: { database: 'a' } }).withCause(err)
  54. }
  55. }
  56. function doFoo () {
  57. try {
  58. doBar()
  59. } catch (err) {
  60. throw new CustomError1({ info: { userId: 123 } }).withCause(err)
  61. }
  62. }
  63. try {
  64. doFoo()
  65. expect.fail('should have thrown')
  66. } catch (e) {
  67. expectError(e, {
  68. name: 'CustomError1',
  69. klass: CustomError1,
  70. message: 'CustomError1: failed to foo: failed to bar: internal error',
  71. firstFrameRx: /doFoo/
  72. })
  73. expect(OError.getFullInfo(e)).to.deep.equal({
  74. userId: 123,
  75. database: 'a'
  76. })
  77. const fullStack = OError.getFullStack(e)
  78. expect(fullStack).to.match(
  79. /^CustomError1: failed to foo: failed to bar: internal error$/m
  80. )
  81. expect(fullStack).to.match(
  82. /^caused by: CustomError2: failed to bar: internal error$/m
  83. )
  84. expect(fullStack).to.match(
  85. /^caused by: Error: internal error$/m
  86. )
  87. }
  88. })
  89. it('handles a custom error without info', () => {
  90. try {
  91. throw new CustomError1({})
  92. expect.fail('should have thrown')
  93. } catch (e) {
  94. expect(OError.getFullInfo(e)).to.deep.equal({})
  95. let infoKey = Object.keys(e).find(k => k === 'info')
  96. expect(infoKey).to.not.exist
  97. }
  98. })
  99. })