From 13b42bec3c934b012c6873fa0dcbb1e8bd2519ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Sun, 1 Nov 2026 22:46:34 +0000 Subject: [PATCH] fix(shader-transitions): keep the loading panel out of snapshot and check captures (#6959) --- .../src/hyper-shader.preview.test.ts | 39 +++++++++++++++++++ .../shader-transitions/src/hyper-shader.ts | 2 + 2 files changed, 41 insertions(+) diff --git a/packages/shader-transitions/src/hyper-shader.preview.test.ts b/packages/shader-transitions/src/hyper-shader.preview.test.ts index ac92da4cfc..b5c354312b 100644 --- a/packages/shader-transitions/src/hyper-shader.preview.test.ts +++ b/packages/shader-transitions/src/hyper-shader.preview.test.ts @@ -79,6 +79,45 @@ function visibilityOf(ids: string[]): string[] { return ids.map((id) => (document.getElementById(id) as HTMLElement).style.visibility); } +describe("the loading panel", () => { + async function panelSeenDuringPrewarm(): Promise { + stubGsap(); + stubWebGl(); + vi.spyOn(console, "warn").mockImplementation(() => {}); + mountScenes(["s1", "s2"]); + let seen = false; + const watch = new MutationObserver((records) => { + for (const record of records) + for (const node of record.addedNodes) + if (node instanceof HTMLElement && node.hasAttribute("data-hyper-shader-loading")) + seen = true; + }); + watch.observe(document.body, { childList: true, subtree: true }); + init({ + bgColor: "#000", + scenes: ["s1", "s2"], + transitions: [{ time: 2, duration: 0.8, shader: "domain-warp" }], + }); + await prewarmDone(); + await Promise.resolve(); + watch.disconnect(); + return seen; + } + + afterEach(() => { + delete (window as { __HF_REPLAY_SKIPPED_FRAMES?: boolean }).__HF_REPLAY_SKIPPED_FRAMES; + }); + + it("covers a live preview while its transitions prepare", async () => { + expect(await panelSeenDuringPrewarm()).toBe(true); + }); + + it("is never added to a still-capture page, so snapshot and check do not see it", async () => { + (window as { __HF_REPLAY_SKIPPED_FRAMES?: boolean }).__HF_REPLAY_SKIPPED_FRAMES = true; + expect(await panelSeenDuringPrewarm()).toBe(false); + }); +}); + describe("preview outside a transition", () => { it("leaves the runtime's hide on shader scenes after the prewarm on a paused page", async () => { stubGsap(); diff --git a/packages/shader-transitions/src/hyper-shader.ts b/packages/shader-transitions/src/hyper-shader.ts index a1fb6b2a9b..f696533965 100644 --- a/packages/shader-transitions/src/hyper-shader.ts +++ b/packages/shader-transitions/src/hyper-shader.ts @@ -224,6 +224,8 @@ function resolvePlayerCaptureScale(): number { } function resolvePlayerLoadingMode(): "internal" | "player" | "none" { + if ((window as { __HF_REPLAY_SKIPPED_FRAMES?: boolean }).__HF_REPLAY_SKIPPED_FRAMES) + return "none"; const raw = readPlayerOption("__HF_SHADER_LOADING", PLAYER_LOADING_PARAM)?.trim().toLowerCase(); if (raw === "player" || raw === "true" || raw === "1") return "player"; if (raw === "none" || raw === "false" || raw === "0" || raw === "off") return "none";