mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
test(studio): close shadow reload regression gaps (#4223)
* test(studio): close shadow reload regression gaps * chore: refresh follow-up checks * test: keep follow-up free of unused exports * test(studio): distinguish root timeline selection
This commit is contained in:
@@ -2796,6 +2796,7 @@ describe("HyperframesPlayer asset-ready gate", () => {
|
||||
pause(): void;
|
||||
seek(timeInSeconds: number): void;
|
||||
shaderLoader: { showAssetsLoading(): void };
|
||||
_settleAssetsReady(generation: number): void;
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -2974,6 +2975,25 @@ describe("HyperframesPlayer asset-ready gate", () => {
|
||||
player.remove();
|
||||
});
|
||||
|
||||
it("dispatches painted once for the current generation when settles share a loader fade", async () => {
|
||||
vi.useFakeTimers();
|
||||
try {
|
||||
const player = await createConnectedPlayer();
|
||||
const painted = vi.fn();
|
||||
player.addEventListener("painted", painted);
|
||||
player.shaderLoader.showAssetsLoading();
|
||||
|
||||
player._waitForAssetsReady(null);
|
||||
player._waitForAssetsReady(null);
|
||||
await vi.runOnlyPendingTimersAsync();
|
||||
|
||||
expect(painted).toHaveBeenCalledTimes(1);
|
||||
player.remove();
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it("defers play() until a pending video settles, then plays and clears the overlay attribute", async () => {
|
||||
const player = await createConnectedPlayer();
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ it("re-evaluates set-destination availability when a reload swaps the live ifram
|
||||
expect(usePlayerStore.getState().motionPathCreateAvailable).toBe(false);
|
||||
|
||||
act(() => {
|
||||
ref.current = after;
|
||||
usePreviewIframeStore.getState().setIframe(after);
|
||||
});
|
||||
expect(usePlayerStore.getState().motionPathCreateAvailable).toBe(true);
|
||||
|
||||
@@ -261,6 +261,7 @@ describe("NLEPreview", () => {
|
||||
expect(players[0].style.clipPath).toBe("");
|
||||
expect(players[1].style.clipPath).toBe("inset(100%)");
|
||||
expect(players[1].style.visibility).toBe("hidden");
|
||||
expect(players[1].style.pointerEvents).toBe("none");
|
||||
view.cleanup();
|
||||
});
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ it("re-reads the size from the promoted iframe's document", () => {
|
||||
act(() => root.render(<Harness />));
|
||||
expect(host.textContent).toBe('{"width":1920,"height":1080}');
|
||||
act(() => {
|
||||
ref.current = b;
|
||||
usePreviewIframeStore.getState().setIframe(b);
|
||||
});
|
||||
expect(host.textContent).toBe('{"width":1080,"height":1920}');
|
||||
|
||||
@@ -85,6 +85,8 @@ async function mountPlayer(props: Partial<PlayerProps> = {}) {
|
||||
|
||||
const twoFrames = () => act(async () => void (await new Promise((r) => setTimeout(r, 80))));
|
||||
|
||||
const flushEffects = () => act(async () => await Promise.resolve());
|
||||
|
||||
function createAudioIframe() {
|
||||
const iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
@@ -216,6 +218,38 @@ describe("ready to show", () => {
|
||||
const painted = (player: TestHyperframesPlayer) =>
|
||||
act(() => void player.dispatchEvent(new Event("painted")));
|
||||
|
||||
it("waits two animation frames before notifying that the preview can show", async () => {
|
||||
const callbacks: FrameRequestCallback[] = [];
|
||||
const requestAnimationFrame = vi
|
||||
.spyOn(window, "requestAnimationFrame")
|
||||
.mockImplementation((callback) => {
|
||||
callbacks.push(callback);
|
||||
return callbacks.length;
|
||||
});
|
||||
try {
|
||||
const onReadyToShowChange = vi.fn();
|
||||
const { player } = await mountPlayer({ onReadyToShowChange });
|
||||
const el = player as TestHyperframesPlayer;
|
||||
|
||||
loadAndReady(el);
|
||||
painted(el);
|
||||
await flushEffects();
|
||||
expect(onReadyToShowChange).not.toHaveBeenCalledWith(true);
|
||||
expect(callbacks).toHaveLength(1);
|
||||
|
||||
act(() => callbacks.shift()?.(0));
|
||||
await flushEffects();
|
||||
expect(onReadyToShowChange).not.toHaveBeenCalledWith(true);
|
||||
expect(callbacks).toHaveLength(1);
|
||||
|
||||
act(() => callbacks.shift()?.(16));
|
||||
await flushEffects();
|
||||
expect(onReadyToShowChange).toHaveBeenLastCalledWith(true);
|
||||
} finally {
|
||||
requestAnimationFrame.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("promotes only once the player reports painted, not at ready or assetsready", async () => {
|
||||
const onReadyToShowChange = vi.fn();
|
||||
const { player } = await mountPlayer({ onReadyToShowChange });
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { resolvePlaybackAdapter } from "./playbackAdapterResolution";
|
||||
|
||||
function timeline(duration: number) {
|
||||
return {
|
||||
duration: vi.fn(() => duration),
|
||||
time: vi.fn(() => 0),
|
||||
seek: vi.fn(),
|
||||
play: vi.fn(),
|
||||
pause: vi.fn(),
|
||||
isActive: vi.fn(() => false),
|
||||
};
|
||||
}
|
||||
|
||||
describe("resolvePlaybackAdapter", () => {
|
||||
it("uses the __timelines key matching the document root, not the first key", () => {
|
||||
const first = timeline(12);
|
||||
const second = timeline(12);
|
||||
const third = timeline(12);
|
||||
const iframe = document.createElement("iframe");
|
||||
const doc = document.implementation.createHTMLDocument("preview");
|
||||
doc.body.innerHTML = '<div data-composition-id="second" data-duration="10"></div>';
|
||||
Object.defineProperty(iframe, "contentDocument", { configurable: true, value: doc });
|
||||
const win = {
|
||||
__timelines: { first, second, third },
|
||||
} as never;
|
||||
|
||||
const adapter = resolvePlaybackAdapter(iframe, win, {
|
||||
cache: { current: null },
|
||||
warned: { current: false },
|
||||
});
|
||||
|
||||
expect(adapter).not.toBeNull();
|
||||
adapter?.seek(7);
|
||||
expect(second.seek).toHaveBeenCalledWith(7);
|
||||
expect(first.seek).not.toHaveBeenCalled();
|
||||
expect(third.seek).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user