UNPKG

@dbs-portal/core-api

Version:

HTTP client and API utilities for DBS Portal

183 lines 6.28 kB
/** * MSW simulation utilities for delays, errors, and network conditions */ import { createErrorResponse } from './response-builder'; /** * Simulate network delay */ export async function simulateDelay(delay) { const ms = Array.isArray(delay) ? Math.floor(Math.random() * (delay[1] - delay[0] + 1)) + delay[0] : delay; if (ms > 0) { await new Promise(resolve => setTimeout(resolve, ms)); } } /** * Simulate network error based on configuration */ export async function simulateError(request, config = {}) { const { networkErrorRate = 0, serverErrorRate = 0, timeoutErrorRate = 0, customErrors = [], } = config; // Check custom error scenarios first for (const scenario of customErrors) { const shouldTrigger = Math.random() < (scenario.probability || 1); if (!shouldTrigger) continue; const matches = typeof scenario.pattern === 'string' ? request.url.pathname.includes(scenario.pattern) : scenario.pattern.test(request.url.pathname); if (matches && (!scenario.method || scenario.method === request.method)) { const error = typeof scenario.error === 'function' ? scenario.error() : scenario.error; return createErrorResponse(error); } } // Network errors (connection issues) if (Math.random() < networkErrorRate) { return createErrorResponse({ code: 'NETWORK_ERROR', message: 'Network connection failed', }, { status: 0 }); // Status 0 indicates network error } // Timeout errors if (Math.random() < timeoutErrorRate) { return createErrorResponse({ code: 'TIMEOUT_ERROR', message: 'Request timeout', }, { status: 408 }); } // Server errors (5xx) if (Math.random() < serverErrorRate) { const serverErrors = [ { status: 500, code: 'INTERNAL_ERROR', message: 'Internal server error' }, { status: 502, code: 'BAD_GATEWAY', message: 'Bad gateway' }, { status: 503, code: 'SERVICE_UNAVAILABLE', message: 'Service unavailable' }, { status: 504, code: 'GATEWAY_TIMEOUT', message: 'Gateway timeout' }, ]; const error = serverErrors[Math.floor(Math.random() * serverErrors.length)]; return createErrorResponse({ code: error?.code || 'No code', message: error?.message || 'No message', }, { status: error?.status || 500 }); } return null; } /** * Simulate loading states with progressive responses */ export async function simulateProgressiveLoading(data, options = {}) { const { steps = 3, stepDelay = 200, onProgress } = options; for (let i = 0; i <= steps; i++) { const progress = (i / steps) * 100; if (onProgress) { onProgress(progress); } if (i < steps) { await simulateDelay(stepDelay); } } return data; } /** * Simulate file upload with progress */ export async function simulateFileUpload(file, options = {}) { const { chunkSize = 1024 * 64, // 64KB chunks chunkDelay = 100, onProgress, failureRate = 0, } = options; // Simulate upload failure if (Math.random() < failureRate) { throw new Error('Upload failed'); } const totalChunks = Math.ceil(file.size / chunkSize); for (let chunk = 0; chunk < totalChunks; chunk++) { const progress = ((chunk + 1) / totalChunks) * 100; if (onProgress) { onProgress(progress); } await simulateDelay(chunkDelay); } // Return mock upload result return { id: `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, url: `/uploads/${file.name}`, metadata: { originalName: file.name, size: file.size, type: file.type, uploadedAt: new Date().toISOString(), }, }; } /** * Simulate real-time data updates */ export function simulateRealTimeUpdates(initialData, updateFn, options = {}) { const { interval = 1000, maxUpdates = Number.POSITIVE_INFINITY, onUpdate } = options; let currentData = initialData; let updateCount = 0; const intervalId = setInterval(() => { if (updateCount >= maxUpdates) { clearInterval(intervalId); return; } currentData = updateFn(currentData); updateCount++; if (onUpdate) { onUpdate(currentData); } }, interval); // Return cleanup function return () => clearInterval(intervalId); } /** * Simulate batch processing */ export async function simulateBatchProcessing(items, processor, options = {}) { const { batchSize = 10, batchDelay = 500, onBatchComplete, onProgress } = options; const results = []; const batches = []; // Split items into batches for (let i = 0; i < items.length; i += batchSize) { batches.push(items.slice(i, i + batchSize)); } // Process each batch for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) { const batch = batches[batchIndex] ?? []; const batchResults = await Promise.all(batch.map(item => Promise.resolve(processor(item)))); results.push(...batchResults); if (onBatchComplete) { onBatchComplete(batchResults, batchIndex); } if (onProgress) { onProgress(results.length, items.length); } // Delay between batches (except for the last one) if (batchIndex < batches.length - 1) { await simulateDelay(batchDelay); } } return results; } /** * Simulate network conditions (slow 3G, fast 3G, etc.) */ export function getNetworkConditionDelay(condition) { switch (condition) { case 'slow-3g': return [2000, 5000]; case 'fast-3g': return [500, 1500]; case '4g': return [100, 500]; case 'wifi': return [50, 200]; default: return [100, 300]; } } /** * Simulate intermittent connectivity */ export function simulateIntermittentConnectivity(successRate = 0.9) { return Math.random() < successRate; } //# sourceMappingURL=simulation.js.map