mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(player): authenticate slideshow navigation senders (#3820)
* fix(player): authenticate slideshow navigation senders * test: isolate playground message boundary imports
This commit is contained in:
@@ -199,6 +199,30 @@ describe("<hyperframes-slideshow>", () => {
|
||||
el.remove();
|
||||
});
|
||||
|
||||
it("accepts embedding-parent and self navigation but rejects other senders", () => {
|
||||
const onNext = vi.fn();
|
||||
const el = makeEl({ onNext });
|
||||
const embedding = document.createElement("iframe");
|
||||
const foreign = document.createElement("iframe");
|
||||
document.body.append(embedding, foreign);
|
||||
vi.stubGlobal("parent", embedding.contentWindow);
|
||||
try {
|
||||
for (const source of [foreign.contentWindow, null]) {
|
||||
window.dispatchEvent(new MessageEvent("message", { source, data: { type: "next" } }));
|
||||
}
|
||||
expect(onNext).not.toHaveBeenCalled();
|
||||
for (const source of [window, embedding.contentWindow]) {
|
||||
window.dispatchEvent(new MessageEvent("message", { source, data: { type: "next" } }));
|
||||
}
|
||||
expect(onNext).toHaveBeenCalledTimes(2);
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
embedding.remove();
|
||||
foreign.remove();
|
||||
el.remove();
|
||||
}
|
||||
});
|
||||
|
||||
it("handles postMessage next", () => {
|
||||
const el = document.createElement("hyperframes-slideshow") as any;
|
||||
document.body.appendChild(el);
|
||||
@@ -215,7 +239,7 @@ describe("<hyperframes-slideshow>", () => {
|
||||
currentSlide: { hotspots: [] },
|
||||
nextSlide: null,
|
||||
});
|
||||
window.dispatchEvent(new MessageEvent("message", { data: { type: "next" } }));
|
||||
window.dispatchEvent(new MessageEvent("message", { source: window, data: { type: "next" } }));
|
||||
expect(nextCalled).toBe(true);
|
||||
el.remove();
|
||||
});
|
||||
@@ -1981,7 +2005,7 @@ describe("<hyperframes-slideshow> Fix 7 — audience mode ignores window postMes
|
||||
currentSlide: { hotspots: [] },
|
||||
nextSlide: null,
|
||||
});
|
||||
window.dispatchEvent(new MessageEvent("message", { data: { type: "next" } }));
|
||||
window.dispatchEvent(new MessageEvent("message", { source: window, data: { type: "next" } }));
|
||||
expect(nextCalled).toBe(false);
|
||||
el.remove();
|
||||
});
|
||||
@@ -2003,7 +2027,7 @@ describe("<hyperframes-slideshow> Fix 7 — audience mode ignores window postMes
|
||||
currentSlide: { hotspots: [] },
|
||||
nextSlide: null,
|
||||
});
|
||||
window.dispatchEvent(new MessageEvent("message", { data: { type: "next" } }));
|
||||
window.dispatchEvent(new MessageEvent("message", { source: window, data: { type: "next" } }));
|
||||
expect(nextCalled).toBe(true);
|
||||
el.remove();
|
||||
});
|
||||
@@ -2474,7 +2498,7 @@ describe("<hyperframes-slideshow> Fix 4 — back affordance (postMessage only; c
|
||||
backCalled = true;
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(new MessageEvent("message", { data: { type: "back" } }));
|
||||
window.dispatchEvent(new MessageEvent("message", { source: window, data: { type: "back" } }));
|
||||
expect(backCalled).toBe(true);
|
||||
el.remove();
|
||||
});
|
||||
@@ -2488,7 +2512,7 @@ describe("<hyperframes-slideshow> Fix 4 — back affordance (postMessage only; c
|
||||
},
|
||||
});
|
||||
el.setAttribute("mode", "audience");
|
||||
window.dispatchEvent(new MessageEvent("message", { data: { type: "back" } }));
|
||||
window.dispatchEvent(new MessageEvent("message", { source: window, data: { type: "back" } }));
|
||||
expect(backCalled).toBe(false);
|
||||
el.remove();
|
||||
});
|
||||
|
||||
@@ -914,6 +914,7 @@ export class HyperframesSlideshow extends HTMLElement {
|
||||
|
||||
// fallow-ignore-next-line complexity
|
||||
private onMessage = (e: MessageEvent): void => {
|
||||
if (e.source !== window.parent && e.source !== window) return;
|
||||
// Audience mode is driven by BroadcastChannel; ignore embed postMessage nav.
|
||||
if (this.resolveMode() === "audience") return;
|
||||
const data = e.data as { type?: unknown; slideIndex?: unknown } | null;
|
||||
|
||||
@@ -4,6 +4,11 @@ import { expect, it, vi } from "vitest";
|
||||
|
||||
// Keep initialization at the asynchronous persistence boundary while exercising
|
||||
// the real static UI and its registered message listener.
|
||||
// The paused initializer never opens a composition. Keep unrelated SDK/parser
|
||||
// and raw animation-library transforms out of this message-boundary witness.
|
||||
vi.mock("@hyperframes/sdk", () => ({ openComposition: vi.fn() }));
|
||||
vi.mock("@hyperframes/core/gsap-parser-acorn", () => ({ parseGsapScriptAcorn: vi.fn() }));
|
||||
vi.mock("gsap/dist/gsap.min.js?raw", () => ({ default: "" }));
|
||||
vi.mock("./fileAdapter.js", () => ({
|
||||
createFileAdapter: () => new Promise(() => {}),
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user