import { describe, expect, test } from "bun:test"; import { parseJsonList } from "../src/core/sl0ppij.ts"; // The crash a user actually hit: `action list-panes --json` on a session that // died underneath us exits 0 with EMPTY stdout, and JSON.parse("") threw // "JSON Parse error: Unexpected EOF" at them on startup. describe("parseJsonList", () => { test("empty output is nothing, not a crash", () => { expect(parseJsonList("", "list-panes")).toEqual([]); expect(parseJsonList(" \n", "list-panes")).toEqual([]); }); test("parses a normal listing", () => { expect(parseJsonList('[{"position":0}]', "list-tabs")).toEqual([{ position: 0 }] as never); }); test("genuinely malformed output names the command and shows the text", () => { expect(() => parseJsonList("There is no active session!", "list-tabs")).toThrow( /list-tabs returned something that is not JSON: There is no active session!/, ); }); test("a non-array payload is treated as nothing rather than crashing later", () => { expect(parseJsonList('{"error":"nope"}', "list-tabs")).toEqual([]); }); }); import { UserError } from "../src/core/errors.ts"; // Actionable answers must not be replaced by a raw multiplexer. Falling through // on "no project called foo" hides the answer AND starts a session nobody asked // for. describe("UserError", () => { test("is distinguishable from a bug", () => { expect(new UserError("nope") instanceof UserError).toBe(true); expect(new UserError("nope") instanceof Error).toBe(true); expect(new Error("boom") instanceof UserError).toBe(false); }); });