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']) }) })