mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
fix(cli): validate capture budget milliseconds
This commit is contained in:
@@ -264,8 +264,10 @@ export async function downloadAndRewriteFonts(
|
||||
|
||||
if (fontUrls.size === 0) return css;
|
||||
|
||||
// Limit font downloads to avoid bloat. Google Fonts serves 20+ unicode-range
|
||||
// subsets per weight — we only need a few per family for video production.
|
||||
// Limit font download attempts to bound worst-case egress and latency. Google Fonts serves
|
||||
// 20+ unicode-range subsets per weight, so successes alone cannot be the bound: six transient
|
||||
// failures can intentionally suppress later URLs in that family. Latin-priority sorting below
|
||||
// makes the limited attempts useful while keeping this failure tradeoff explicit.
|
||||
const MAX_FONTS_PER_FAMILY = 6;
|
||||
const MAX_TOTAL_FONTS = 30;
|
||||
const familyCounts = new Map<string, number>();
|
||||
|
||||
@@ -57,7 +57,11 @@ describe("capture command — vision control", () => {
|
||||
? Reflect.get(captureCommand.args, "capture-budget")
|
||||
: undefined;
|
||||
expect(captureBudgetArg).toMatchObject({ type: "string" });
|
||||
expect(captureBudgetArg?.description.toLowerCase()).toContain("post-navigation");
|
||||
const description = captureBudgetArg?.description.toLowerCase();
|
||||
expect(description).toContain("post-navigation");
|
||||
expect(description).toContain("cooperative");
|
||||
expect(description).toContain("not a hard wall-clock timeout");
|
||||
expect(description).toContain("already-started native/core work");
|
||||
expect(captureBudgetArg?.description).toContain("--timeout");
|
||||
});
|
||||
|
||||
@@ -81,28 +85,34 @@ describe("capture command — vision control", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("plumbs a positive --capture-budget into the post-navigation budget", async () => {
|
||||
vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
it.each([
|
||||
["1", 1],
|
||||
["45000", 45_000],
|
||||
])(
|
||||
"plumbs positive integer --capture-budget %s into the post-navigation budget",
|
||||
async (captureBudget, expectedBudget) => {
|
||||
vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
await captureCommand.run!({
|
||||
args: {
|
||||
url: "https://example.com",
|
||||
output: "/tmp/hf-capture-budget-test",
|
||||
"skip-assets": false,
|
||||
"skip-vision": false,
|
||||
"capture-budget": "45000",
|
||||
json: true,
|
||||
},
|
||||
} as never);
|
||||
await captureCommand.run!({
|
||||
args: {
|
||||
url: "https://example.com",
|
||||
output: "/tmp/hf-capture-budget-test",
|
||||
"skip-assets": false,
|
||||
"skip-vision": false,
|
||||
"capture-budget": captureBudget,
|
||||
json: true,
|
||||
},
|
||||
} as never);
|
||||
|
||||
expect(captureWebsiteMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ postNavigationBudgetMs: 45_000 }),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
expect(captureWebsiteMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ postNavigationBudgetMs: expectedBudget }),
|
||||
undefined,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it.each(["0", "-1", "Infinity", "not-a-number"])(
|
||||
it.each(["0", "-1", "0.5", "Infinity", "not-a-number"])(
|
||||
"rejects invalid --capture-budget %s before capture starts",
|
||||
async (captureBudget) => {
|
||||
vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
|
||||
@@ -15,8 +15,8 @@ function emitCapturePhase(event: CapturePhaseProgress): void {
|
||||
function parseCaptureBudget(raw: string | undefined): number | undefined {
|
||||
if (raw === undefined) return undefined;
|
||||
const parsed = Number(raw);
|
||||
if (!Number.isFinite(parsed) || parsed <= 0) {
|
||||
console.error("--capture-budget must be a positive finite number of milliseconds.");
|
||||
if (!Number.isInteger(parsed) || parsed <= 0) {
|
||||
console.error("--capture-budget must be a positive integer in milliseconds.");
|
||||
failCommand();
|
||||
}
|
||||
return parsed;
|
||||
@@ -73,7 +73,7 @@ export default defineCommand({
|
||||
"capture-budget": {
|
||||
type: "string",
|
||||
description:
|
||||
"Post-navigation capture budget in ms (default: 120000); separate from page-load --timeout",
|
||||
"Cooperative post-navigation budget in ms (default: 120000), separate from page-load --timeout; not a hard wall-clock timeout and cannot interrupt already-started native/core work",
|
||||
},
|
||||
json: {
|
||||
type: "boolean",
|
||||
|
||||
Reference in New Issue
Block a user