Files
claude-code/src/utils/__tests__/json.test.ts
claude-code-best 1173a62301 refactor: 统一 log.ts/debug.ts 的测试 mock 为共享定义
- 新增 tests/mocks/log.ts 和 tests/mocks/debug.ts,覆盖源文件全部实际导出
- 移除旧 mock 中不存在的导出(logToFile、logEvent、getLogFilePath)
- 13 个测试文件改为使用共享 mock,避免定义分散和不一致

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-23 11:39:53 +08:00

150 lines
4.7 KiB
TypeScript

import { mock, describe, expect, test } from "bun:test";
import { logMock } from "../../../tests/mocks/log";
// Mock log.ts to cut the heavy dependency chain (log.ts → bootstrap/state.ts → analytics)
mock.module("src/utils/log.ts", logMock);
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"]);
});
});