feat: Implement comprehensive web request handling with caching, retry, and interceptors
- Added cache strategies: NetworkFirst, CacheFirst, StaleWhileRevalidate, NetworkOnly, and CacheOnly. - Introduced InterceptorManager for managing request, response, and error interceptors. - Developed RetryManager for handling request retries with customizable backoff strategies. - Implemented RequestDeduplicator to prevent simultaneous identical requests. - Created timeout utilities for handling request timeouts. - Enhanced WebrequestClient to support global interceptors, caching, and retry logic. - Added convenience methods for common HTTP methods (GET, POST, PUT, DELETE) with JSON handling. - Established a fetch-compatible webrequest function for seamless integration. - Defined core type structures for caching, retry options, interceptors, and web request configurations.
This commit is contained in:
		
							
								
								
									
										71
									
								
								test/test.ts
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								test/test.ts
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| import { expect, tap } from '@push.rocks/tapbundle'; | ||||
| import * as webrequest from '../ts/index.js'; | ||||
| import { expect, tap } from '@git.zone/tstest/tapbundle'; | ||||
| import { webrequest } from '../ts/index.js'; | ||||
|  | ||||
| // test dependencies | ||||
| import * as typedserver from '@api.global/typedserver'; | ||||
| @@ -18,7 +18,7 @@ tap.test('setup test server', async () => { | ||||
|     new typedserver.servertools.Handler('GET', (req, res) => { | ||||
|       res.status(429); | ||||
|       res.end(); | ||||
|     }) | ||||
|     }), | ||||
|   ); | ||||
|  | ||||
|   testServer.addRoute( | ||||
| @@ -26,7 +26,7 @@ tap.test('setup test server', async () => { | ||||
|     new typedserver.servertools.Handler('GET', (req, res) => { | ||||
|       res.status(500); | ||||
|       res.end(); | ||||
|     }) | ||||
|     }), | ||||
|   ); | ||||
|  | ||||
|   testServer.addRoute( | ||||
| @@ -36,43 +36,62 @@ tap.test('setup test server', async () => { | ||||
|       res.send({ | ||||
|         hithere: 'hi', | ||||
|       }); | ||||
|     }) | ||||
|     }), | ||||
|   ); | ||||
|  | ||||
|   await testServer.start(); | ||||
| }); | ||||
|  | ||||
| tap.test('first test', async (tools) => { | ||||
|   const response = await ( | ||||
|     await new webrequest.WebRequest().requestMultiEndpoint( | ||||
|       [ | ||||
|         'http://localhost:2345/apiroute1', | ||||
| tap.test('should handle fallback URLs', async () => { | ||||
|   const response = await webrequest( | ||||
|     'http://localhost:2345/apiroute1', | ||||
|     { | ||||
|       fallbackUrls: [ | ||||
|         'http://localhost:2345/apiroute2', | ||||
|         'http://localhost:2345/apiroute4', | ||||
|         'http://localhost:2345/apiroute3', | ||||
|       ], | ||||
|       { | ||||
|         method: 'GET', | ||||
|       } | ||||
|     ) | ||||
|   ).json(); | ||||
|       retry: { | ||||
|         maxAttempts: 3, | ||||
|         backoff: 'constant', | ||||
|         initialDelay: 100, | ||||
|       }, | ||||
|     } | ||||
|   ); | ||||
|  | ||||
|   const response2 = await new webrequest.WebRequest().getJson('http://localhost:2345/apiroute3'); | ||||
|   const data = await response.json(); | ||||
|   console.log('response with fallbacks: ' + JSON.stringify(data)); | ||||
|   expect(data).toHaveProperty('hithere'); | ||||
| }); | ||||
|  | ||||
|   console.log('response 1: ' + JSON.stringify(response)); | ||||
|   console.log('response 2: ' + JSON.stringify(response2)); | ||||
|  | ||||
|   expect(response).toHaveProperty('hithere'); //.to.equal('hi'); | ||||
|   expect(response2).toHaveProperty('hithere'); //.to.equal('hi'); | ||||
| tap.test('should use getJson convenience method', async () => { | ||||
|   const data = await webrequest.getJson('http://localhost:2345/apiroute3'); | ||||
|   console.log('getJson response: ' + JSON.stringify(data)); | ||||
|   expect(data).toHaveProperty('hithere'); | ||||
| }); | ||||
|  | ||||
| tap.test('should cache response', async () => { | ||||
|   const webrequestInstance = new webrequest.WebRequest(); | ||||
|   const response = await webrequestInstance.getJson('http://localhost:2345/apiroute3', true); | ||||
|   expect(response).toHaveProperty('hithere'); | ||||
|   // First request - goes to network | ||||
|   const response1 = await webrequest.getJson( | ||||
|     'http://localhost:2345/apiroute3', | ||||
|     { | ||||
|       cacheStrategy: 'cache-first', | ||||
|     } | ||||
|   ); | ||||
|   expect(response1).toHaveProperty('hithere'); | ||||
|  | ||||
|   // Stop server | ||||
|   await testServer.stop(); | ||||
|   const response2 = await webrequestInstance.getJson('http://localhost:2345/apiroute3', true); | ||||
|  | ||||
|   // Second request - should use cache since server is down | ||||
|   const response2 = await webrequest.getJson( | ||||
|     'http://localhost:2345/apiroute3', | ||||
|     { | ||||
|       cacheStrategy: 'network-first', // Will fallback to cache on network error | ||||
|     } | ||||
|   ); | ||||
|   expect(response2).toHaveProperty('hithere'); | ||||
|   console.log('Cache fallback worked'); | ||||
| }); | ||||
|  | ||||
| tap.start(); | ||||
| export default tap.start(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user