fix(studio): guard storyboard history navigation

This commit is contained in:
James
2026-07-16 15:49:40 -04:00
parent ded443647d
commit 68beec0e76
2 changed files with 72 additions and 11 deletions
@@ -98,8 +98,16 @@ function clickButton(host: HTMLElement, label: string): void {
act(() => button.dispatchEvent(new MouseEvent("click", { bubbles: true })));
}
async function goBack(): Promise<void> {
await act(async () => {
window.history.back();
await new Promise((resolve) => setTimeout(resolve, 0));
});
}
beforeEach(() => {
window.history.replaceState({}, "", "/?view=storyboard");
window.history.replaceState({ entry: "timeline" }, "", "/");
window.history.pushState({ entry: "storyboard" }, "", "/?view=storyboard");
onSelectComposition.mockReset();
});
@@ -140,4 +148,23 @@ describe("dirty storyboard voiceover view-mode guard", () => {
expect(onSelectComposition).toHaveBeenCalledWith("frames/01-opening.html");
act(() => root.unmount());
});
it("guards browser history transitions on decline and allows them on accept", async () => {
const confirm = vi.spyOn(window, "confirm").mockReturnValue(false);
const { host, root } = renderApp();
makeVoiceoverDirty(host);
await goBack();
expect(host.querySelector("[data-view-mode]")?.textContent).toBe("storyboard");
expect(window.location.search).toBe("?view=storyboard");
expect(window.history.state).toEqual({ entry: "storyboard" });
expect(confirm).toHaveBeenCalledWith("Discard unsaved voiceover changes?");
confirm.mockReturnValue(true);
await goBack();
expect(host.querySelector("[data-view-mode]")?.textContent).toBe("timeline");
expect(window.location.search).toBe("");
expect(window.history.state).toEqual({ entry: "timeline" });
act(() => root.unmount());
});
});