- 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.
		
			
				
	
	
		
			98 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { expect, tap } from '@git.zone/tstest/tapbundle';
 | |
| import { webrequest } from '../ts/index.js';
 | |
| 
 | |
| // test dependencies
 | |
| import * as typedserver from '@api.global/typedserver';
 | |
| 
 | |
| let testServer: typedserver.servertools.Server;
 | |
| 
 | |
| tap.test('setup test server', async () => {
 | |
|   testServer = new typedserver.servertools.Server({
 | |
|     cors: false,
 | |
|     forceSsl: false,
 | |
|     port: 2345,
 | |
|   });
 | |
| 
 | |
|   testServer.addRoute(
 | |
|     '/apiroute1',
 | |
|     new typedserver.servertools.Handler('GET', (req, res) => {
 | |
|       res.status(429);
 | |
|       res.end();
 | |
|     }),
 | |
|   );
 | |
| 
 | |
|   testServer.addRoute(
 | |
|     '/apiroute2',
 | |
|     new typedserver.servertools.Handler('GET', (req, res) => {
 | |
|       res.status(500);
 | |
|       res.end();
 | |
|     }),
 | |
|   );
 | |
| 
 | |
|   testServer.addRoute(
 | |
|     '/apiroute3',
 | |
|     new typedserver.servertools.Handler('GET', (req, res) => {
 | |
|       res.status(200);
 | |
|       res.send({
 | |
|         hithere: 'hi',
 | |
|       });
 | |
|     }),
 | |
|   );
 | |
| 
 | |
|   await testServer.start();
 | |
| });
 | |
| 
 | |
| 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',
 | |
|       ],
 | |
|       retry: {
 | |
|         maxAttempts: 3,
 | |
|         backoff: 'constant',
 | |
|         initialDelay: 100,
 | |
|       },
 | |
|     }
 | |
|   );
 | |
| 
 | |
|   const data = await response.json();
 | |
|   console.log('response with fallbacks: ' + JSON.stringify(data));
 | |
|   expect(data).toHaveProperty('hithere');
 | |
| });
 | |
| 
 | |
| 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 () => {
 | |
|   // 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();
 | |
| 
 | |
|   // 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');
 | |
| });
 | |
| 
 | |
| export default tap.start();
 |