"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const _1 = require(".");
const fast_js_1 = require("./fast.js");
const portable_js_1 = require("./portable.js");
// an object with keys that are intentionally out of order
const obj1 = {
    // some alphanumeric keys
    b: 0,
    a: 1,
    // some keys that could be interpreted as indices
    '1': 2,
    '10': 3,
    '7': 4,
    // some keys that could be interpreted as numbers but not as indices
    '2.0': 5,
    '10.0': 6,
    '+0': 7,
    '-0': 8,
    // a key that sorts before the numeric keys, but should appear after the indices
    $c: 9,
    // Symbol keys should be ignored
    [Symbol('f')]: 10
};
const expectedObj1String = '{"1":2,"7":4,"10":3,"$c":9,"+0":7,"-0":8,"10.0":6,"2.0":5,"a":1,"b":0}';
// a class with a toJSON method that returns an object
class ClassWithToJSON {
    toJSON() {
        return obj1;
    }
}
// an object with a property that is an instance of a class with a toJSON method
const obj2 = {
    a: new ClassWithToJSON()
};
const stableJSONStringify_implementations = {
    stableJSONStringify_fast: fast_js_1.stableJSONStringify_fast,
    stableJSONStringify_portable: portable_js_1.stableJSONStringify_portable
};
// an object with keys that should be ignored because of their value type
const obj3 = {
    a: undefined,
    b: () => {
        /* do nothing */
    }
};
const complexObj = {
    // deliberately out of order
    obj3,
    obj1,
    obj2,
    booleanKey: true
};
(0, vitest_1.describe)('stableJSONStringify', () => {
    (0, vitest_1.describe)('object keys should be returned in canonical order', () => {
        vitest_1.test.each(Object.entries(stableJSONStringify_implementations))('stableJSONStringify implementation: %s', (_name, stringify) => {
            const str1 = stringify(obj1);
            (0, vitest_1.expect)(str1).toEqual(expectedObj1String);
            // verify that the canonicalization is applied recursively to objects returned by toJSON methods
            const str2 = stringify(obj2);
            (0, vitest_1.expect)(str2).toEqual('{"a":' + expectedObj1String + '}');
        });
    });
    (0, vitest_1.describe)('some object properties should be skipped', () => {
        vitest_1.test.each(Object.entries(stableJSONStringify_implementations))('stableJSONStringify implementation: %s', (_name, stringify) => {
            (0, vitest_1.expect)(stringify(obj3)).toEqual('{}');
        });
    });
    (0, vitest_1.describe)('skipped values are treated as null in arrays', () => {
        vitest_1.test.each(Object.entries(stableJSONStringify_implementations))('stableJSONStringify implementation: %s', (_name, stringify) => {
            const values = Object.values(obj3);
            const expected = '[' + new Array(values.length).fill('null').join(',') + ']';
            (0, vitest_1.expect)(stringify(values)).toEqual(expected);
        });
    });
    (0, vitest_1.describe)('escaping of characters in strings is consistent', () => {
        vitest_1.test.each(Object.entries(stableJSONStringify_implementations))('stableJSONStringify implementation: %s', (_name, stringify) => {
            (0, vitest_1.expect)(stringify(_1.testStringSrc)).toEqual(_1.testStringOut);
        });
    });
    (0, vitest_1.test)('the two implementations agree on a complex object', () => {
        (0, vitest_1.expect)((0, fast_js_1.stableJSONStringify_fast)(complexObj)).toEqual((0, portable_js_1.stableJSONStringify_portable)(complexObj));
    });
});
//# sourceMappingURL=index.test.js.map