/ tests / utils / error-handler-supplement.test.js
error-handler-supplement.test.js
 1  /**
 2   * Error Handler Supplement — Hit JSON repair control-char paths (lines 126-139)
 3   *
 4   * safeJsonParse has a second-attempt repair path that escapes raw \n \r \t
 5   * control characters inside JSON string values. These branches are hit when:
 6   * 1. Initial JSON.parse fails (the JSON has raw control chars)
 7   * 2. The repair loop encounters: escaped chars (\\), backslash-in-string,
 8   *    quote toggling, and raw \n \r \t inside strings
 9   */
10  
11  import { test, describe } from 'node:test';
12  import assert from 'node:assert/strict';
13  import { safeJsonParse } from '../../src/utils/error-handler.js';
14  
15  describe('safeJsonParse - JSON repair control-char paths', () => {
16    test('repairs raw \\n inside JSON string (line 135)', () => {
17      // A JSON string with a literal newline char (invalid JSON)
18      const raw = '{"msg":"hello\nworld"}';
19      const result = safeJsonParse(raw);
20      assert.ok(result !== null, 'should repair and return object');
21      assert.ok(
22        result.msg.includes('\n') || result.msg.includes('\\n') || result.msg === 'hello\nworld'
23      );
24    });
25  
26    test('repairs raw \\r inside JSON string (line 137)', () => {
27      const raw = '{"msg":"line1\rline2"}';
28      const result = safeJsonParse(raw);
29      assert.ok(result !== null, 'should repair \\r in string');
30    });
31  
32    test('repairs raw \\t inside JSON string (line 139)', () => {
33      const raw = '{"msg":"col1\tcol2"}';
34      const result = safeJsonParse(raw);
35      assert.ok(result !== null, 'should repair \\t in string');
36    });
37  
38    test('handles backslash-escaped char in string (lines 128-130)', () => {
39      // Valid JSON with backslash escape — should parse on first attempt
40      const raw = '{"path":"C:\\\\Users\\\\test"}';
41      const result = safeJsonParse(raw);
42      assert.ok(result !== null);
43      assert.equal(result.path, 'C:\\Users\\test');
44    });
45  
46    test('handles quote toggling in repair loop (lines 131-133)', () => {
47      // JSON with multiple string fields — quotes toggle inString state
48      const raw = '{"a":"hello\nworld","b":"foo\tbar"}';
49      const result = safeJsonParse(raw);
50      assert.ok(result !== null, 'should parse multi-field JSON with control chars');
51      assert.ok(result.a !== undefined);
52      assert.ok(result.b !== undefined);
53    });
54  
55    test('mixed: raw newlines and escaped backslashes together', () => {
56      // A string with both raw newlines and a backslash escape — exercises both paths
57      const raw = '{"text":"line1\nline2\\nstill_line2"}';
58      const result = safeJsonParse(raw);
59      // Either it repairs successfully or returns null — just don't throw
60      assert.ok(result === null || typeof result === 'object');
61    });
62  
63    test('returns fallback when repair also fails (totally invalid JSON)', () => {
64      const result = safeJsonParse('{broken json without quotes at all}', 'fallback');
65      assert.equal(result, 'fallback');
66    });
67  });