UNPKG

@wizard9/json-patch-apply

Version:

A library for describing, calculating, and applying patches to Javascript Objects.

365 lines 23.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = require("chai"); const index_1 = require("../index"); /** * DO NOT CHANGE - changes will be lost! * dynamically generated using generate_conformance.ts script see README.md file * for details on how to re-generate or change this file. */ describe("conformance", () => { function run_test(doc, patch, error, expected) { try { let result = index_1.Patch.apply(doc, ...patch); if (error) { throw new Error("Missing error: " + error); } else { chai_1.expect(result).eql(expected); } } catch (e) { if (error) { chai_1.expect(!!e.message, error).be.true; } else { chai_1.expect("Unexpected error: " + e.message + ", missing expected: " + JSON.stringify(expected)).eql('to pass'); } } } describe("tests.json - main tests", () => { it("empty list, empty docs", () => { run_test({}, [], undefined, {}); }); it("empty patch list", () => { run_test({ "foo": 1 }, [], undefined, { "foo": 1 }); }); it("rearrangements OK?", () => { run_test({ "foo": 1, "bar": 2 }, [], undefined, { "bar": 2, "foo": 1 }); }); it("rearrangements OK? How about one level down ... array", () => { run_test([{ "foo": 1, "bar": 2 }], [], undefined, [{ "bar": 2, "foo": 1 }]); }); it("rearrangements OK? How about one level down...", () => { run_test({ "foo": { "foo": 1, "bar": 2 } }, [], undefined, { "foo": { "bar": 2, "foo": 1 } }); }); it("add replaces any existing field", () => { run_test({ "foo": null }, [{ "op": "add", "path": "/foo", "value": 1 }], undefined, { "foo": 1 }); }); it("toplevel array", () => { run_test([], [{ "op": "add", "path": "/0", "value": "foo" }], undefined, ["foo"]); }); it("toplevel array, no change", () => { run_test(["foo"], [], undefined, ["foo"]); }); it("toplevel object, numeric string", () => { run_test({}, [{ "op": "add", "path": "/foo", "value": "1" }], undefined, { "foo": "1" }); }); it("toplevel object, integer", () => { run_test({}, [{ "op": "add", "path": "/foo", "value": 1 }], undefined, { "foo": 1 }); }); xit("Toplevel scalar values OK?", () => { run_test("foo", [{ "op": "replace", "path": "", "value": "bar" }], undefined, "bar"); }); it("replace object document with array document?", () => { run_test({}, [{ "op": "add", "path": "", "value": [] }], undefined, []); }); it("replace array document with object document?", () => { run_test([], [{ "op": "add", "path": "", "value": {} }], undefined, {}); }); it("append to root array document?", () => { run_test([], [{ "op": "add", "path": "/-", "value": "hi" }], undefined, ["hi"]); }); it("Add, / target", () => { run_test({}, [{ "op": "add", "path": "/", "value": 1 }], undefined, { "": 1 }); }); it("Add, /foo/ deep target (trailing slash)", () => { run_test({ "foo": {} }, [{ "op": "add", "path": "/foo/", "value": 1 }], undefined, { "foo": { "": 1 } }); }); it("Add composite value at top level", () => { run_test({ "foo": 1 }, [{ "op": "add", "path": "/bar", "value": [1, 2] }], undefined, { "foo": 1, "bar": [1, 2] }); }); it("Add into composite value", () => { run_test({ "foo": 1, "baz": [{ "qux": "hello" }] }, [{ "op": "add", "path": "/baz/0/foo", "value": "world" }], undefined, { "foo": 1, "baz": [{ "qux": "hello", "foo": "world" }] }); }); it("conformance #18", () => { run_test({ "bar": [1, 2] }, [{ "op": "add", "path": "/bar/8", "value": "5" }], "Out of bounds (upper)", undefined); }); it("conformance #19", () => { run_test({ "bar": [1, 2] }, [{ "op": "add", "path": "/bar/-1", "value": "5" }], "Out of bounds (lower)", undefined); }); it("conformance #20", () => { run_test({ "foo": 1 }, [{ "op": "add", "path": "/bar", "value": true }], undefined, { "foo": 1, "bar": true }); }); it("conformance #21", () => { run_test({ "foo": 1 }, [{ "op": "add", "path": "/bar", "value": false }], undefined, { "foo": 1, "bar": false }); }); it("conformance #22", () => { run_test({ "foo": 1 }, [{ "op": "add", "path": "/bar", "value": null }], undefined, { "foo": 1, "bar": null }); }); it("0 can be an array index or object element name", () => { run_test({ "foo": 1 }, [{ "op": "add", "path": "/0", "value": "bar" }], undefined, { "0": "bar", "foo": 1 }); }); it("conformance #24", () => { run_test(["foo"], [{ "op": "add", "path": "/1", "value": "bar" }], undefined, ["foo", "bar"]); }); it("conformance #25", () => { run_test(["foo", "sil"], [{ "op": "add", "path": "/1", "value": "bar" }], undefined, ["foo", "bar", "sil"]); }); it("conformance #26", () => { run_test(["foo", "sil"], [{ "op": "add", "path": "/0", "value": "bar" }], undefined, ["bar", "foo", "sil"]); }); it("push item to array via last index + 1", () => { run_test(["foo", "sil"], [{ "op": "add", "path": "/2", "value": "bar" }], undefined, ["foo", "sil", "bar"]); }); it("add item to array at index > length should fail", () => { run_test(["foo", "sil"], [{ "op": "add", "path": "/3", "value": "bar" }], "index is greater than number of items in array", undefined); }); it("test against implementation-specific numeric parsing", () => { run_test({ "1e0": "foo" }, [{ "op": "test", "path": "/1e0", "value": "foo" }], undefined, { "1e0": "foo" }); }); it("test with bad number should fail", () => { run_test(["foo", "bar"], [{ "op": "test", "path": "/1e0", "value": "bar" }], "test op shouldn't get array element 1", undefined); }); it("conformance #31", () => { run_test(["foo", "sil"], [{ "op": "add", "path": "/bar", "value": 42 }], "Object operation on array target", undefined); }); it("value in array add not flattened", () => { run_test(["foo", "sil"], [{ "op": "add", "path": "/1", "value": ["bar", "baz"] }], undefined, ["foo", ["bar", "baz"], "sil"]); }); it("conformance #33", () => { run_test({ "foo": 1, "bar": [1, 2, 3, 4] }, [{ "op": "remove", "path": "/bar" }], undefined, { "foo": 1 }); }); it("conformance #34", () => { run_test({ "foo": 1, "baz": [{ "qux": "hello" }] }, [{ "op": "remove", "path": "/baz/0/qux" }], undefined, { "foo": 1, "baz": [{}] }); }); it("conformance #35", () => { run_test({ "foo": 1, "baz": [{ "qux": "hello" }] }, [{ "op": "replace", "path": "/foo", "value": [1, 2, 3, 4] }], undefined, { "foo": [1, 2, 3, 4], "baz": [{ "qux": "hello" }] }); }); it("conformance #36", () => { run_test({ "foo": [1, 2, 3, 4], "baz": [{ "qux": "hello" }] }, [{ "op": "replace", "path": "/baz/0/qux", "value": "world" }], undefined, { "foo": [1, 2, 3, 4], "baz": [{ "qux": "world" }] }); }); it("conformance #37", () => { run_test(["foo"], [{ "op": "replace", "path": "/0", "value": "bar" }], undefined, ["bar"]); }); it("conformance #38", () => { run_test([""], [{ "op": "replace", "path": "/0", "value": 0 }], undefined, [0]); }); it("conformance #39", () => { run_test([""], [{ "op": "replace", "path": "/0", "value": true }], undefined, [true]); }); it("conformance #40", () => { run_test([""], [{ "op": "replace", "path": "/0", "value": false }], undefined, [false]); }); it("conformance #41", () => { run_test([""], [{ "op": "replace", "path": "/0", "value": null }], undefined, [null]); }); it("value in array replace not flattened", () => { run_test(["foo", "sil"], [{ "op": "replace", "path": "/1", "value": ["bar", "baz"] }], undefined, ["foo", ["bar", "baz"]]); }); it("replace whole document", () => { run_test({ "foo": "bar" }, [{ "op": "replace", "path": "", "value": { "baz": "qux" } }], undefined, { "baz": "qux" }); }); it("test replace with missing parent key should fail", () => { run_test({ "bar": "baz" }, [{ "op": "replace", "path": "/foo/bar", "value": false }], "replace op should fail with missing parent key", undefined); }); it("spurious patch properties", () => { run_test({ "foo": 1 }, [{ "op": "test", "path": "/foo", "value": 1, "spurious": 1 }], undefined, { "foo": 1 }); }); it("null value should be valid obj property", () => { run_test({ "foo": null }, [{ "op": "test", "path": "/foo", "value": null }], undefined, { "foo": null }); }); it("null value should be valid obj property to be replaced with something truthy", () => { run_test({ "foo": null }, [{ "op": "replace", "path": "/foo", "value": "truthy" }], undefined, { "foo": "truthy" }); }); it("null value should be valid obj property to be moved", () => { run_test({ "foo": null }, [{ "op": "move", "from": "/foo", "path": "/bar" }], undefined, { "bar": null }); }); it("null value should be valid obj property to be copied", () => { run_test({ "foo": null }, [{ "op": "copy", "from": "/foo", "path": "/bar" }], undefined, { "foo": null, "bar": null }); }); it("null value should be valid obj property to be removed", () => { run_test({ "foo": null }, [{ "op": "remove", "path": "/foo" }], undefined, {}); }); it("null value should still be valid obj property replace other value", () => { run_test({ "foo": "bar" }, [{ "op": "replace", "path": "/foo", "value": null }], undefined, { "foo": null }); }); it("test should pass despite rearrangement", () => { run_test({ "foo": { "foo": 1, "bar": 2 } }, [{ "op": "test", "path": "/foo", "value": { "bar": 2, "foo": 1 } }], undefined, { "foo": { "foo": 1, "bar": 2 } }); }); it("test should pass despite (nested) rearrangement", () => { run_test({ "foo": [{ "foo": 1, "bar": 2 }] }, [{ "op": "test", "path": "/foo", "value": [{ "bar": 2, "foo": 1 }] }], undefined, { "foo": [{ "foo": 1, "bar": 2 }] }); }); it("test should pass - no error", () => { run_test({ "foo": { "bar": [1, 2, 5, 4] } }, [{ "op": "test", "path": "/foo", "value": { "bar": [1, 2, 5, 4] } }], undefined, { "foo": { "bar": [1, 2, 5, 4] } }); }); it("conformance #55", () => { run_test({ "foo": { "bar": [1, 2, 5, 4] } }, [{ "op": "test", "path": "/foo", "value": [1, 2] }], "test op should fail", undefined); }); xit("Whole document", () => { run_test({ "foo": 1 }, [{ "op": "test", "path": "", "value": { "foo": 1 } }], undefined, undefined); }); it("Empty-string element", () => { run_test({ "": 1 }, [{ "op": "test", "path": "/", "value": 1 }], undefined, { "": 1 }); }); it("conformance #58", () => { run_test({ "foo": ["bar", "baz"], "": 0, "a/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8 }, [{ "op": "test", "path": "/foo", "value": ["bar", "baz"] }, { "op": "test", "path": "/foo/0", "value": "bar" }, { "op": "test", "path": "/", "value": 0 }, { "op": "test", "path": "/a~1b", "value": 1 }, { "op": "test", "path": "/c%d", "value": 2 }, { "op": "test", "path": "/e^f", "value": 3 }, { "op": "test", "path": "/g|h", "value": 4 }, { "op": "test", "path": "/i\\j", "value": 5 }, { "op": "test", "path": "/k\"l", "value": 6 }, { "op": "test", "path": "/ ", "value": 7 }, { "op": "test", "path": "/m~0n", "value": 8 }], undefined, { "": 0, " ": 7, "a/b": 1, "c%d": 2, "e^f": 3, "foo": ["bar", "baz"], "g|h": 4, "i\\j": 5, "k\"l": 6, "m~n": 8 }); }); it("Move to same location has no effect", () => { run_test({ "foo": 1 }, [{ "op": "move", "from": "/foo", "path": "/foo" }], undefined, { "foo": 1 }); }); it("conformance #60", () => { run_test({ "foo": 1, "baz": [{ "qux": "hello" }] }, [{ "op": "move", "from": "/foo", "path": "/bar" }], undefined, { "baz": [{ "qux": "hello" }], "bar": 1 }); }); it("conformance #61", () => { run_test({ "baz": [{ "qux": "hello" }], "bar": 1 }, [{ "op": "move", "from": "/baz/0/qux", "path": "/baz/1" }], undefined, { "baz": [{}, "hello"], "bar": 1 }); }); it("conformance #62", () => { run_test({ "baz": [{ "qux": "hello" }], "bar": 1 }, [{ "op": "copy", "from": "/baz/0", "path": "/boo" }], undefined, { "baz": [{ "qux": "hello" }], "bar": 1, "boo": { "qux": "hello" } }); }); it("replacing the root of the document is possible with add", () => { run_test({ "foo": "bar" }, [{ "op": "add", "path": "", "value": { "baz": "qux" } }], undefined, { "baz": "qux" }); }); it("Adding to \"/-\" adds to the end of the array", () => { run_test([1, 2], [{ "op": "add", "path": "/-", "value": { "foo": ["bar", "baz"] } }], undefined, [1, 2, { "foo": ["bar", "baz"] }]); }); it("Adding to \"/-\" adds to the end of the array, even n levels down", () => { run_test([1, 2, [3, [4, 5]]], [{ "op": "add", "path": "/2/1/-", "value": { "foo": ["bar", "baz"] } }], undefined, [1, 2, [3, [4, 5, { "foo": ["bar", "baz"] }]]]); }); it("test remove with bad number should fail", () => { run_test({ "foo": 1, "baz": [{ "qux": "hello" }] }, [{ "op": "remove", "path": "/baz/1e0/qux" }], "remove op shouldn't remove from array with bad number", undefined); }); it("test remove on array", () => { run_test([1, 2, 3, 4], [{ "op": "remove", "path": "/0" }], undefined, [2, 3, 4]); }); it("test repeated removes", () => { run_test([1, 2, 3, 4], [{ "op": "remove", "path": "/1" }, { "op": "remove", "path": "/2" }], undefined, [1, 3]); }); it("test remove with bad index should fail", () => { run_test([1, 2, 3, 4], [{ "op": "remove", "path": "/1e0" }], "remove op shouldn't remove from array with bad number", undefined); }); it("test replace with bad number should fail", () => { run_test([""], [{ "op": "replace", "path": "/1e0", "value": false }], "replace op shouldn't replace in array with bad number", undefined); }); it("test copy with bad number should fail", () => { run_test({ "baz": [1, 2, 3], "bar": 1 }, [{ "op": "copy", "from": "/baz/1e0", "path": "/boo" }], "copy op shouldn't work with bad number", undefined); }); it("test move with bad number should fail", () => { run_test({ "foo": 1, "baz": [1, 2, 3, 4] }, [{ "op": "move", "from": "/baz/1e0", "path": "/foo" }], "move op shouldn't work with bad number", undefined); }); it("test add with bad number should fail", () => { run_test(["foo", "sil"], [{ "op": "add", "path": "/1e0", "value": "bar" }], "add op shouldn't add to array with bad number", undefined); }); it("missing 'path' parameter", () => { run_test({}, [{ "op": "add", "value": "bar" }], "missing 'path' parameter", undefined); }); it("'path' parameter with null value", () => { run_test({}, [{ "op": "add", "path": null, "value": "bar" }], "null is not valid value for 'path'", undefined); }); it("invalid JSON Pointer token", () => { run_test({}, [{ "op": "add", "path": "foo", "value": "bar" }], "JSON Pointer should start with a slash", undefined); }); it("missing 'value' parameter to add", () => { run_test([1], [{ "op": "add", "path": "/-" }], "missing 'value' parameter", undefined); }); it("missing 'value' parameter to replace", () => { run_test([1], [{ "op": "replace", "path": "/0" }], "missing 'value' parameter", undefined); }); it("missing 'value' parameter to test", () => { run_test([null], [{ "op": "test", "path": "/0" }], "missing 'value' parameter", undefined); }); it("missing value parameter to test - where undef is falsy", () => { run_test([false], [{ "op": "test", "path": "/0" }], "missing 'value' parameter", undefined); }); it("missing from parameter to copy", () => { run_test([1], [{ "op": "copy", "path": "/-" }], "missing 'from' parameter", undefined); }); it("missing from location to copy", () => { run_test({ "foo": 1 }, [{ "op": "copy", "from": "/bar", "path": "/foo" }], "missing 'from' location", undefined); }); it("missing from parameter to move", () => { run_test({ "foo": 1 }, [{ "op": "move", "path": "" }], "missing 'from' parameter", undefined); }); it("missing from location to move", () => { run_test({ "foo": 1 }, [{ "op": "move", "from": "/bar", "path": "/foo" }], "missing 'from' location", undefined); }); xit("duplicate ops", () => { run_test({ "foo": "bar" }, [{ "op": "move", "path": "/baz", "value": "qux", "from": "/foo" }], "patch has two 'op' members", undefined); }); it("unrecognized op should fail", () => { run_test({ "foo": 1 }, [{ "op": "spam", "path": "/foo", "value": 1 }], "Unrecognized op 'spam'", undefined); }); it("test with bad array number that has leading zeros", () => { run_test(["foo", "bar"], [{ "op": "test", "path": "/00", "value": "foo" }], "test op should reject the array value, it has leading zeros", undefined); }); it("test with bad array number that has leading zeros", () => { run_test(["foo", "bar"], [{ "op": "test", "path": "/01", "value": "bar" }], "test op should reject the array value, it has leading zeros", undefined); }); it("Removing nonexistent field", () => { run_test({ "foo": "bar" }, [{ "op": "remove", "path": "/baz" }], "removing a nonexistent field should fail", undefined); }); it("Removing deep nonexistent path", () => { run_test({ "foo": "bar" }, [{ "op": "remove", "path": "/missing1/missing2" }], "removing a nonexistent field should fail", undefined); }); it("Removing nonexistent index", () => { run_test(["foo", "bar"], [{ "op": "remove", "path": "/2" }], "removing a nonexistent index should fail", undefined); }); it("Patch with different capitalisation than doc", () => { run_test({ "foo": "bar" }, [{ "op": "add", "path": "/FOO", "value": "BAR" }], undefined, { "foo": "bar", "FOO": "BAR" }); }); }); describe("spec_tests.json - RFC6902 spec", () => { it("4.1. add with missing object", () => { run_test({ "q": { "bar": 2 } }, [{ "op": "add", "path": "/a/b", "value": 1 }], "path /a does not exist -- missing objects are not created recursively", undefined); }); it("A.1. Adding an Object Member", () => { run_test({ "foo": "bar" }, [{ "op": "add", "path": "/baz", "value": "qux" }], undefined, { "baz": "qux", "foo": "bar" }); }); it("A.2. Adding an Array Element", () => { run_test({ "foo": ["bar", "baz"] }, [{ "op": "add", "path": "/foo/1", "value": "qux" }], undefined, { "foo": ["bar", "qux", "baz"] }); }); it("A.3. Removing an Object Member", () => { run_test({ "baz": "qux", "foo": "bar" }, [{ "op": "remove", "path": "/baz" }], undefined, { "foo": "bar" }); }); it("A.4. Removing an Array Element", () => { run_test({ "foo": ["bar", "qux", "baz"] }, [{ "op": "remove", "path": "/foo/1" }], undefined, { "foo": ["bar", "baz"] }); }); it("A.5. Replacing a Value", () => { run_test({ "baz": "qux", "foo": "bar" }, [{ "op": "replace", "path": "/baz", "value": "boo" }], undefined, { "baz": "boo", "foo": "bar" }); }); it("A.6. Moving a Value", () => { run_test({ "foo": { "bar": "baz", "waldo": "fred" }, "qux": { "corge": "grault" } }, [{ "op": "move", "from": "/foo/waldo", "path": "/qux/thud" }], undefined, { "foo": { "bar": "baz" }, "qux": { "corge": "grault", "thud": "fred" } }); }); it("A.7. Moving an Array Element", () => { run_test({ "foo": ["all", "grass", "cows", "eat"] }, [{ "op": "move", "from": "/foo/1", "path": "/foo/3" }], undefined, { "foo": ["all", "cows", "eat", "grass"] }); }); it("A.8. Testing a Value: Success", () => { run_test({ "baz": "qux", "foo": ["a", 2, "c"] }, [{ "op": "test", "path": "/baz", "value": "qux" }, { "op": "test", "path": "/foo/1", "value": 2 }], undefined, { "baz": "qux", "foo": ["a", 2, "c"] }); }); it("A.9. Testing a Value: Error", () => { run_test({ "baz": "qux" }, [{ "op": "test", "path": "/baz", "value": "bar" }], "string not equivalent", undefined); }); it("A.10. Adding a nested Member Object", () => { run_test({ "foo": "bar" }, [{ "op": "add", "path": "/child", "value": { "grandchild": {} } }], undefined, { "foo": "bar", "child": { "grandchild": {} } }); }); it("A.11. Ignoring Unrecognized Elements", () => { run_test({ "foo": "bar" }, [{ "op": "add", "path": "/baz", "value": "qux", "xyz": 123 }], undefined, { "foo": "bar", "baz": "qux" }); }); it("A.12. Adding to a Non-existent Target", () => { run_test({ "foo": "bar" }, [{ "op": "add", "path": "/baz/bat", "value": "qux" }], "add to a non-existent target", undefined); }); xit("A.13 Invalid JSON Patch Document", () => { run_test({ "foo": "bar" }, [{ "op": "remove", "path": "/baz", "value": "qux" }], "operation has two 'op' members", undefined); }); it("A.14. ~ Escape Ordering", () => { run_test({ "/": 9, "~1": 10 }, [{ "op": "test", "path": "/~01", "value": 10 }], undefined, { "/": 9, "~1": 10 }); }); it("A.15. Comparing Strings and Numbers", () => { run_test({ "/": 9, "~1": 10 }, [{ "op": "test", "path": "/~01", "value": "10" }], "number is not equal to string", undefined); }); it("A.16. Adding an Array Value", () => { run_test({ "foo": ["bar"] }, [{ "op": "add", "path": "/foo/-", "value": ["abc", "def"] }], undefined, { "foo": ["bar", ["abc", "def"]] }); }); }); }); //# sourceMappingURL=conformance.spec.js.map