o-error.test.js 2.7 KB

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