-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Expand file tree
/
Copy patherrors.test.ts
More file actions
129 lines (112 loc) · 4.23 KB
/
Copy patherrors.test.ts
File metadata and controls
129 lines (112 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* @vitest-environment node
*/
import { describe, expect, it } from 'vitest'
import { describeError, getPostgresErrorCode, toError } from './errors.js'
describe('toError', () => {
it('returns the same Error when given an Error', () => {
const err = new Error('test')
expect(toError(err)).toBe(err)
})
it('wraps a string into an Error', () => {
const err = toError('msg')
expect(err).toBeInstanceOf(Error)
expect(err.message).toBe('msg')
})
it('wraps a number into an Error', () => {
const err = toError(42)
expect(err).toBeInstanceOf(Error)
expect(err.message).toBe('42')
})
it('wraps null into an Error', () => {
const err = toError(null)
expect(err).toBeInstanceOf(Error)
expect(err.message).toBe('null')
})
it('wraps undefined into an Error', () => {
const err = toError(undefined)
expect(err).toBeInstanceOf(Error)
expect(err.message).toBe('undefined')
})
})
describe('getPostgresErrorCode', () => {
it('reads code from Error.code', () => {
const err = new Error('fail') as Error & { code: string }
err.code = '23505'
expect(getPostgresErrorCode(err)).toBe('23505')
})
it('reads code from plain object', () => {
expect(getPostgresErrorCode({ code: '23505' })).toBe('23505')
})
it('reads code from Error.cause', () => {
const err = new Error('fail', { cause: { code: '23505' } })
expect(getPostgresErrorCode(err)).toBe('23505')
})
it('walks nested Error causes', () => {
const pgErr = new Error('unique_violation') as Error & { code: string }
pgErr.code = '23505'
const err = new Error('outer', { cause: new Error('inner', { cause: pgErr }) })
expect(getPostgresErrorCode(err)).toBe('23505')
})
it('returns undefined for non-errors', () => {
expect(getPostgresErrorCode(undefined)).toBeUndefined()
expect(getPostgresErrorCode(null)).toBeUndefined()
expect(getPostgresErrorCode('23505')).toBeUndefined()
})
it('returns undefined when no code is present', () => {
expect(getPostgresErrorCode(new Error('no code'))).toBeUndefined()
})
it('does not loop forever on circular cause chains', () => {
const err1 = new Error('a')
const err2 = new Error('b', { cause: err1 })
// Create circular reference
;(err1 as { cause?: unknown }).cause = err2
expect(getPostgresErrorCode(err1)).toBeUndefined()
})
})
describe('describeError', () => {
it('reports name and message for a plain error, omitting causeChain', () => {
const described = describeError(new Error('boom'))
expect(described).toEqual({ name: 'Error', message: 'boom' })
expect(described.causeChain).toBeUndefined()
})
it('surfaces the deepest cause for a wrapped driver error', () => {
const driver = Object.assign(new Error('read ECONNRESET'), {
code: 'ECONNRESET',
errno: 'ECONNRESET',
syscall: 'read',
})
const wrapped = new Error('Failed query: select ...', { cause: driver })
const described = describeError(wrapped)
expect(described.message).toBe('read ECONNRESET')
expect(described.code).toBe('ECONNRESET')
expect(described.errno).toBe('ECONNRESET')
expect(described.syscall).toBe('read')
expect(described.causeChain).toEqual([
'Error: Failed query: select ...',
'Error: read ECONNRESET',
])
})
it('always returns the cause for unclassified errors (AbortError)', () => {
const aborted = Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })
expect(describeError(aborted)).toEqual({
name: 'AbortError',
message: 'The operation was aborted',
})
})
it('falls back to a populated description for non-Error input without throwing', () => {
expect(describeError('just a string')).toEqual({ name: 'Error', message: 'just a string' })
expect(() => describeError({ weird: true })).not.toThrow()
})
it('stops at depth 10 and does not loop on a cyclic cause', () => {
const a = new Error('a')
const b = new Error('b')
;(a as { cause?: unknown }).cause = b
;(b as { cause?: unknown }).cause = a
let described: ReturnType<typeof describeError> | undefined
expect(() => {
described = describeError(a)
}).not.toThrow()
expect(described?.causeChain?.length).toBeLessThanOrEqual(10)
})
})