From e9c0b30f28ed635fee61db2d0099d4e67d514bb0 Mon Sep 17 00:00:00 2001 From: Miguel Angel Simon Sierra Date: Mon, 2 Nov 2026 06:24:39 -0500 Subject: [PATCH] fix(cli): check ignores the cancelled fetch of a proxy-swapped media file, not a broken image --- packages/cli/src/commands/validate.test.ts | 7 +++++ packages/cli/src/commands/validate.ts | 3 +- packages/cli/src/utils/checkBrowser.test.ts | 31 +++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/commands/validate.test.ts b/packages/cli/src/commands/validate.test.ts index 797c8e105e..0c60e1036d 100644 --- a/packages/cli/src/commands/validate.test.ts +++ b/packages/cli/src/commands/validate.test.ts @@ -189,6 +189,13 @@ describe("shouldIgnoreRequestFailure", () => { } }); + it("keeps an aborted image request reportable whatever its file suffix", () => { + for (const ext of ["mkv", "mp4", "png"]) { + const url = `http://127.0.0.1:3000/assets/plate.${ext}`; + expect(shouldIgnoreRequestFailure(url, "net::ERR_ABORTED", "image")).toBe(false); + } + }); + it("keeps non-media and non-aborted failures reportable", () => { expect( shouldIgnoreRequestFailure("http://127.0.0.1:3000/assets/map.png", "net::ERR_ABORTED"), diff --git a/packages/cli/src/commands/validate.ts b/packages/cli/src/commands/validate.ts index 0c63ac58bb..21afa80b3b 100644 --- a/packages/cli/src/commands/validate.ts +++ b/packages/cli/src/commands/validate.ts @@ -51,7 +51,7 @@ interface ContrastEntry { const CONTRAST_SAMPLES = 5; const SEEK_SETTLE_MS = 150; const PREFERRED_SEEK_TARGET_WAIT_MS = 500; -// Containers a proxy swap can abandon mid-fetch; an aborted fetch of one is not a load failure. +// Media files a proxy swap can abandon mid-fetch; an aborted non-image request for one is not a load failure. const MEDIA_EXTENSIONS = /\.(3gp|aac|aif|aiff|avi|flac|flv|m2ts|m4a|m4v|mkv|mov|mp3|mp4|mpeg|mpg|mts|mxf|oga|ogg|ogv|opus|wav|weba|webm|wma|wmv)$/i; // Turn Puppeteer's opaque "Navigation timeout of Nms exceeded" into an @@ -76,6 +76,7 @@ export function shouldIgnoreRequestFailure( if (errorText === "net::ERR_ABORTED" && isOptionalCaptionOverridesRequest(url)) return true; if (errorText !== "net::ERR_ABORTED") return false; if (resourceType === "media") return true; + if (resourceType === "image") return false; try { return MEDIA_EXTENSIONS.test(new URL(url).pathname); } catch { diff --git a/packages/cli/src/utils/checkBrowser.test.ts b/packages/cli/src/utils/checkBrowser.test.ts index 9dcca61359..3dbd1146f8 100644 --- a/packages/cli/src/utils/checkBrowser.test.ts +++ b/packages/cli/src/utils/checkBrowser.test.ts @@ -1174,6 +1174,37 @@ describe("keepBrokenImageAborts", () => { ]); }); + it("reports a still-broken aborted image even when its URL ends in a video suffix", async () => { + const base = "http://127.0.0.1:3000/assets"; + mountCanvasFixture(``); + (document.getElementById("stuck") as HTMLImageElement).decode = () => + Promise.reject(new Error("broken")); + const aborted = (url: string, resourceType: string) => ({ + url: () => url, + failure: () => ({ errorText: "net::ERR_ABORTED" }), + resourceType: () => resourceType, + }); + const page = fakePage(); + page.on = vi.fn((event: string, handler: (request: ReturnType) => void) => { + if (event !== "requestfailed") return; + handler(aborted(`${base}/plate.mkv`, "image")); + handler(aborted(`${base}/clip.mkv`, "fetch")); + }); + installSessionMock(page); + + const result = await runBrowserCheck( + PROJECT, + { ...DEFAULT_CHECK_OPTIONS, samples: 1, contrast: false }, + { kind: "none" }, + runAuditGrid, + ); + + const failed = result.runtimeFindings.filter((finding) => finding.code === "request_failed"); + expect(failed.map((finding) => finding.message)).toEqual([ + "Failed to load assets/plate.mkv: net::ERR_ABORTED", + ]); + }); + it("does not report an aborted image whose reload is still pending at the cap", async () => { const url = "http://127.0.0.1:3000/assets/slow.png"; mountCanvasFixture(``);