mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-04 13:07:11 +00:00
fix(cli): snapshot warns when self-closed audio or video clips have swallowed the page (#6915)
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { selfClosedMediaWarning } from "./snapshot.js";
|
||||
|
||||
const page = (media: string) => `<!doctype html><html><body>
|
||||
<div id="root" data-composition-id="main" data-start="0" data-duration="10" data-width="1280" data-height="720">
|
||||
${media}
|
||||
<h1 id="title">Hello</h1></div></body></html>`;
|
||||
|
||||
describe("selfClosedMediaWarning", () => {
|
||||
it("names the self-closed clips and what they do to the still", async () => {
|
||||
const clips = Array.from(
|
||||
{ length: 3 },
|
||||
(_, i) => `<audio id="sfx${i}" src="s${i}.wav" data-start="${i}" data-duration="1" />`,
|
||||
).join("\n");
|
||||
|
||||
const warning = await selfClosedMediaWarning(page(clips));
|
||||
|
||||
expect(warning).toContain("3 self-closed <audio>/<video> tags");
|
||||
expect(warning).toContain("#sfx0");
|
||||
expect(warning).toContain("stills come out blank");
|
||||
});
|
||||
|
||||
it("stays quiet when every clip has a closing tag, even with fallback content", async () => {
|
||||
const closed = `<audio id="a" src="a.wav" data-start="0" data-duration="1"></audio>
|
||||
<video id="v" src="v.mp4" data-start="0" data-duration="2"><p>Your browser cannot play this.</p></video>`;
|
||||
|
||||
expect(await selfClosedMediaWarning(page(closed))).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -938,6 +938,14 @@ export async function captureSnapshots(
|
||||
// Localize fonts (embed remote @font-face as data URIs, matching the render
|
||||
// path) so snapshots render the real font instead of a fallback sans.
|
||||
const html = await bundleWithLocalizedFonts(projectDir);
|
||||
const entry = join(projectDir, "index.html");
|
||||
const swallowed = existsSync(entry)
|
||||
? await selfClosedMediaWarning(readFileSync(entry, "utf8"))
|
||||
: null;
|
||||
if (swallowed) {
|
||||
warnings.push(swallowed);
|
||||
console.warn(` ${c.warn("⚠")} ${swallowed}`);
|
||||
}
|
||||
const server = await serveCapturePage(projectDir, html, opts.autoProxy);
|
||||
|
||||
const savedPaths: string[] = [];
|
||||
@@ -1506,6 +1514,20 @@ function warnUnsettledImages(images: UnsettledImages, time: number, warnings: st
|
||||
}
|
||||
}
|
||||
|
||||
/** What the project's own lint says about self-closed clips, which hide the rest of the page and blank every still. */
|
||||
export async function selfClosedMediaWarning(source: string): Promise<string | null> {
|
||||
const { lintHyperframeHtml } = await import("@hyperframes/lint");
|
||||
const found = (await lintHyperframeHtml(source)).findings.filter(
|
||||
(finding) => finding.code === "self_closing_media_tag",
|
||||
);
|
||||
if (found.length === 0) return null;
|
||||
const ids = found.flatMap((finding) => (finding.elementId ? [`#${finding.elementId}`] : []));
|
||||
return (
|
||||
`index.html has ${found.length} self-closed <audio>/<video> tags${ids.length ? ` (${ids.slice(0, 3).join(", ")})` : ""}: ` +
|
||||
"HTML leaves them open, so everything after the first one is hidden and stills come out blank. Write <audio ...></audio>."
|
||||
);
|
||||
}
|
||||
|
||||
function warnSnapshotsNotRecorded(error: unknown): undefined {
|
||||
console.warn(` ${c.warn("⚠")} Snapshots were not recorded: ${normalizeErrorMessage(error)}`);
|
||||
return undefined;
|
||||
|
||||
Reference in New Issue
Block a user