| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  | import { tap, expect } from '@git.zone/tstest/tapbundle'; | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  | import { SmartRequest } from '../ts/client/index.js'; | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 22:37:36 +00:00
										 |  |  | tap.test('client: should request a html document over https', async () => { | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  |   const response = await SmartRequest.create() | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |     .url('https://encrypted.google.com/') | 
					
						
							|  |  |  |     .get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-27 21:23:20 +00:00
										 |  |  |   expect(response).not.toBeNull(); | 
					
						
							|  |  |  |   expect(response).toHaveProperty('status'); | 
					
						
							|  |  |  |   expect(response.status).toBeGreaterThan(0); | 
					
						
							|  |  |  |   const text = await response.text(); | 
					
						
							|  |  |  |   expect(text.length).toBeGreaterThan(0); | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 22:37:36 +00:00
										 |  |  | tap.test('client: should request a JSON document over https', async () => { | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  |   const response = await SmartRequest.create() | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |     .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							|  |  |  |     .get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-27 21:23:20 +00:00
										 |  |  |   const body = await response.json(); | 
					
						
							|  |  |  |   expect(body).toHaveProperty('id'); | 
					
						
							|  |  |  |   expect(body.id).toEqual(1); | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 22:37:36 +00:00
										 |  |  | tap.test('client: should post a JSON document over http', async () => { | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |   const testData = { title: 'example_text', body: 'test body', userId: 1 }; | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  |   const response = await SmartRequest.create() | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |     .url('https://jsonplaceholder.typicode.com/posts') | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |     .json(testData) | 
					
						
							|  |  |  |     .post(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-27 21:23:20 +00:00
										 |  |  |   const body = await response.json(); | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |   expect(body).toHaveProperty('title'); | 
					
						
							|  |  |  |   expect(body.title).toEqual('example_text'); | 
					
						
							|  |  |  |   expect(body).toHaveProperty('id'); // jsonplaceholder returns an id for created posts
 | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 22:37:36 +00:00
										 |  |  | tap.test('client: should set headers correctly', async () => { | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |   const customHeader = 'X-Custom-Header'; | 
					
						
							|  |  |  |   const headerValue = 'test-value'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  |   const response = await SmartRequest.create() | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |     .url('https://echo.zuplo.io/') | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |     .header(customHeader, headerValue) | 
					
						
							|  |  |  |     .get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-27 21:23:20 +00:00
										 |  |  |   const body = await response.json(); | 
					
						
							|  |  |  |   expect(body).toHaveProperty('headers'); | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |   // Check if the header exists (headers might be lowercase)
 | 
					
						
							|  |  |  |   const headers = body.headers; | 
					
						
							| 
									
										
										
										
											2025-08-18 00:21:14 +00:00
										 |  |  |   const headerFound = | 
					
						
							|  |  |  |     headers[customHeader] || | 
					
						
							|  |  |  |     headers[customHeader.toLowerCase()] || | 
					
						
							|  |  |  |     headers['x-custom-header']; | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |   expect(headerFound).toEqual(headerValue); | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 22:37:36 +00:00
										 |  |  | tap.test('client: should handle query parameters', async () => { | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |   const params = { userId: '1' }; | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  |   const response = await SmartRequest.create() | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |     .url('https://jsonplaceholder.typicode.com/posts') | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |     .query(params) | 
					
						
							|  |  |  |     .get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-27 21:23:20 +00:00
										 |  |  |   const body = await response.json(); | 
					
						
							| 
									
										
										
										
											2025-07-29 13:49:50 +00:00
										 |  |  |   expect(Array.isArray(body)).toBeTrue(); | 
					
						
							|  |  |  |   // Check that we got posts for userId 1
 | 
					
						
							|  |  |  |   if (body.length > 0) { | 
					
						
							|  |  |  |     expect(body[0]).toHaveProperty('userId'); | 
					
						
							|  |  |  |     expect(body[0].userId).toEqual(1); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 22:37:36 +00:00
										 |  |  | tap.test('client: should handle timeout configuration', async () => { | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |   // This test just verifies that the timeout method doesn't throw
 | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  |   const client = SmartRequest.create() | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  |     .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |     .timeout(5000); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const response = await client.get(); | 
					
						
							| 
									
										
										
										
											2025-07-27 21:23:20 +00:00
										 |  |  |   expect(response).toHaveProperty('ok'); | 
					
						
							|  |  |  |   expect(response.ok).toBeTrue(); | 
					
						
							| 
									
										
										
										
											2025-08-18 00:21:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 15:44:04 +00:00
										 |  |  |   // Consume the body to prevent socket hanging
 | 
					
						
							|  |  |  |   await response.text(); | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-28 22:37:36 +00:00
										 |  |  | tap.test('client: should handle retry configuration', async () => { | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |   // This test just verifies that the retry method doesn't throw
 | 
					
						
							| 
									
										
										
										
											2025-07-28 23:20:52 +00:00
										 |  |  |   const client = SmartRequest.create() | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  |     .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  |     .retry(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const response = await client.get(); | 
					
						
							| 
									
										
										
										
											2025-07-27 21:23:20 +00:00
										 |  |  |   expect(response).toHaveProperty('ok'); | 
					
						
							|  |  |  |   expect(response.ok).toBeTrue(); | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 15:44:04 +00:00
										 |  |  |   // Consume the body to prevent socket hanging
 | 
					
						
							|  |  |  |   await response.text(); | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-18 00:21:14 +00:00
										 |  |  | tap.test( | 
					
						
							|  |  |  |   'client: should support keepAlive option for connection reuse', | 
					
						
							|  |  |  |   async () => { | 
					
						
							|  |  |  |     // Simple test
 | 
					
						
							|  |  |  |     const response = await SmartRequest.create() | 
					
						
							|  |  |  |       .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							|  |  |  |       .options({ keepAlive: true }) | 
					
						
							|  |  |  |       .get(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(response.ok).toBeTrue(); | 
					
						
							|  |  |  |     await response.text(); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | tap.test( | 
					
						
							|  |  |  |   'client: should handle 429 rate limiting with default config', | 
					
						
							|  |  |  |   async () => { | 
					
						
							|  |  |  |     // Test that handle429Backoff can be configured without errors
 | 
					
						
							|  |  |  |     const client = SmartRequest.create() | 
					
						
							|  |  |  |       .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							|  |  |  |       .handle429Backoff(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const response = await client.get(); | 
					
						
							|  |  |  |     expect(response.status).toEqual(200); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Consume the body to prevent socket hanging
 | 
					
						
							|  |  |  |     await response.text(); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  | tap.test('client: should handle 429 with custom config', async () => { | 
					
						
							|  |  |  |   let rateLimitCallbackCalled = false; | 
					
						
							|  |  |  |   let attemptCount = 0; | 
					
						
							|  |  |  |   let waitTimeReceived = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const client = SmartRequest.create() | 
					
						
							|  |  |  |     .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							|  |  |  |     .handle429Backoff({ | 
					
						
							|  |  |  |       maxRetries: 2, | 
					
						
							|  |  |  |       fallbackDelay: 500, | 
					
						
							|  |  |  |       maxWaitTime: 5000, | 
					
						
							|  |  |  |       onRateLimit: (attempt, waitTime) => { | 
					
						
							|  |  |  |         rateLimitCallbackCalled = true; | 
					
						
							|  |  |  |         attemptCount = attempt; | 
					
						
							|  |  |  |         waitTimeReceived = waitTime; | 
					
						
							| 
									
										
										
										
											2025-08-18 00:21:14 +00:00
										 |  |  |       }, | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const response = await client.get(); | 
					
						
							|  |  |  |   expect(response.status).toEqual(200); | 
					
						
							| 
									
										
										
										
											2025-08-18 00:21:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  |   // The callback should not have been called for a 200 response
 | 
					
						
							|  |  |  |   expect(rateLimitCallbackCalled).toBeFalse(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-29 15:44:04 +00:00
										 |  |  |   // Consume the body to prevent socket hanging
 | 
					
						
							|  |  |  |   await response.text(); | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-18 00:21:14 +00:00
										 |  |  | tap.test( | 
					
						
							|  |  |  |   'client: should respect Retry-After header format (seconds)', | 
					
						
							|  |  |  |   async () => { | 
					
						
							|  |  |  |     // Test the configuration works - actual 429 testing would require a mock server
 | 
					
						
							|  |  |  |     const client = SmartRequest.create() | 
					
						
							|  |  |  |       .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							|  |  |  |       .handle429Backoff({ | 
					
						
							|  |  |  |         maxRetries: 1, | 
					
						
							|  |  |  |         respectRetryAfter: true, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const response = await client.get(); | 
					
						
							|  |  |  |     expect(response.ok).toBeTrue(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Consume the body to prevent socket hanging
 | 
					
						
							|  |  |  |     await response.text(); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | tap.test( | 
					
						
							|  |  |  |   'client: should handle rate limiting with exponential backoff', | 
					
						
							|  |  |  |   async () => { | 
					
						
							|  |  |  |     // Test exponential backoff configuration
 | 
					
						
							|  |  |  |     const client = SmartRequest.create() | 
					
						
							|  |  |  |       .url('https://jsonplaceholder.typicode.com/posts/1') | 
					
						
							|  |  |  |       .handle429Backoff({ | 
					
						
							|  |  |  |         maxRetries: 3, | 
					
						
							|  |  |  |         fallbackDelay: 100, | 
					
						
							|  |  |  |         backoffFactor: 2, | 
					
						
							|  |  |  |         maxWaitTime: 1000, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const response = await client.get(); | 
					
						
							|  |  |  |     expect(response.status).toEqual(200); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Consume the body to prevent socket hanging
 | 
					
						
							|  |  |  |     await response.text(); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | tap.test( | 
					
						
							|  |  |  |   'client: should not retry non-429 errors with rate limit handler', | 
					
						
							|  |  |  |   async () => { | 
					
						
							|  |  |  |     // Test that 404 errors are not retried by rate limit handler
 | 
					
						
							|  |  |  |     const client = SmartRequest.create() | 
					
						
							|  |  |  |       .url('https://jsonplaceholder.typicode.com/posts/999999') | 
					
						
							|  |  |  |       .handle429Backoff(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const response = await client.get(); | 
					
						
							|  |  |  |     expect(response.status).toEqual(404); | 
					
						
							|  |  |  |     expect(response.ok).toBeFalse(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Consume the body to prevent socket hanging
 | 
					
						
							|  |  |  |     await response.text(); | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  | ); | 
					
						
							| 
									
										
										
										
											2025-07-29 13:19:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-03 06:52:58 +00:00
										 |  |  | tap.start(); |