From 7cf4fae70e28780cf8ebc828f034f4209aa7cda0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Sun, 6 Sep 2026 02:06:16 +0000 Subject: [PATCH] fix(render): probe runtime media source mutations --- packages/lint/src/rules/media.test.ts | 56 +++++++++ packages/lint/src/rules/media.ts | 43 +++++++ packages/parsers/src/index.ts | 1 + packages/parsers/src/mediaSrcMutation.ts | 85 ++++++++++++++ .../src/services/render/observability.ts | 2 +- .../services/render/stages/probeStage.test.ts | 108 ++++++++++++++++++ .../src/services/render/stages/probeStage.ts | 52 ++++++--- .../src/services/render/videoFrameCoverage.ts | 4 +- 8 files changed, 335 insertions(+), 16 deletions(-) create mode 100644 packages/parsers/src/mediaSrcMutation.ts diff --git a/packages/lint/src/rules/media.test.ts b/packages/lint/src/rules/media.test.ts index 1d621e8a51..ec14b9d421 100644 --- a/packages/lint/src/rules/media.test.ts +++ b/packages/lint/src/rules/media.test.ts @@ -379,6 +379,62 @@ describe("media rules", () => { expect(finding).toBeUndefined(); }); + it("warns on raw src mutations targeting existing video and audio", async () => { + const html = ` + +
+ + +
+ +`; + + const result = await lintHyperframeHtml(html); + const findings = result.findings.filter( + (finding) => finding.code === "media_runtime_src_mutation", + ); + expect(findings).toHaveLength(2); + expect(findings.map((finding) => finding.elementId).sort()).toEqual(["clip", "voice"]); + expect(findings.every((finding) => finding.fixHint?.includes("data-var-src"))).toBe(true); + }); + + it("does not flag img or script src mutations", async () => { + const html = ` + +
+ +
+ +`; + + const result = await lintHyperframeHtml(html); + expect( + result.findings.find((finding) => finding.code === "media_runtime_src_mutation"), + ).toBeUndefined(); + }); + + it("warns when a source child of existing media is mutated", async () => { + const html = ` + +
+ +
+ +`; + + const result = await lintHyperframeHtml(html); + expect( + result.findings.find((finding) => finding.code === "media_runtime_src_mutation"), + ).toMatchObject({ severity: "warning", elementId: "clip" }); + }); + it("does not flag