Files
hyperframes/packages/cli/src/capture/screenshotCapture.degrade.test.ts
T
Xuanru LiandCursor 43dba22057 fix(capture): bound scroll/evaluate timeouts so heavy pages keep capturing (#3236)
* fix(capture): bound scroll/evaluate timeouts so heavy pages keep capturing

Fonts/Vercel-class sites were failing after navigation when a single in-page
scroll/evaluate hung until protocolTimeout. Drive lazy scroll from Node,
degrade on evaluate timeouts, and stop labeling those failures as bot blocks.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(capture): enforce stage budgets and surface evaluate degradation

Bound each scroll/content evaluate with remaining stage time so a wedged
page.evaluate cannot outlive the advertised 15s/8s budgets, skip recovery
CDP calls after expiry, and return/propagate timed-out animation and
screenshot work so caller warnings are reachable.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(capture): prefer TimeoutError instanceof for timeout classification

Use puppeteer-core TimeoutError as the primary signal for navigation vs
evaluate/protocol timeouts, with message checks only as a fallback for
string formatting and non-TimeoutError cases.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 18:26:22 -07:00

26 lines
970 B
TypeScript

import { describe, expect, it, vi } from "vitest";
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { TimeoutError } from "puppeteer-core";
import type { Page } from "puppeteer-core";
import { captureScrollScreenshots } from "./screenshotCapture.js";
describe("captureScrollScreenshots degradation", () => {
it("rethrows protocol evaluate timeouts for the caller warning path", async () => {
const dir = mkdtempSync(join(tmpdir(), "hf-scroll-degrade-"));
const page = {
evaluate: vi.fn(async () => {
throw new TimeoutError(
"Runtime.evaluate timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.",
);
}),
screenshot: vi.fn(),
} as unknown as Page;
await expect(
captureScrollScreenshots(page, dir, { remainingMs: () => 5_000 }),
).rejects.toBeInstanceOf(TimeoutError);
});
});