import { isNavigationTimeoutError } from "./captureTimeout.js"; export { isNavigationTimeoutError }; export const NETWORK_IDLE_ATTEMPT_MS = 30_000; export type CaptureGotoWaitUntil = "networkidle2" | "domcontentloaded"; export interface CaptureGotoOptions { waitUntil: CaptureGotoWaitUntil; timeout: number; } export interface CaptureGotoPage { goto(url: string, options: CaptureGotoOptions): Promise; } export interface NavigateForCaptureResult { response: TResponse; waitUntil: CaptureGotoWaitUntil; networkIdleTimeoutMs: number; fellBackFromNetworkIdle: boolean; } export function networkIdleAttemptTimeoutMs(totalTimeoutMs: number): number { return Math.min(NETWORK_IDLE_ATTEMPT_MS, Math.max(0, totalTimeoutMs)); } export async function navigateForCapture( page: CaptureGotoPage, url: string, totalTimeoutMs: number, ): Promise> { const networkIdleTimeoutMs = networkIdleAttemptTimeoutMs(totalTimeoutMs); try { const response = await page.goto(url, { waitUntil: "networkidle2", timeout: networkIdleTimeoutMs, }); return { response, waitUntil: "networkidle2", networkIdleTimeoutMs, fellBackFromNetworkIdle: false, }; } catch (err) { if (!isNavigationTimeoutError(err) || networkIdleTimeoutMs >= totalTimeoutMs) { throw err; } } const fallbackTimeoutMs = totalTimeoutMs - networkIdleTimeoutMs; const response = await page.goto(url, { waitUntil: "domcontentloaded", timeout: fallbackTimeoutMs, }); return { response, waitUntil: "domcontentloaded", networkIdleTimeoutMs, fellBackFromNetworkIdle: true, }; }