import { EnvironmentId, ThreadId } from "@t3tools/contracts"; import { describe, expect, it } from "vite-plus/test"; import { requestThreadUnpinConfirmation, ThreadArchiveBlockedError } from "./useThreadActions"; describe("ThreadArchiveBlockedError", () => { it("keeps the blocked thread context with the fixed message", () => { const error = new ThreadArchiveBlockedError({ environmentId: EnvironmentId.make("environment-1"), threadId: ThreadId.make("thread-1"), }); expect(error).toMatchObject({ environmentId: "environment-1", threadId: "thread-1", }); expect(error.message).toBe("Cannot archive a running thread."); }); }); describe("requestThreadUnpinConfirmation", () => { it("skips the dialog when confirmation is disabled", async () => { let callCount = 0; const result = await requestThreadUnpinConfirmation({ enabled: false, title: "Pinned thread", confirm: async () => { callCount += 1; return false; }, }); expect(result).toMatchObject({ _tag: "Success", value: true }); expect(callCount).toBe(0); }); it("degrades gracefully when dialogs are unavailable", async () => { const result = await requestThreadUnpinConfirmation({ enabled: true, title: "Pinned thread", confirm: null, }); expect(result).toMatchObject({ _tag: "Success", value: true }); }); it("uses the thread title and returns the user's decision", async () => { let message = ""; const result = await requestThreadUnpinConfirmation({ enabled: true, title: "Release prep", confirm: async (nextMessage) => { message = nextMessage; return false; }, }); expect(message).toBe( 'Unpin thread "Release prep"?\nThis will move the thread out of your pinned section.', ); expect(result).toMatchObject({ _tag: "Success", value: false }); }); it("keeps dialog failures observable", async () => { const result = await requestThreadUnpinConfirmation({ enabled: true, title: "Pinned thread", confirm: () => Promise.reject(new Error("dialog unavailable")), }); expect(result._tag).toBe("Failure"); }); });