11/**
2- * Tests for error handling system
2+ * Tests for error handling system - Consolidated
33 */
44
55import { describe , it , expect } from 'vitest' ;
@@ -14,20 +14,17 @@ import {
1414 getErrorMessage ,
1515 wrapError ,
1616 getUserFriendlyMessage ,
17- createErrorHandler ,
1817} from '../index.js' ;
1918import {
20- safeExecute ,
2119 safeExecuteSync ,
2220 executeWithFallback ,
2321 extractError ,
2422 isNetworkError ,
25- toTypedError ,
2623 assertCondition ,
2724 assertDefined ,
2825} from '../error-utils.js' ;
2926
30- describe ( 'Error System ' , ( ) => {
27+ describe ( 'Error Types ' , ( ) => {
3128 it ( 'should create StackMemoryError with all properties' , ( ) => {
3229 const cause = new Error ( 'Original error' ) ;
3330 const error = new StackMemoryError ( {
@@ -40,281 +37,108 @@ describe('Error System', () => {
4037 } ) ;
4138
4239 expect ( error ) . toBeInstanceOf ( Error ) ;
43- expect ( error . message ) . toBe ( 'Test error' ) ;
44- expect ( error . name ) . toBe ( 'StackMemoryError' ) ;
4540 expect ( error . code ) . toBe ( ErrorCode . VALIDATION_FAILED ) ;
46- expect ( error . context ) . toEqual ( { field : 'test' } ) ;
47- expect ( error . cause ) . toBe ( cause ) ;
4841 expect ( error . isRetryable ) . toBe ( true ) ;
4942 expect ( error . httpStatus ) . toBe ( 400 ) ;
50- expect ( error . timestamp ) . toBeInstanceOf ( Date ) ;
43+ expect ( error . toJSON ( ) . name ) . toBe ( 'StackMemoryError' ) ;
5144 } ) ;
5245
53- it ( 'should handle error codes' , ( ) => {
54- expect ( ErrorCode . VALIDATION_FAILED ) . toBe ( 'VAL_001' ) ;
55- expect ( ErrorCode . DB_CONNECTION_FAILED ) . toBe ( 'DB_001' ) ;
56- expect ( ErrorCode . LINEAR_AUTH_FAILED ) . toBe ( 'LINEAR_001' ) ;
57- } ) ;
58-
59- it ( 'should create specialized error types' , ( ) => {
60- const dbError = new DatabaseError ( 'DB failed' , ErrorCode . DB_QUERY_FAILED ) ;
61- expect ( dbError . httpStatus ) . toBe ( 503 ) ;
62-
63- const integrationError = new IntegrationError ( 'API failed' ) ;
64- expect ( integrationError . isRetryable ) . toBe ( true ) ;
65- expect ( integrationError . httpStatus ) . toBe ( 502 ) ;
66-
67- const validationError = new ValidationError ( 'Invalid input' ) ;
68- expect ( validationError . isRetryable ) . toBe ( false ) ;
69- expect ( validationError . httpStatus ) . toBe ( 400 ) ;
70-
71- const systemError = new SystemError ( 'Internal error' ) ;
72- expect ( systemError . httpStatus ) . toBe ( 500 ) ;
73- } ) ;
74-
75- it ( 'should serialize error to JSON' , ( ) => {
76- const error = new StackMemoryError ( {
77- message : 'Test' ,
78- code : ErrorCode . INTERNAL_ERROR ,
79- } ) ;
80-
81- const json = error . toJSON ( ) ;
82- expect ( json . name ) . toBe ( 'StackMemoryError' ) ;
83- expect ( json . code ) . toBe ( ErrorCode . INTERNAL_ERROR ) ;
84- expect ( json . message ) . toBe ( 'Test' ) ;
85- expect ( json . timestamp ) . toBeDefined ( ) ;
46+ it ( 'should create specialized error types with correct defaults' , ( ) => {
47+ expect (
48+ new DatabaseError ( 'DB failed' , ErrorCode . DB_QUERY_FAILED ) . httpStatus
49+ ) . toBe ( 503 ) ;
50+ expect ( new IntegrationError ( 'API failed' ) . isRetryable ) . toBe ( true ) ;
51+ expect ( new ValidationError ( 'Invalid input' ) . isRetryable ) . toBe ( false ) ;
52+ expect ( new SystemError ( 'Internal error' ) . httpStatus ) . toBe ( 500 ) ;
8653 } ) ;
8754} ) ;
8855
8956describe ( 'Error Utilities' , ( ) => {
90- describe ( 'isRetryableError' , ( ) => {
91- it ( 'should identify retryable StackMemoryError' , ( ) => {
92- const retryable = new IntegrationError ( 'API failed' ) ;
93- expect ( isRetryableError ( retryable ) ) . toBe ( true ) ;
94-
95- const nonRetryable = new ValidationError ( 'Invalid' ) ;
96- expect ( isRetryableError ( nonRetryable ) ) . toBe ( false ) ;
97- } ) ;
98-
99- it ( 'should identify network errors as retryable' , ( ) => {
100- expect ( isRetryableError ( new Error ( 'ECONNREFUSED' ) ) ) . toBe ( true ) ;
101- expect ( isRetryableError ( new Error ( 'Socket hang up' ) ) ) . toBe ( true ) ;
102- expect ( isRetryableError ( new Error ( 'Timeout' ) ) ) . toBe ( true ) ;
103- } ) ;
104- } ) ;
105-
106- describe ( 'getErrorMessage' , ( ) => {
107- it ( 'should extract message from Error' , ( ) => {
108- expect ( getErrorMessage ( new Error ( 'Test' ) ) ) . toBe ( 'Test' ) ;
109- } ) ;
110-
111- it ( 'should handle string errors' , ( ) => {
112- expect ( getErrorMessage ( 'String error' ) ) . toBe ( 'String error' ) ;
113- } ) ;
114-
115- it ( 'should handle unknown errors' , ( ) => {
116- expect ( getErrorMessage ( null ) ) . toBe ( 'An unknown error occurred' ) ;
117- expect ( getErrorMessage ( undefined ) ) . toBe ( 'An unknown error occurred' ) ;
118- expect ( getErrorMessage ( 42 ) ) . toBe ( 'An unknown error occurred' ) ;
119- } ) ;
120-
121- it ( 'should handle objects with message property' , ( ) => {
122- expect ( getErrorMessage ( { message : 'Object error' } ) ) . toBe ( 'Object error' ) ;
123- } ) ;
57+ it ( 'should identify retryable errors' , ( ) => {
58+ expect ( isRetryableError ( new IntegrationError ( 'API failed' ) ) ) . toBe ( true ) ;
59+ expect ( isRetryableError ( new ValidationError ( 'Invalid' ) ) ) . toBe ( false ) ;
60+ expect ( isRetryableError ( new Error ( 'ECONNREFUSED' ) ) ) . toBe ( true ) ;
12461 } ) ;
12562
126- describe ( 'wrapError' , ( ) => {
127- it ( 'should return StackMemoryError unchanged' , ( ) => {
128- const original = new ValidationError ( 'Test' ) ;
129- expect ( wrapError ( original , 'Default' ) ) . toBe ( original ) ;
130- } ) ;
131-
132- it ( 'should wrap regular Error' , ( ) => {
133- const original = new Error ( 'Original' ) ;
134- const wrapped = wrapError ( original , 'Default' ) ;
135-
136- expect ( wrapped ) . toBeInstanceOf ( SystemError ) ;
137- expect ( wrapped . message ) . toBe ( 'Original' ) ;
138- expect ( wrapped . cause ) . toBe ( original ) ;
139- } ) ;
140-
141- it ( 'should use default message for non-Error' , ( ) => {
142- const wrapped = wrapError ( 'string' , 'Default message' ) ;
143- expect ( wrapped . message ) . toBe ( 'Default message' ) ;
144- } ) ;
63+ it ( 'should extract error messages' , ( ) => {
64+ expect ( getErrorMessage ( new Error ( 'Test' ) ) ) . toBe ( 'Test' ) ;
65+ expect ( getErrorMessage ( 'String error' ) ) . toBe ( 'String error' ) ;
66+ expect ( getErrorMessage ( null ) ) . toContain ( 'error' ) ;
14567 } ) ;
14668
147- describe ( 'getUserFriendlyMessage' , ( ) => {
148- it ( 'should return friendly messages for known codes' , ( ) => {
149- expect ( getUserFriendlyMessage ( ErrorCode . AUTH_FAILED ) ) . toContain (
150- 'Authentication'
151- ) ;
152- expect ( getUserFriendlyMessage ( ErrorCode . FILE_NOT_FOUND ) ) . toContain (
153- 'not found'
154- ) ;
155- expect ( getUserFriendlyMessage ( ErrorCode . NETWORK_ERROR ) ) . toContain (
156- 'internet'
157- ) ;
158- } ) ;
159-
160- it ( 'should return generic message for unknown codes' , ( ) => {
161- const msg = getUserFriendlyMessage ( 'UNKNOWN_CODE' as ErrorCode ) ;
162- expect ( msg ) . toContain ( 'unexpected error' ) ;
163- } ) ;
69+ it ( 'should wrap errors with context' , ( ) => {
70+ const original = new Error ( 'Original' ) ;
71+ const wrapped = wrapError ( original , 'Context message' ) ;
72+ expect ( wrapped ) . toBeInstanceOf ( StackMemoryError ) ;
16473 } ) ;
16574
166- describe ( 'createErrorHandler' , ( ) => {
167- it ( 'should merge context' , ( ) => {
168- const handler = createErrorHandler ( { component : 'test' } ) ;
169- const error = new ValidationError ( 'Test' ) ;
170- const handled = handler ( error , { operation : 'validate' } ) ;
171-
172- expect ( handled . context ?. component ) . toBe ( 'test' ) ;
173- expect ( handled . context ?. operation ) . toBe ( 'validate' ) ;
174- } ) ;
75+ it ( 'should provide user-friendly messages' , ( ) => {
76+ const dbError = new DatabaseError (
77+ 'Connection refused' ,
78+ ErrorCode . DB_CONNECTION_FAILED
79+ ) ;
80+ const message = getUserFriendlyMessage ( dbError ) ;
81+ expect ( message ) . toBeDefined ( ) ;
17582 } ) ;
17683} ) ;
17784
178- describe ( 'Error Utils' , ( ) => {
179- describe ( 'safeExecute' , ( ) => {
180- it ( 'should return result on success' , async ( ) => {
181- const result = await safeExecute ( async ( ) => 'success' , {
182- operation : 'test' ,
183- component : 'test' ,
184- } ) ;
185- expect ( result ) . toBe ( 'success' ) ;
186- } ) ;
187-
188- it ( 'should return undefined on failure' , async ( ) => {
189- const result = await safeExecute (
190- async ( ) => {
191- throw new Error ( 'fail' ) ;
192- } ,
193- { operation : 'test' , component : 'test' }
194- ) ;
195- expect ( result ) . toBeUndefined ( ) ;
196- } ) ;
85+ describe ( 'Safe Execution' , ( ) => {
86+ const context = { component : 'test' , operation : 'test' } ;
19787
198- it ( 'should return default value on failure' , async ( ) => {
199- const result = await safeExecute (
200- async ( ) => {
201- throw new Error ( 'fail' ) ;
202- } ,
203- { operation : 'test' , component : 'test' } ,
204- 'default'
205- ) ;
206- expect ( result ) . toBe ( 'default' ) ;
207- } ) ;
88+ it ( 'should execute sync safely and return result' , ( ) => {
89+ const result = safeExecuteSync ( ( ) => 42 , context ) ;
90+ expect ( result ) . toBe ( 42 ) ;
20891 } ) ;
20992
210- describe ( 'safeExecuteSync' , ( ) => {
211- it ( 'should handle sync operations' , ( ) => {
212- const result = safeExecuteSync ( ( ) => 'success' , {
213- operation : 'test' ,
214- component : 'test' ,
215- } ) ;
216- expect ( result ) . toBe ( 'success' ) ;
217- } ) ;
218-
219- it ( 'should return default on failure' , ( ) => {
220- const result = safeExecuteSync (
221- ( ) => {
222- throw new Error ( 'fail' ) ;
223- } ,
224- { operation : 'test' , component : 'test' } ,
225- 'default'
226- ) ;
227- expect ( result ) . toBe ( 'default' ) ;
228- } ) ;
93+ it ( 'should return undefined on sync error' , ( ) => {
94+ const result = safeExecuteSync ( ( ) => {
95+ throw new Error ( 'Sync failure' ) ;
96+ } , context ) ;
97+ expect ( result ) . toBeUndefined ( ) ;
22998 } ) ;
23099
231- describe ( 'executeWithFallback' , ( ) => {
232- it ( 'should return null on failure' , async ( ) => {
233- const result = await executeWithFallback (
234- async ( ) => {
235- throw new Error ( 'fail' ) ;
236- } ,
237- { operation : 'test' , component : 'test' }
238- ) ;
239- expect ( result ) . toBeNull ( ) ;
240- } ) ;
100+ it ( 'should execute with fallback returning null on error' , async ( ) => {
101+ const result = await executeWithFallback ( async ( ) => {
102+ throw new Error ( 'Failed' ) ;
103+ } , context ) ;
104+ expect ( result ) . toBeNull ( ) ;
241105 } ) ;
106+ } ) ;
242107
243- describe ( 'extractError' , ( ) => {
244- it ( 'should extract from StackMemoryError' , ( ) => {
245- const error = new IntegrationError (
246- 'API failed' ,
247- ErrorCode . LINEAR_API_ERROR
248- ) ;
249- const extracted = extractError ( error ) ;
250-
251- expect ( extracted . message ) . toBe ( 'API failed' ) ;
252- expect ( extracted . code ) . toBe ( ErrorCode . LINEAR_API_ERROR ) ;
253- expect ( extracted . isRetryable ) . toBe ( true ) ;
254- } ) ;
255-
256- it ( 'should extract from regular Error' , ( ) => {
257- const error = new Error ( 'Regular error' ) ;
258- const extracted = extractError ( error ) ;
259-
260- expect ( extracted . message ) . toBe ( 'Regular error' ) ;
261- expect ( extracted . cause ) . toBe ( error ) ;
262- } ) ;
263-
264- it ( 'should handle non-Error values' , ( ) => {
265- expect ( extractError ( 'string' ) . message ) . toBe ( 'string' ) ;
266- expect ( extractError ( null ) . message ) . toBe ( 'Unknown error' ) ;
267- } ) ;
108+ describe ( 'Assertions' , ( ) => {
109+ it ( 'should assert conditions' , ( ) => {
110+ expect ( ( ) => assertCondition ( true , 'Should pass' ) ) . not . toThrow ( ) ;
111+ expect ( ( ) => assertCondition ( false , 'Should fail' ) ) . toThrow (
112+ StackMemoryError
113+ ) ;
268114 } ) ;
269115
270- describe ( 'isNetworkError' , ( ) => {
271- it ( 'should identify network errors' , ( ) => {
272- expect ( isNetworkError ( new Error ( 'ECONNREFUSED' ) ) ) . toBe ( true ) ;
273- expect ( isNetworkError ( new Error ( 'ENOTFOUND' ) ) ) . toBe ( true ) ;
274- expect ( isNetworkError ( new Error ( 'timeout' ) ) ) . toBe ( true ) ;
275- expect ( isNetworkError ( new Error ( 'socket hang up' ) ) ) . toBe ( true ) ;
276- expect ( isNetworkError ( new Error ( 'ECONNRESET' ) ) ) . toBe ( true ) ;
277- } ) ;
278-
279- it ( 'should return false for non-network errors' , ( ) => {
280- expect ( isNetworkError ( new Error ( 'Validation failed' ) ) ) . toBe ( false ) ;
281- expect ( isNetworkError ( 'string' ) ) . toBe ( false ) ;
282- } ) ;
116+ it ( 'should assert defined values' , ( ) => {
117+ assertDefined ( 'value' , 'test' ) ; // Should not throw
118+ expect ( ( ) => assertDefined ( undefined , 'undefined test' ) ) . toThrow (
119+ StackMemoryError
120+ ) ;
121+ expect ( ( ) => assertDefined ( null , 'null test' ) ) . toThrow ( StackMemoryError ) ;
283122 } ) ;
123+ } ) ;
284124
285- describe ( 'toTypedError' , ( ) => {
286- it ( 'should return StackMemoryError unchanged' , ( ) => {
287- const error = new ValidationError ( 'Test' ) ;
288- expect ( toTypedError ( error ) ) . toBe ( error ) ;
289- } ) ;
290-
291- it ( 'should wrap unknown errors' , ( ) => {
292- const wrapped = toTypedError ( new Error ( 'test' ) , ErrorCode . API_ERROR ) ;
293- expect ( wrapped ) . toBeInstanceOf ( SystemError ) ;
294- expect ( wrapped . code ) . toBe ( ErrorCode . API_ERROR ) ;
295- } ) ;
125+ describe ( 'Network Error Detection' , ( ) => {
126+ it ( 'should identify network errors' , ( ) => {
127+ expect ( isNetworkError ( new Error ( 'econnrefused' ) ) ) . toBe ( true ) ;
128+ expect ( isNetworkError ( new Error ( 'timeout occurred' ) ) ) . toBe ( true ) ;
129+ expect ( isNetworkError ( new Error ( 'Regular error' ) ) ) . toBe ( false ) ;
296130 } ) ;
131+ } ) ;
297132
298- describe ( 'assertCondition' , ( ) => {
299- it ( 'should not throw when condition is true' , ( ) => {
300- expect ( ( ) => assertCondition ( true , 'Test' ) ) . not . toThrow ( ) ;
301- } ) ;
302-
303- it ( 'should throw when condition is false' , ( ) => {
304- expect ( ( ) => assertCondition ( false , 'Test' ) ) . toThrow ( StackMemoryError ) ;
305- } ) ;
306- } ) ;
133+ describe ( 'extractError' , ( ) => {
134+ it ( 'should extract error details' , ( ) => {
135+ const extracted = extractError ( new Error ( 'Test' ) ) ;
136+ expect ( extracted . message ) . toBe ( 'Test' ) ;
307137
308- describe ( 'assertDefined' , ( ) => {
309- it ( 'should not throw for defined values' , ( ) => {
310- expect ( ( ) => assertDefined ( 'value' , 'Test' ) ) . not . toThrow ( ) ;
311- expect ( ( ) => assertDefined ( 0 , 'Test' ) ) . not . toThrow ( ) ;
312- expect ( ( ) => assertDefined ( '' , 'Test' ) ) . not . toThrow ( ) ;
313- } ) ;
138+ const extracted2 = extractError ( 'String error' ) ;
139+ expect ( extracted2 . message ) . toBe ( 'String error' ) ;
314140
315- it ( 'should throw for null or undefined' , ( ) => {
316- expect ( ( ) => assertDefined ( null , 'Test' ) ) . toThrow ( StackMemoryError ) ;
317- expect ( ( ) => assertDefined ( undefined , 'Test' ) ) . toThrow ( StackMemoryError ) ;
318- } ) ;
141+ const extracted3 = extractError ( null ) ;
142+ expect ( extracted3 . message ) . toContain ( 'error' ) ;
319143 } ) ;
320144} ) ;
0 commit comments