mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 16:42:27 +00:00
93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { Page } from "puppeteer-core";
|
|
import { collectMediaReadinessWarnings } from "./frameCapture.js";
|
|
|
|
function makePage(input: {
|
|
images?: Array<{ src: string; complete: boolean; naturalWidth: number }>;
|
|
media?: Array<{
|
|
id?: string;
|
|
tagName: "VIDEO" | "AUDIO";
|
|
src: string;
|
|
readyState: number;
|
|
networkState?: number;
|
|
error?: unknown;
|
|
}>;
|
|
}): Page {
|
|
return {
|
|
evaluate: async (fn: (skipIds: readonly string[]) => unknown, skipIds: readonly string[]) => {
|
|
const previousDocument = Reflect.get(globalThis, "document");
|
|
const previousMedia = Reflect.get(globalThis, "HTMLMediaElement");
|
|
Reflect.set(globalThis, "HTMLMediaElement", {
|
|
NETWORK_NO_SOURCE: 3,
|
|
HAVE_CURRENT_DATA: 2,
|
|
});
|
|
Reflect.set(globalThis, "document", {
|
|
querySelectorAll: (selector: string) => {
|
|
if (selector === "img") {
|
|
return (input.images ?? []).map((image) => ({
|
|
...image,
|
|
getAttribute: (name: string) => (name === "src" ? image.src : null),
|
|
}));
|
|
}
|
|
const media =
|
|
selector === "video"
|
|
? (input.media ?? []).filter((element) => element.tagName === "VIDEO")
|
|
: (input.media ?? []);
|
|
return media.map((media) => ({
|
|
id: media.id ?? "",
|
|
tagName: media.tagName,
|
|
currentSrc: media.src,
|
|
readyState: media.readyState,
|
|
networkState: media.networkState ?? 1,
|
|
error: media.error ?? null,
|
|
getAttribute: (name: string) => (name === "src" ? media.src : null),
|
|
}));
|
|
},
|
|
});
|
|
try {
|
|
return await fn(skipIds);
|
|
} finally {
|
|
Reflect.set(globalThis, "document", previousDocument);
|
|
Reflect.set(globalThis, "HTMLMediaElement", previousMedia);
|
|
}
|
|
},
|
|
} as unknown as Page;
|
|
}
|
|
|
|
describe("collectMediaReadinessWarnings", () => {
|
|
it("returns stable warnings for visual media and ignores out-of-band audio", async () => {
|
|
const page = makePage({
|
|
images: [
|
|
{ src: "/pending.png", complete: false, naturalWidth: 0 },
|
|
{ src: "/broken.png", complete: true, naturalWidth: 0 },
|
|
],
|
|
media: [
|
|
{ tagName: "VIDEO", src: "/broken.mp4", readyState: 0, error: new Error("decode") },
|
|
{ tagName: "AUDIO", src: "/pending.mp3", readyState: 1 },
|
|
{ id: "injected", tagName: "VIDEO", src: "/injected.mp4", readyState: 0 },
|
|
],
|
|
});
|
|
|
|
const warnings = await collectMediaReadinessWarnings(page, ["injected"], 45000);
|
|
|
|
expect(warnings.map((warning) => [warning.code, warning.details?.mediaType])).toEqual([
|
|
["media_readiness_timeout", "image"],
|
|
["media_load_failed", "image"],
|
|
["media_load_failed", "video"],
|
|
]);
|
|
expect(warnings.every((warning) => warning.details?.timeoutMs === 45000)).toBe(true);
|
|
});
|
|
|
|
it("returns no warnings when every relevant resource is ready", async () => {
|
|
const page = makePage({
|
|
images: [{ src: "/ready.png", complete: true, naturalWidth: 100 }],
|
|
media: [
|
|
{ tagName: "VIDEO", src: "/ready.mp4", readyState: 2 },
|
|
{ tagName: "AUDIO", src: "/ready.mp3", readyState: 2 },
|
|
],
|
|
});
|
|
|
|
await expect(collectMediaReadinessWarnings(page, [], 1000)).resolves.toEqual([]);
|
|
});
|
|
});
|