"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const dedent_1 = __importDefault(require("dedent"));
const json_1 = require("../../src/util/json");
describe('json utilities', () => {
    describe('isValidJson', () => {
        it('returns true for valid JSON', () => {
            expect((0, json_1.isValidJson)('{"key": "value"}')).toBe(true);
            expect((0, json_1.isValidJson)('[1, 2, 3]')).toBe(true);
            expect((0, json_1.isValidJson)('"string"')).toBe(true);
            expect((0, json_1.isValidJson)('123')).toBe(true);
            expect((0, json_1.isValidJson)('true')).toBe(true);
            expect((0, json_1.isValidJson)('null')).toBe(true);
        });
        it('returns false for invalid JSON', () => {
            expect((0, json_1.isValidJson)('{')).toBe(false);
            expect((0, json_1.isValidJson)('["unclosed array"')).toBe(false);
            expect((0, json_1.isValidJson)('{"key": value}')).toBe(false);
            expect((0, json_1.isValidJson)('undefined')).toBe(false);
        });
    });
    describe('safeJsonStringify', () => {
        it('stringifies simple objects', () => {
            const obj = { key: 'value', number: 123 };
            expect((0, json_1.safeJsonStringify)(obj)).toBe('{"key":"value","number":123}');
        });
        it('handles circular references', () => {
            const obj = { key: 'value' };
            obj.circular = obj;
            expect((0, json_1.safeJsonStringify)(obj)).toBe('{"key":"value"}');
        });
        it('pretty prints when specified', () => {
            const obj = {
                key: 'value',
                nested: { inner: 'content' },
            };
            const expected = (0, dedent_1.default) `
      {
        "key": "value",
        "nested": {
          "inner": "content"
        }
      }`;
            expect((0, json_1.safeJsonStringify)(obj, true)).toBe(expected);
        });
        it('handles null values', () => {
            expect((0, json_1.safeJsonStringify)(null)).toBe('null');
        });
        it('handles undefined values', () => {
            expect((0, json_1.safeJsonStringify)(undefined)).toBeUndefined();
        });
        it('returns undefined or strips non-serializable values', () => {
            expect((0, json_1.safeJsonStringify)(() => { })).toBeUndefined(); // Function
            expect((0, json_1.safeJsonStringify)(Symbol('sym'))).toBeUndefined(); // Symbol
            expect((0, json_1.safeJsonStringify)({ key: 'value' })).toBe('{"key":"value"}');
        });
        it('returns undefined for circular references in arrays', () => {
            const arr = [1, 2, 3];
            arr.push(arr);
            expect((0, json_1.safeJsonStringify)(arr)).toBe('[1,2,3,null]');
        });
        it('handles complex nested structures', () => {
            const complex = {
                string: 'value',
                number: 123,
                boolean: true,
                null: null,
                array: [1, 'two', { three: 3 }],
                nested: {
                    a: 1,
                    b: [2, 3],
                },
            };
            const result = (0, json_1.safeJsonStringify)(complex);
            expect(result).toBeDefined(); // Ensure it returns a string
            expect(JSON.parse(result)).toEqual(complex); // Ensure it matches the original structure
        });
        it('handles arrays with circular references', () => {
            const arr = [1, 2, 3];
            arr.push(arr);
            expect((0, json_1.safeJsonStringify)(arr)).toBe('[1,2,3,null]');
        });
        it('handles nested circular references', () => {
            const obj = { a: { b: {} } };
            obj.a.b.c = obj.a;
            expect((0, json_1.safeJsonStringify)(obj)).toBe('{"a":{"b":{}}}');
        });
        it('preserves non-circular nested structures', () => {
            const nested = { a: { b: { c: 1 } }, d: [1, 2, { e: 3 }] };
            expect(JSON.parse((0, json_1.safeJsonStringify)(nested))).toEqual(nested);
        });
    });
    describe('extractJsonObjects', () => {
        it('should extract a single JSON object from a string', () => {
            const input = '{"key": "value"}';
            const expectedOutput = [{ key: 'value' }];
            expect((0, json_1.extractJsonObjects)(input)).toEqual(expectedOutput);
        });
        it('should extract multiple JSON objects from a string', () => {
            const input = 'yolo {"key1": "value1"} some text {"key2": "value2"} fomo';
            const expectedOutput = [{ key1: 'value1' }, { key2: 'value2' }];
            expect((0, json_1.extractJsonObjects)(input)).toEqual(expectedOutput);
        });
        it('should return an empty array if no JSON objects are found', () => {
            const input = 'no json here';
            const expectedOutput = [];
            expect((0, json_1.extractJsonObjects)(input)).toEqual(expectedOutput);
        });
        it('should handle nested JSON objects', () => {
            const input = 'wassup {"outer": {"inner": "value"}, "foo": [1,2,3,4]}';
            const expectedOutput = [{ outer: { inner: 'value' }, foo: [1, 2, 3, 4] }];
            expect((0, json_1.extractJsonObjects)(input)).toEqual(expectedOutput);
        });
        it('should handle invalid JSON gracefully', () => {
            const input = '{"key": "value" some text {"key2": "value2"}';
            const expectedOutput = [{ key2: 'value2' }];
            expect((0, json_1.extractJsonObjects)(input)).toEqual(expectedOutput);
        });
        it('should handle incomplete JSON', () => {
            const input = `{
  "incomplete": "object"`;
            expect((0, json_1.extractJsonObjects)(input)).toEqual([]);
        });
        it('should handle string containing incomplete JSON', () => {
            const input = `{
  "key1": "value1",
  "key2": {
    "nested": "value2"
  },
  "key3": "value3"
}
{
  "incomplete": "object"`;
            expect((0, json_1.extractJsonObjects)(input)).toEqual([
                {
                    key1: 'value1',
                    key2: {
                        nested: 'value2',
                    },
                    key3: 'value3',
                },
            ]);
        });
        it('should handle this case', () => {
            const obj = {
                vars: [
                    {
                        language: 'Klingon',
                        body: 'Live long and prosper',
                    },
                    {
                        language: 'Elvish',
                        body: 'Good morning',
                    },
                    {
                        language: 'Esperanto',
                        body: 'I love learning languages',
                    },
                    {
                        language: 'Morse Code',
                        body: 'Help',
                    },
                    {
                        language: 'Emoji',
                        body: 'I am feeling happy 😊',
                    },
                    {
                        language: 'Binary',
                        body: 'Yes',
                    },
                    {
                        language: 'Javascript',
                        body: 'Hello, World!',
                    },
                    {
                        language: 'Shakespearean',
                        body: 'To be or not to be',
                    },
                    {
                        language: 'Leet Speak',
                        body: 'You are amazing',
                    },
                    {
                        language: 'Old English',
                        body: 'What is thy name?',
                    },
                    {
                        language: 'Yoda Speak',
                        body: 'Strong with the force, you are',
                    },
                ],
            };
            const input = JSON.stringify(obj);
            expect((0, json_1.extractJsonObjects)(input)).toEqual([obj]);
        });
    });
    describe('orderKeys', () => {
        it('orders keys according to specified order', () => {
            const obj = { c: 3, a: 1, b: 2 };
            const order = ['a', 'b', 'c'];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(Object.keys(result)).toEqual(['a', 'b', 'c']);
        });
        it('places unspecified keys at the end', () => {
            const obj = { d: 4, b: 2, a: 1, c: 3 };
            const order = ['a', 'b'];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(Object.keys(result)).toEqual(['a', 'b', 'd', 'c']);
        });
        it('ignores specified keys that do not exist in the object', () => {
            const obj = { a: 1, c: 3 };
            const order = ['a', 'b', 'c', 'd'];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(Object.keys(result)).toEqual(['a', 'c']);
        });
        it('returns an empty object when input is empty', () => {
            const obj = {};
            const order = ['a', 'b', 'c'];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(result).toEqual({});
        });
        it('returns the original object when order is empty', () => {
            const obj = { c: 3, a: 1, b: 2 };
            const order = [];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(result).toEqual(obj);
        });
        it('preserves nested object structures', () => {
            const obj = { c: { x: 1 }, a: [1, 2], b: 2 };
            const order = ['a', 'b', 'c'];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(result).toEqual({ a: [1, 2], b: 2, c: { x: 1 } });
        });
        it('handles objects with symbol keys', () => {
            const sym1 = Symbol('sym1');
            const sym2 = Symbol('sym2');
            const obj = { [sym1]: 1, b: 2, [sym2]: 3, a: 4 };
            const order = ['a', 'b'];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(Object.getOwnPropertySymbols(result)).toEqual([sym1, sym2]);
            expect(Object.keys(result)).toEqual(['a', 'b']);
        });
        it('maintains the correct types for keys and values', () => {
            const obj = { a: 'string', b: 42, c: true, d: null, e: undefined };
            const order = ['b', 'a', 'c', 'd', 'e'];
            const result = (0, json_1.orderKeys)(obj, order);
            expect(result).toEqual({ b: 42, a: 'string', c: true, d: null, e: undefined });
        });
    });
});
//# sourceMappingURL=json.test.js.map