1import { beforeEach, describe, expect, it } from "vite-plus/test";
2
3import {
4 completeConfirmDialogClose,
5 readConfirmDialogState,
6 requestConfirmDialog,
7 resetConfirmDialogForTests,
8 respondToConfirmDialog,
9 subscribeConfirmDialogHost,
10} from "./confirmDialog";
11
12const mountHost = () => subscribeConfirmDialogHost(() => {});
13
14function requireConfirmation(confirmation: Promise<boolean> | undefined): Promise<boolean> {
15 if (!confirmation) {
16 throw new Error("Expected a registered confirmation host.");
17 }
18 return confirmation;
19}
20
21describe("confirm dialog coordinator", () => {
22 beforeEach(() => {
23 resetConfirmDialogForTests();
24 });
25
26 it("serializes concurrent confirmations", async () => {
27 const unregister = mountHost();
28 const first = requireConfirmation(
29 requestConfirmDialog("Delete the project?", { initialFocus: "confirm" }),
30 );
31 const second = requireConfirmation(requestConfirmDialog("Delete the worktree too?"));
32
33 respondToConfirmDialog(false);
34 await expect(first).resolves.toBe(false);
35 expect(readConfirmDialogState()).toEqual({
36 status: "closing",
37 message: "Delete the project?",
38 variant: "default",
39 initialFocus: "confirm",
40 });
41
42 completeConfirmDialogClose();
43 expect(readConfirmDialogState()).toEqual({
44 status: "confirming",
45 message: "Delete the worktree too?",
46 variant: "default",
47 });
48
49 respondToConfirmDialog(true);
50 await expect(second).resolves.toBe(true);
51 completeConfirmDialogClose();
52 expect(readConfirmDialogState()).toEqual({ status: "idle" });
53 unregister();
54 });
55
56 it("cancels active and queued confirmations if the last host unmounts", async () => {
57 const unregister = mountHost();
58 const active = requireConfirmation(requestConfirmDialog("Delete the thread?"));
59 const queued = requireConfirmation(requestConfirmDialog("Delete the worktree too?"));
60
61 unregister();
62
63 await expect(Promise.all([active, queued])).resolves.toEqual([false, false]);
64 expect(readConfirmDialogState()).toEqual({ status: "idle" });
65 });
66
67 it("has no host until one subscribes", () => {
68 expect(requestConfirmDialog("Continue?")).toBeUndefined();
69 const unsubscribe = mountHost();
70 expect(requestConfirmDialog("Continue?")).toBeDefined();
71 unsubscribe();
72 expect(requestConfirmDialog("Continue?")).toBeUndefined();
73 });
74
75 it("ignores responses after the active dialog has been closed", () => {
76 const unregister = mountHost();
77 const confirmation = requireConfirmation(requestConfirmDialog("Continue?"));
78
79 respondToConfirmDialog(true);
80 respondToConfirmDialog(false);
81 completeConfirmDialogClose();
82
83 expect(readConfirmDialogState()).toEqual({ status: "idle" });
84 unregister();
85 return expect(confirmation).resolves.toBe(true);
86 });
87});