@@ -13,6 +13,12 @@ describe('VantigeHttpClient', () => {
1313 let mockAxiosInstance : any ;
1414
1515 beforeEach ( ( ) => {
16+ // Mock setTimeout to make retry delays instant
17+ jest . spyOn ( global , 'setTimeout' ) . mockImplementation ( ( fn ) => {
18+ fn ( ) ;
19+ return { } as any ;
20+ } ) ;
21+
1622 mockAuth = {
1723 getAuthHeaders : jest . fn ( ) . mockReturnValue ( {
1824 'Authorization' : 'Bearer test-token' ,
@@ -39,23 +45,24 @@ describe('VantigeHttpClient', () => {
3945
4046 httpClient = new VantigeHttpClient ( {
4147 baseUrl : 'https://api.vantige.ai' ,
42- timeout : 30000 ,
43- retries : 3 ,
48+ timeout : 1000 , // Much shorter timeout for tests
49+ retries : 2 , // Fewer retries for faster tests
4450 auth : mockAuth ,
4551 debug : false ,
4652 } ) ;
4753 } ) ;
4854
4955 afterEach ( ( ) => {
5056 jest . clearAllMocks ( ) ;
57+ jest . restoreAllMocks ( ) ;
5158 } ) ;
5259
5360 describe ( 'Constructor' , ( ) => {
5461 it ( 'should create HTTP client with correct configuration' , ( ) => {
5562 expect ( httpClient ) . toBeInstanceOf ( VantigeHttpClient ) ;
5663 expect ( mockedAxios . create ) . toHaveBeenCalledWith ( {
5764 baseURL : 'https://api.vantige.ai' ,
58- timeout : 30000 ,
65+ timeout : 1000 ,
5966 headers : {
6067 'Authorization' : 'Bearer test-token' ,
6168 'Content-Type' : 'application/json' ,
@@ -70,6 +77,13 @@ describe('VantigeHttpClient', () => {
7077 } ) ;
7178
7279 describe ( 'Error Handling' , ( ) => {
80+ it ( 'should pass through existing VantigeSDKError without wrapping' , async ( ) => {
81+ const existing = new VantigeSDKError ( 'Existing' , VantigeErrorCode . NETWORK_ERROR ) ;
82+ mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( existing ) ;
83+
84+ await expect ( httpClient . get ( '/test' ) ) . rejects . toBe ( existing ) ;
85+ } ) ;
86+
7387 it ( 'should handle network timeout errors' , async ( ) => {
7488 const timeoutError = new Error ( 'timeout of 30000ms exceeded' ) as AxiosError ;
7589 timeoutError . code = 'ECONNABORTED' ;
@@ -78,7 +92,7 @@ describe('VantigeHttpClient', () => {
7892 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( timeoutError ) ;
7993
8094 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
81- } , 10000 ) ;
95+ } ) ;
8296
8397 it ( 'should handle network errors without response' , async ( ) => {
8498 const networkError = new Error ( 'Network Error' ) as AxiosError ;
@@ -88,7 +102,7 @@ describe('VantigeHttpClient', () => {
88102 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( networkError ) ;
89103
90104 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
91- } , 10000 ) ;
105+ } ) ;
92106
93107 it ( 'should handle 401 Unauthorized errors' , async ( ) => {
94108 const unauthorizedError = {
@@ -102,7 +116,7 @@ describe('VantigeHttpClient', () => {
102116 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( unauthorizedError ) ;
103117
104118 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
105- } , 10000 ) ;
119+ } ) ;
106120
107121 it ( 'should handle 403 Forbidden errors' , async ( ) => {
108122 const forbiddenError = {
@@ -116,7 +130,7 @@ describe('VantigeHttpClient', () => {
116130 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( forbiddenError ) ;
117131
118132 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
119- } , 10000 ) ;
133+ } ) ;
120134
121135 it ( 'should handle 404 Not Found errors' , async ( ) => {
122136 const notFoundError = {
@@ -130,7 +144,7 @@ describe('VantigeHttpClient', () => {
130144 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( notFoundError ) ;
131145
132146 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
133- } , 10000 ) ;
147+ } ) ;
134148
135149 it ( 'should handle 422 Validation errors' , async ( ) => {
136150 const validationError = {
@@ -144,7 +158,7 @@ describe('VantigeHttpClient', () => {
144158 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( validationError ) ;
145159
146160 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
147- } , 10000 ) ;
161+ } ) ;
148162
149163 it ( 'should handle 429 Rate Limit errors' , async ( ) => {
150164 const rateLimitError = {
@@ -158,7 +172,7 @@ describe('VantigeHttpClient', () => {
158172 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( rateLimitError ) ;
159173
160174 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
161- } , 10000 ) ;
175+ } ) ;
162176
163177 it ( 'should handle 500 Internal Server errors' , async ( ) => {
164178 const serverError = {
@@ -172,7 +186,7 @@ describe('VantigeHttpClient', () => {
172186 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( serverError ) ;
173187
174188 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
175- } , 10000 ) ;
189+ } ) ;
176190
177191 it ( 'should handle 503 Service Unavailable errors' , async ( ) => {
178192 const serviceUnavailableError = {
@@ -186,7 +200,7 @@ describe('VantigeHttpClient', () => {
186200 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( serviceUnavailableError ) ;
187201
188202 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
189- } , 10000 ) ;
203+ } ) ;
190204
191205 it ( 'should handle unknown HTTP errors' , async ( ) => {
192206 const unknownError = {
@@ -200,18 +214,33 @@ describe('VantigeHttpClient', () => {
200214 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( unknownError ) ;
201215
202216 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
203- } , 10000 ) ;
217+ } ) ;
204218
205219 it ( 'should handle non-axios errors' , async ( ) => {
206220 const genericError = new Error ( 'Generic error' ) ;
207221
208222 mockAxiosInstance . get = jest . fn ( ) . mockRejectedValue ( genericError ) ;
209223
210224 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
211- } , 10000 ) ;
225+ } ) ;
212226 } ) ;
213227
214228 describe ( 'Retry Logic' , ( ) => {
229+ it ( 'should throw after exhausting retries' , async ( ) => {
230+ const networkError = new Error ( 'Network Error' ) as AxiosError ;
231+ networkError . isAxiosError = true ;
232+ networkError . response = undefined ;
233+
234+ mockAxiosInstance . get = jest . fn ( )
235+ . mockRejectedValueOnce ( networkError )
236+ . mockRejectedValueOnce ( networkError )
237+ . mockRejectedValueOnce ( networkError )
238+ . mockRejectedValueOnce ( networkError ) ;
239+
240+ await expect ( httpClient . get ( '/test' ) ) . rejects . toBeInstanceOf ( VantigeSDKError ) ;
241+ expect ( mockAxiosInstance . get ) . toHaveBeenCalled ( ) ;
242+ } ) ;
243+
215244 it ( 'should retry on network errors' , async ( ) => {
216245 const networkError = new Error ( 'Network Error' ) as AxiosError ;
217246 networkError . isAxiosError = true ;
@@ -227,7 +256,7 @@ describe('VantigeHttpClient', () => {
227256 const result = await httpClient . get ( '/test' ) ;
228257 expect ( result ) . toEqual ( successResponse ) ;
229258 expect ( mockAxiosInstance . get ) . toHaveBeenCalledTimes ( 3 ) ;
230- } , 10000 ) ;
259+ } ) ;
231260
232261 it ( 'should not retry on authentication errors' , async ( ) => {
233262 const authError = {
@@ -247,7 +276,7 @@ describe('VantigeHttpClient', () => {
247276
248277 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
249278 expect ( mockAxiosInstance . get ) . toHaveBeenCalledTimes ( 1 ) ;
250- } , 10000 ) ;
279+ } ) ;
251280
252281 it ( 'should not retry on validation errors' , async ( ) => {
253282 const validationError = {
@@ -267,7 +296,7 @@ describe('VantigeHttpClient', () => {
267296
268297 await expect ( httpClient . get ( '/test' ) ) . rejects . toThrow ( VantigeSDKError ) ;
269298 expect ( mockAxiosInstance . get ) . toHaveBeenCalledTimes ( 1 ) ;
270- } , 10000 ) ;
299+ } ) ;
271300
272301 it ( 'should retry on rate limit errors with delay' , async ( ) => {
273302 const rateLimitError = {
@@ -288,21 +317,32 @@ describe('VantigeHttpClient', () => {
288317 . mockRejectedValueOnce ( rateLimitError )
289318 . mockResolvedValueOnce ( { data : successResponse } ) ;
290319
291- // Mock setTimeout to avoid actual delays in tests
292- jest . spyOn ( global , 'setTimeout' ) . mockImplementation ( ( fn ) => {
293- fn ( ) ;
294- return { } as any ;
295- } ) ;
296-
297320 const result = await httpClient . get ( '/test' ) ;
298321 expect ( result ) . toEqual ( successResponse ) ;
299322 expect ( mockAxiosInstance . get ) . toHaveBeenCalledTimes ( 2 ) ;
300-
301- jest . restoreAllMocks ( ) ;
302- } , 10000 ) ;
323+ } ) ;
303324 } ) ;
304325
305326 describe ( 'HTTP Methods' , ( ) => {
327+ it ( 'should use interceptor success handler to return response unmodified' , ( ) => {
328+ const handlers : any = { } ;
329+ mockAxiosInstance . interceptors . response . use = jest . fn ( ( success : any , fail : any ) => {
330+ handlers . success = success ;
331+ handlers . fail = fail ;
332+ } ) ;
333+
334+ // Recreate client to register interceptor with captured handlers
335+ httpClient = new VantigeHttpClient ( {
336+ baseUrl : 'https://api.vantige.ai' ,
337+ timeout : 1000 ,
338+ retries : 2 ,
339+ auth : mockAuth ,
340+ } ) ;
341+
342+ const resp = { data : { ok : true } } as any ;
343+ const result = handlers . success ( resp ) ;
344+ expect ( result ) . toBe ( resp ) ;
345+ } ) ;
306346 it ( 'should make GET requests' , async ( ) => {
307347 const mockResponse = { success : true } ;
308348 mockAxiosInstance . get = jest . fn ( ) . mockResolvedValue ( { data : mockResponse } ) ;
0 commit comments