Warn on tab close when create-flow module or wizard edits have not been saved.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilallo
2026-08-31 11:00:40 -06:00
co-authored by Cursor
parent a820739d07
commit 7f67cc6271
19 changed files with 350 additions and 1 deletions
@@ -0,0 +1,26 @@
import { renderHook } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import { useBeforeUnloadGuard } from "../../../app/hooks/useBeforeUnloadGuard";
import { dispatchBeforeUnload } from "../../utils/test-utils";
describe("useBeforeUnloadGuard", () => {
it("does not intercept unload when disabled", () => {
renderHook(() => useBeforeUnloadGuard(false));
expect(dispatchBeforeUnload()).toBe(false);
});
it("prevents unload when enabled", () => {
renderHook(() => useBeforeUnloadGuard(true));
expect(dispatchBeforeUnload()).toBe(true);
});
it("drops the listener when enabled flips to false", () => {
const { rerender } = renderHook(
({ enabled }) => useBeforeUnloadGuard(enabled),
{ initialProps: { enabled: true } },
);
expect(dispatchBeforeUnload()).toBe(true);
rerender({ enabled: false });
expect(dispatchBeforeUnload()).toBe(false);
});
});
@@ -0,0 +1,29 @@
import { describe, expect, it } from "vitest";
import {
captureMethodCardCustomizeSnapshot,
isMethodCardCustomizeUnloadBlocked,
} from "../../lib/create/methodCardCustomizeSession";
const HEADER_0 = { title: "", description: "" };
describe("isMethodCardCustomizeUnloadBlocked", () => {
it("is false when the modal is closed or snapshot is missing", () => {
const snap = captureMethodCardCustomizeSnapshot({ x: 1 }, null, HEADER_0);
expect(
isMethodCardCustomizeUnloadBlocked(false, snap, { x: 2 }, null, HEADER_0),
).toBe(false);
expect(
isMethodCardCustomizeUnloadBlocked(true, null, { x: 2 }, null, HEADER_0),
).toBe(false);
});
it("is true only when the open modal is dirty", () => {
const snap = captureMethodCardCustomizeSnapshot({ x: 1 }, null, HEADER_0);
expect(
isMethodCardCustomizeUnloadBlocked(true, snap, { x: 1 }, null, HEADER_0),
).toBe(false);
expect(
isMethodCardCustomizeUnloadBlocked(true, snap, { x: 2 }, null, HEADER_0),
).toBe(true);
});
});