import { describe, expect, test } from "bun:test" import { collectOpenProjectDeepLinks, drainPendingDeepLinks, parseDeepLink } from "./deep-links" import { displayName, errorMessage, getDraggableId, syncWorkspaceOrder, workspaceKey } from "./helpers" describe("layout deep links", () => { test("parses open-project deep links", () => { expect(parseDeepLink("opencode://open-project?directory=/tmp/demo")).toBe("/tmp/demo") }) test("ignores non-project deep links", () => { expect(parseDeepLink("opencode://other?directory=/tmp/demo")).toBeUndefined() expect(parseDeepLink("https://example.com")).toBeUndefined() }) test("ignores malformed deep links safely", () => { expect(() => parseDeepLink("opencode://open-project/%E0%A4%A%")).not.toThrow() expect(parseDeepLink("opencode://open-project/%E0%A4%A%")).toBeUndefined() }) test("parses links when URL.canParse is unavailable", () => { const original = Object.getOwnPropertyDescriptor(URL, "canParse") Object.defineProperty(URL, "canParse", { configurable: true, value: undefined }) try { expect(parseDeepLink("opencode://open-project?directory=/tmp/demo")).toBe("/tmp/demo") } finally { if (original) Object.defineProperty(URL, "canParse", original) if (!original) Reflect.deleteProperty(URL, "canParse") } }) test("ignores open-project deep links without directory", () => { expect(parseDeepLink("opencode://open-project")).toBeUndefined() expect(parseDeepLink("opencode://open-project?directory=")).toBeUndefined() }) test("collects only valid open-project directories", () => { const result = collectOpenProjectDeepLinks([ "opencode://open-project?directory=/a", "opencode://other?directory=/b", "opencode://open-project?directory=/c", ]) expect(result).toEqual(["/a", "/c"]) }) test("drains global deep links once", () => { const target = { __OPENCODE__: { deepLinks: ["opencode://open-project?directory=/a"], }, } as unknown as Window & { __OPENCODE__?: { deepLinks?: string[] } } expect(drainPendingDeepLinks(target)).toEqual(["opencode://open-project?directory=/a"]) expect(drainPendingDeepLinks(target)).toEqual([]) }) }) describe("layout workspace helpers", () => { test("normalizes trailing slash in workspace key", () => { expect(workspaceKey("/tmp/demo///")).toBe("/tmp/demo") expect(workspaceKey("C:\\tmp\\demo\\\\")).toBe("C:\\tmp\\demo") }) test("preserves posix and drive roots in workspace key", () => { expect(workspaceKey("/")).toBe("/") expect(workspaceKey("///")).toBe("/") expect(workspaceKey("C:\\")).toBe("C:\\") expect(workspaceKey("C:\\\\\\")).toBe("C:\\") expect(workspaceKey("C:///")).toBe("C:/") }) test("keeps local first while preserving known order", () => { const result = syncWorkspaceOrder("/root", ["/root", "/b", "/c"], ["/root", "/c", "/a", "/b"]) expect(result).toEqual(["/root", "/c", "/b"]) }) test("extracts draggable id safely", () => { expect(getDraggableId({ draggable: { id: "x" } })).toBe("x") expect(getDraggableId({ draggable: { id: 42 } })).toBeUndefined() expect(getDraggableId(null)).toBeUndefined() }) test("formats fallback project display name", () => { expect(displayName({ worktree: "/tmp/app" })).toBe("app") expect(displayName({ worktree: "/tmp/app", name: "My App" })).toBe("My App") }) test("extracts api error message and fallback", () => { expect(errorMessage({ data: { message: "boom" } }, "fallback")).toBe("boom") expect(errorMessage(new Error("broken"), "fallback")).toBe("broken") expect(errorMessage("unknown", "fallback")).toBe("fallback") }) })