test(app): 補齊 isSafeRepoPath/extractBalancedJSON/normalizeText/repairJSONArrayWithAI/格式化函式測試

為可測性 export 三個內部函式(isSafeRepoPath、extractBalancedJSON/extractJSONText、normalizeText)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeffery
2026-06-26 14:41:41 +08:00
co-authored by Claude Opus 4.8
parent fc10ab7266
commit 775cc575ae
8 changed files with 354 additions and 5 deletions
+88
View File
@@ -1,6 +1,7 @@
import { describe, it, beforeEach, afterEach, mock } from 'node:test';
import assert from 'node:assert/strict';
import axios from 'axios';
import { extractBalancedJSON, extractJSONText } from '../llm.js';
const ENV_KEYS = [
'OPENCODE_BASE_URL', 'OPENCODE_MODEL', 'OPENCODE_PROVIDER',
@@ -143,3 +144,90 @@ describe('chatJSON', async () => {
assert.deepEqual(result, []);
});
});
describe('extractBalancedJSON', () => {
it('returns the whole object for a simple object from index 0', () => {
const text = '{"a":1}';
assert.equal(extractBalancedJSON(text, 0), '{"a":1}');
});
it('returns the full balanced segment for deeply nested object/array', () => {
const text = '{"a":[1,{"b":[2,{"c":3}]}],"d":4}';
assert.equal(extractBalancedJSON(text, 0), '{"a":[1,{"b":[2,{"c":3}]}],"d":4}');
});
it('does not let braces inside a string value break balancing', () => {
const text = '{"a":"}{"}';
assert.equal(extractBalancedJSON(text, 0), '{"a":"}{"}');
});
it('handles an escaped quote inside a string value', () => {
const text = '{"a":"\\""}';
assert.equal(extractBalancedJSON(text, 0), '{"a":"\\""}');
});
it('returns null for truncated/incomplete JSON', () => {
const text = '{"a":1';
assert.equal(extractBalancedJSON(text, 0), null);
});
it('extracts a balanced array when starting at a "["', () => {
const text = '[1,[2,3],{"a":4}]';
assert.equal(extractBalancedJSON(text, 0), '[1,[2,3],{"a":4}]');
});
it('excludes trailing content after the balanced segment', () => {
const text = '{"a":1} trailing text {"b":2}';
assert.equal(extractBalancedJSON(text, 0), '{"a":1}');
});
});
describe('extractJSONText', () => {
it('strips a fenced ```json block', () => {
const text = '```json\n{"a":1}\n```';
const result = extractJSONText(text);
assert.deepEqual(JSON.parse(result), { a: 1 });
});
it('extracts a JSON object after leading prose', () => {
const text = 'Here are the findings:\n{"level":"critical"}';
const result = extractJSONText(text);
assert.deepEqual(JSON.parse(result), { level: 'critical' });
});
it('extracts an array embedded in surrounding text', () => {
const text = 'prefix [1,2,3] suffix';
const result = extractJSONText(text);
assert.deepEqual(JSON.parse(result), [1, 2, 3]);
});
it('returns an already-pure JSON string as-is', () => {
const text = '{"a":1,"b":[2,3]}';
const result = extractJSONText(text);
assert.equal(result, '{"a":1,"b":[2,3]}');
assert.deepEqual(JSON.parse(result), { a: 1, b: [2, 3] });
});
it('returns the de-fenced original text when no valid JSON is found', () => {
const text = '```\nnot json at all\n```';
const result = extractJSONText(text);
assert.equal(result, 'not json at all');
});
});