import { mock, describe, expect, test } from "bun:test"; // Mock log.ts to cut the heavy dependency chain (log.ts → bootstrap/state.ts → analytics) mock.module("src/utils/log.ts", () => ({ logError: () => {}, logToFile: () => {}, getLogDisplayTitle: () => "", logEvent: () => {}, })); const { safeParseJSON, safeParseJSONC, parseJSONL, addItemToJSONCArray } = await import("../json"); // ─── safeParseJSON ────────────────────────────────────────────────────── describe("safeParseJSON", () => { test("parses valid object", () => { expect(safeParseJSON('{"a":1}')).toEqual({ a: 1 }); }); test("parses valid array", () => { expect(safeParseJSON("[1,2,3]")).toEqual([1, 2, 3]); }); test("parses string value", () => { expect(safeParseJSON('"hello"')).toBe("hello"); }); test("parses number value", () => { expect(safeParseJSON("42")).toBe(42); }); test("parses boolean value", () => { expect(safeParseJSON("true")).toBe(true); }); test("parses null value", () => { expect(safeParseJSON("null")).toBeNull(); }); test("returns null for invalid JSON", () => { expect(safeParseJSON("{bad}")).toBeNull(); }); test("returns null for empty string", () => { expect(safeParseJSON("")).toBeNull(); }); test("returns null for undefined input", () => { expect(safeParseJSON(undefined as any)).toBeNull(); }); test("returns null for null input", () => { expect(safeParseJSON(null as any)).toBeNull(); }); test("handles JSON with BOM", () => { expect(safeParseJSON('\uFEFF{"a":1}')).toEqual({ a: 1 }); }); test("parses nested objects", () => { const input = '{"a":{"b":{"c":1}}}'; expect(safeParseJSON(input)).toEqual({ a: { b: { c: 1 } } }); }); }); // ─── safeParseJSONC ───────────────────────────────────────────────────── describe("safeParseJSONC", () => { test("parses standard JSON", () => { expect(safeParseJSONC('{"a":1}')).toEqual({ a: 1 }); }); test("parses JSON with single-line comments", () => { expect(safeParseJSONC('{\n// comment\n"a":1\n}')).toEqual({ a: 1 }); }); test("parses JSON with block comments", () => { expect(safeParseJSONC('{\n/* comment */\n"a":1\n}')).toEqual({ a: 1 }); }); test("parses JSON with trailing commas", () => { expect(safeParseJSONC('{"a":1,}')).toEqual({ a: 1 }); }); test("returns null for null input", () => { expect(safeParseJSONC(null as any)).toBeNull(); }); test("returns null for empty string", () => { expect(safeParseJSONC("")).toBeNull(); }); }); // ─── parseJSONL ───────────────────────────────────────────────────────── describe("parseJSONL", () => { test("parses multiple lines", () => { const result = parseJSONL('{"a":1}\n{"b":2}'); expect(result).toEqual([{ a: 1 }, { b: 2 }]); }); test("returns empty array for empty string", () => { expect(parseJSONL("")).toEqual([]); }); test("parses single line", () => { expect(parseJSONL('{"a":1}')).toEqual([{ a: 1 }]); }); test("accepts Buffer input", () => { const buf = Buffer.from('{"x":1}\n{"y":2}'); const result = parseJSONL(buf as any); expect(result).toEqual([{ x: 1 }, { y: 2 }]); }); // NOTE: Skipping malformed-line test — Bun.JSONL.parseChunk hangs // indefinitely in its error-recovery loop when encountering bad lines. }); // ─── addItemToJSONCArray ──────────────────────────────────────────────── describe("addItemToJSONCArray", () => { test("appends to existing array", () => { const result = addItemToJSONCArray('["a","b"]', "c"); const parsed = JSON.parse(result); expect(parsed).toEqual(["a", "b", "c"]); }); test("appends to empty array", () => { const result = addItemToJSONCArray("[]", "item"); const parsed = JSON.parse(result); expect(parsed).toEqual(["item"]); }); test("creates array from empty content", () => { const result = addItemToJSONCArray("", "first"); const parsed = JSON.parse(result); expect(parsed).toEqual(["first"]); }); test("handles object item", () => { const result = addItemToJSONCArray("[]", { key: "val" }); const parsed = JSON.parse(result); expect(parsed).toEqual([{ key: "val" }]); }); test("wraps item in new array for non-array content", () => { const result = addItemToJSONCArray('{"a":1}', "item"); const parsed = JSON.parse(result); expect(parsed).toEqual(["item"]); }); });