/** * Network throttle simulation via CDP. * * Simulates different network conditions during crawl to test how the app * behaves under slow connections. Useful for detecting loading states, error * handling, and performance degradation on poor networks. * * Conditions mirror Chrome DevTools presets: * - slow3g: ~500kbps download, high latency * - fast3g: ~1.6Mbps download, medium latency * - 4g: ~9Mbps download, low latency * - offline: no connectivity * - none: no throttle (default) */ export type NetworkConditionPreset = 'none' | 'slow3g' | 'fast3g' | '4g' | 'offline'; interface NetworkCondition { offline: boolean; downloadThroughput: number; // bytes/s uploadThroughput: number; // bytes/s latency: number; // ms } const PRESETS: Record = { none: { offline: false, downloadThroughput: -1, uploadThroughput: -1, latency: 0 }, slow3g: { offline: false, downloadThroughput: 500 * 1024 / 8, uploadThroughput: 500 * 1024 / 8, latency: 2_000 }, fast3g: { offline: false, downloadThroughput: 1.6 * 1024 * 1024 / 8, uploadThroughput: 750 * 1024 / 8, latency: 562.5 }, '4g': { offline: false, downloadThroughput: 9 * 1024 * 1024 / 8, uploadThroughput: 2.67 * 1024 * 1024 / 8, latency: 85 }, offline: { offline: true, downloadThroughput: 0, uploadThroughput: 0, latency: 0 }, }; export async function applyNetworkThrottle( cdpSession: any, preset: NetworkConditionPreset, ): Promise { if (!cdpSession?.send) return; const condition = PRESETS[preset]; try { await cdpSession.send('Network.enable'); await cdpSession.send('Network.emulateNetworkConditions', condition); } catch { /* non-fatal — CDP may not be available */ } } export async function clearNetworkThrottle(cdpSession: any): Promise { await applyNetworkThrottle(cdpSession, 'none'); } export interface ThrottledCrawlOpts { /** Network preset to apply during this URL's crawl */ preset: NetworkConditionPreset; /** Restore to 'none' after navigation (default: true) */ restoreAfter?: boolean; } /** Apply throttle, run fn, restore. Returns fn's result. */ export async function withNetworkThrottle( cdpSession: any, preset: NetworkConditionPreset, fn: () => Promise, restoreAfter = true, ): Promise { await applyNetworkThrottle(cdpSession, preset); try { return await fn(); } finally { if (restoreAfter) await clearNetworkThrottle(cdpSession).catch(() => {}); } }