mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 06:30:03 +00:00
fix(cli): honor check navigation timeout (#2860)
* fix(cli): honor check navigation timeout * test(cli): clarify diagnostic timeout precedence
This commit is contained in:
@@ -542,7 +542,7 @@ Word-level transcripts (whisper output) are grouped into readable caption cues o
|
|||||||
| `--snapshots` | Write overview frames (annotated with labeled finding boxes when there are errors) plus `finding-NN-<code>.png` crops |
|
| `--snapshots` | Write overview frames (annotated with labeled finding boxes when there are errors) plus `finding-NN-<code>.png` crops |
|
||||||
| `--samples` / `--at` / `--at-transitions` | Control the seek grid (default 9 samples; `--at-transitions` adds tween boundaries) |
|
| `--samples` / `--at` / `--at-transitions` | Control the seek grid (default 9 samples; `--at-transitions` adds tween boundaries) |
|
||||||
| `--tolerance` | Allowed overflow in px before reporting (default 2) |
|
| `--tolerance` | Allowed overflow in px before reporting (default 2) |
|
||||||
| `--timeout` | Initial settle budget in ms (default 3000) |
|
| `--timeout` | Initial render-ready budget in ms; also raises the page-navigation budget above its 10s floor (default 3000) |
|
||||||
| `--no-contrast` | Skip the WCAG audit while iterating |
|
| `--no-contrast` | Skip the WCAG audit while iterating |
|
||||||
| `--strict` | Exit non-zero on warnings too (default: only errors) |
|
| `--strict` | Exit non-zero on warnings too (default: only errors) |
|
||||||
| `--caption-zone "<x0=..;y0=..;x1=..;y1=..>"` | Opt-in band gate: flags content whose center sits inside the fractional band (optional `severity`, `seek`) |
|
| `--caption-zone "<x0=..;y0=..;x1=..;y1=..>"` | Opt-in band gate: flags content whose center sits inside the fractional band (optional `severity`, `seek`) |
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ export interface SettledCompositionPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface OpenSettledCompositionPageOptions {
|
export interface OpenSettledCompositionPageOptions {
|
||||||
|
// Separate from the post-navigation render-ready budget. Diagnostic callers
|
||||||
|
// without their own navigation knob keep the historical 10-second minimum.
|
||||||
|
navigationTimeoutMs?: number;
|
||||||
renderReadyTimeoutMs: number;
|
renderReadyTimeoutMs: number;
|
||||||
renderReadyWarningSuffix: string;
|
renderReadyWarningSuffix: string;
|
||||||
// Screenshot paths take the engine's software-GPU default; validate/check
|
// Screenshot paths take the engine's software-GPU default; validate/check
|
||||||
@@ -182,7 +185,7 @@ export async function openSettledCompositionPage(
|
|||||||
await options.beforeNavigate?.(page);
|
await options.beforeNavigate?.(page);
|
||||||
await page.goto(url, {
|
await page.goto(url, {
|
||||||
waitUntil: "domcontentloaded",
|
waitUntil: "domcontentloaded",
|
||||||
timeout: resolveDiagnosticNavigationTimeoutMs(),
|
timeout: resolveDiagnosticNavigationTimeoutMs(process.env, options.navigationTimeoutMs),
|
||||||
});
|
});
|
||||||
const renderReadyTimedOut = !(await waitForCompositionSettle(page, options));
|
const renderReadyTimedOut = !(await waitForCompositionSettle(page, options));
|
||||||
return { browser: chromeBrowser, page, renderReadyTimedOut };
|
return { browser: chromeBrowser, page, renderReadyTimedOut };
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ export function createCheckCommand(
|
|||||||
},
|
},
|
||||||
timeout: {
|
timeout: {
|
||||||
type: "string",
|
type: "string",
|
||||||
description: "Ms to wait for scripts and media to settle initially (default: 3000)",
|
description:
|
||||||
|
"Initial render-ready timeout in ms; also sets the navigation minimum (10s floor, default: 3000)",
|
||||||
default: "3000",
|
default: "3000",
|
||||||
},
|
},
|
||||||
contrast: {
|
contrast: {
|
||||||
|
|||||||
@@ -155,6 +155,28 @@ it("carries raw browser geometry through the page driver and pipeline", async ()
|
|||||||
expect(mocks.serverClose).toHaveBeenCalledOnce();
|
expect(mocks.serverClose).toHaveBeenCalledOnce();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses check --timeout for both navigation and render-ready settling", async () => {
|
||||||
|
mountCanvasFixture();
|
||||||
|
const page = fakePage();
|
||||||
|
installSessionMock(page);
|
||||||
|
|
||||||
|
await runBrowserCheck(
|
||||||
|
PROJECT,
|
||||||
|
{ ...DEFAULT_CHECK_OPTIONS, samples: 1, contrast: false, timeout: 30_000 },
|
||||||
|
{ kind: "none" },
|
||||||
|
runAuditGrid,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(openSettledCompositionPage).toHaveBeenCalledWith(
|
||||||
|
"<html></html>",
|
||||||
|
"http://127.0.0.1:3000",
|
||||||
|
expect.objectContaining({
|
||||||
|
navigationTimeoutMs: 30_000,
|
||||||
|
renderReadyTimeoutMs: 30_000,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("round-trips the browser script's raw contrast candidates back into finish", async () => {
|
it("round-trips the browser script's raw contrast candidates back into finish", async () => {
|
||||||
// The U2 regression class: Node parses prepare's candidates for reporting,
|
// The U2 regression class: Node parses prepare's candidates for reporting,
|
||||||
// but must hand the UNTOUCHED objects back to __contrastAuditFinish — the
|
// but must hand the UNTOUCHED objects back to __contrastAuditFinish — the
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ export async function runBrowserCheck(
|
|||||||
try {
|
try {
|
||||||
const launchSettleStart = Date.now();
|
const launchSettleStart = Date.now();
|
||||||
const session = await openSettledCompositionPage(html, server.url, {
|
const session = await openSettledCompositionPage(html, server.url, {
|
||||||
|
navigationTimeoutMs: options.timeout,
|
||||||
renderReadyTimeoutMs: options.timeout,
|
renderReadyTimeoutMs: options.timeout,
|
||||||
renderReadyWarningSuffix: "checking the current page state",
|
renderReadyWarningSuffix: "checking the current page state",
|
||||||
browserGpuMode: resolveCliChromeGpuMode(),
|
browserGpuMode: resolveCliChromeGpuMode(),
|
||||||
@@ -225,6 +226,7 @@ export async function captureFindingCrops(
|
|||||||
const written: string[] = [];
|
const written: string[] = [];
|
||||||
try {
|
try {
|
||||||
const session = await openSettledCompositionPage(html, server.url, {
|
const session = await openSettledCompositionPage(html, server.url, {
|
||||||
|
navigationTimeoutMs: options.timeout,
|
||||||
renderReadyTimeoutMs: options.timeout,
|
renderReadyTimeoutMs: options.timeout,
|
||||||
renderReadyWarningSuffix: "capturing finding crops",
|
renderReadyWarningSuffix: "capturing finding crops",
|
||||||
browserGpuMode: resolveCliChromeGpuMode(),
|
browserGpuMode: resolveCliChromeGpuMode(),
|
||||||
|
|||||||
@@ -118,6 +118,23 @@ describe("resolveDiagnosticNavigationTimeoutMs", () => {
|
|||||||
resolveDiagnosticNavigationTimeoutMs({ PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS: "invalid" }),
|
resolveDiagnosticNavigationTimeoutMs({ PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS: "invalid" }),
|
||||||
).toBe(10_000);
|
).toBe(10_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("raises the diagnostic navigation budget to a larger caller-provided minimum", () => {
|
||||||
|
expect(resolveDiagnosticNavigationTimeoutMs({}, 30_000)).toBe(30_000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not let a caller-provided minimum shorten the default budget", () => {
|
||||||
|
expect(resolveDiagnosticNavigationTimeoutMs({}, 3_000)).toBe(10_000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not let a caller-provided minimum shorten the environment override", () => {
|
||||||
|
expect(
|
||||||
|
resolveDiagnosticNavigationTimeoutMs(
|
||||||
|
{ PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS: "90000" },
|
||||||
|
30_000,
|
||||||
|
),
|
||||||
|
).toBe(90_000);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("parseCompositionEntryArg", () => {
|
describe("parseCompositionEntryArg", () => {
|
||||||
|
|||||||
@@ -118,12 +118,20 @@ export function resolveBrowserTimeoutMsArg(raw: string | undefined): number | un
|
|||||||
return result.value;
|
return result.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Navigation budget shared by snapshot/check/inspect browser diagnostics. */
|
/**
|
||||||
|
* Navigation budget shared by snapshot/check/inspect browser diagnostics.
|
||||||
|
*
|
||||||
|
* The environment variable remains the historical global override. Callers
|
||||||
|
* with their own timeout knob can supply a minimum without shortening that
|
||||||
|
* override or the existing 10-second default.
|
||||||
|
*/
|
||||||
export function resolveDiagnosticNavigationTimeoutMs(
|
export function resolveDiagnosticNavigationTimeoutMs(
|
||||||
env: Record<string, string | undefined> = process.env,
|
env: Record<string, string | undefined> = process.env,
|
||||||
|
minimumTimeoutMs = 0,
|
||||||
): number {
|
): number {
|
||||||
const parsed = Number(env.PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS);
|
const parsed = Number(env.PRODUCER_PAGE_NAVIGATION_TIMEOUT_MS);
|
||||||
return Number.isFinite(parsed) && parsed > 0 ? parsed : 10_000;
|
const configured = Number.isFinite(parsed) && parsed > 0 ? parsed : 10_000;
|
||||||
|
return Math.max(configured, minimumTimeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── --composition ──────────────────────────────────────────────────────
|
// ── --composition ──────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
"files": 121
|
"files": 121
|
||||||
},
|
},
|
||||||
"hyperframes-cli": {
|
"hyperframes-cli": {
|
||||||
"hash": "966972db5ab8f932",
|
"hash": "42b621ca580541b6",
|
||||||
"files": 11
|
"files": 11
|
||||||
},
|
},
|
||||||
"hyperframes-core": {
|
"hyperframes-core": {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ npx hyperframes check --samples 15 # denser timeline sweep (default 9)
|
|||||||
npx hyperframes check --at 1.5,4,7.25 # explicit hero-frame timestamps
|
npx hyperframes check --at 1.5,4,7.25 # explicit hero-frame timestamps
|
||||||
npx hyperframes check --at-transitions # also sample every tween start/end boundary
|
npx hyperframes check --at-transitions # also sample every tween start/end boundary
|
||||||
npx hyperframes check --tolerance 4 # allowed overflow px before reporting (default 2)
|
npx hyperframes check --tolerance 4 # allowed overflow px before reporting (default 2)
|
||||||
npx hyperframes check --timeout 5000 # ms for the initial settle (default 3000)
|
npx hyperframes check --timeout 30000 # initial render-ready + navigation minimum in ms (defaults: 3000 / 10000)
|
||||||
npx hyperframes check --no-contrast # skip the WCAG audit while iterating
|
npx hyperframes check --no-contrast # skip the WCAG audit while iterating
|
||||||
npx hyperframes check --strict # exit non-zero on warnings too (default: only errors)
|
npx hyperframes check --strict # exit non-zero on warnings too (default: only errors)
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user