Files
hyperframes/packages/studio/src/hooks/useSlideshowTabState.test.ts
T
Vance Ingalls 53b3621437 fix(studio): short-circuit slideshow-island detection with a substring check (review N2)
slideshowIslandRegex scanned the full file content on every editingFile
change even for the common non-slideshow case. Gate it behind a plain
substring check on SLIDESHOW_ISLAND_TYPE first — cheap, and avoids the
full-content RegExp pass for files that plainly have no island.

Added a test for the still-open behavior this preserves: a malformed
island (invalid JSON) still trips the substring check and the regex,
so the tab stays discoverable rather than silently disappearing.
2026-07-17 00:37:39 -07:00

97 lines
3.6 KiB
TypeScript

// @vitest-environment happy-dom
import React, { act } from "react";
import { createRoot } from "react-dom/client";
import { afterEach, describe, expect, it } from "vitest";
import { useSlideshowTabState } from "./useSlideshowTabState";
import type { RightPanelTab } from "../utils/studioHelpers";
(globalThis as unknown as { IS_REACT_ACT_ENVIRONMENT: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
const SLIDESHOW_HTML = `<html><body><script type="application/hyperframes-slideshow+json">{"slides":[]}</script></body></html>`;
const PLAIN_HTML = `<html><body><div id="title">hi</div></body></html>`;
afterEach(() => {
document.body.innerHTML = "";
});
function renderHook(params: {
editingFileContent: string | null | undefined;
rightPanelTab: RightPanelTab;
}) {
const host = document.createElement("div");
document.body.append(host);
const root = createRoot(host);
const setRightPanelTabCalls: RightPanelTab[] = [];
let current: ReturnType<typeof useSlideshowTabState> | null = null;
function Harness() {
current = useSlideshowTabState({
editingFileContent: params.editingFileContent,
previewIframeRef: { current: null },
refreshKey: 0,
rightPanelTab: params.rightPanelTab,
setRightPanelTab: (tab) => setRightPanelTabCalls.push(tab),
});
return null;
}
act(() => {
root.render(React.createElement(Harness));
});
return {
getState: (): ReturnType<typeof useSlideshowTabState> => {
if (!current) throw new Error("useSlideshowTabState did not render");
return current;
},
setRightPanelTabCalls,
unmount: () => act(() => root.unmount()),
};
}
describe("useSlideshowTabState", () => {
it("detects a slideshow composition via the JSON island", () => {
const harness = renderHook({ editingFileContent: SLIDESHOW_HTML, rightPanelTab: "design" });
expect(harness.getState().isSlideshowComposition).toBe(true);
harness.unmount();
});
it("reports false for a plain (non-slideshow) composition", () => {
const harness = renderHook({ editingFileContent: PLAIN_HTML, rightPanelTab: "design" });
expect(harness.getState().isSlideshowComposition).toBe(false);
harness.unmount();
});
it("reports false when there is no editing file yet", () => {
const harness = renderHook({ editingFileContent: undefined, rightPanelTab: "design" });
expect(harness.getState().isSlideshowComposition).toBe(false);
harness.unmount();
});
it("still detects a malformed island — presence-only, not full manifest validation", () => {
const malformed = `<html><body><script type="application/hyperframes-slideshow+json">{not valid json</script></body></html>`;
const harness = renderHook({ editingFileContent: malformed, rightPanelTab: "design" });
expect(harness.getState().isSlideshowComposition).toBe(true);
harness.unmount();
});
it("bounces rightPanelTab off 'slideshow' to 'renders' on a non-slideshow composition", () => {
const harness = renderHook({ editingFileContent: PLAIN_HTML, rightPanelTab: "slideshow" });
expect(harness.setRightPanelTabCalls).toEqual(["renders"]);
harness.unmount();
});
it("does not bounce when the composition is a slideshow", () => {
const harness = renderHook({ editingFileContent: SLIDESHOW_HTML, rightPanelTab: "slideshow" });
expect(harness.setRightPanelTabCalls).toEqual([]);
harness.unmount();
});
it("does not bounce a tab other than 'slideshow'", () => {
const harness = renderHook({ editingFileContent: PLAIN_HTML, rightPanelTab: "renders" });
expect(harness.setRightPanelTabCalls).toEqual([]);
harness.unmount();
});
});