505 lines
12 KiB
JavaScript
505 lines
12 KiB
JavaScript
import { readFileSync } from 'fs'
|
|
import test from 'ava'
|
|
import { META, jsonToEson, esonToJson } from '../src/eson'
|
|
import { patchEson } from '../src/patchEson'
|
|
import { assertDeepEqualEson } from './utils/assertDeepEqualEson'
|
|
|
|
test('jsonpatch add', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 2}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'add', path: '/obj/b', value: {foo: 'bar'}}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
|
|
assertDeepEqualEson(t, patchedData, jsonToEson({
|
|
arr: [1,2,3],
|
|
obj: {a : 2, b: {foo: 'bar'}}
|
|
}))
|
|
t.deepEqual(revert, [
|
|
{op: 'remove', path: '/obj/b'}
|
|
])
|
|
})
|
|
|
|
test('jsonpatch add: insert in matrix', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 2}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'add', path: '/arr/1', value: 4}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
|
|
assertDeepEqualEson(t, patchedData, jsonToEson({
|
|
arr: [1,4,2,3],
|
|
obj: {a : 2}
|
|
}))
|
|
t.deepEqual(revert, [
|
|
{op: 'remove', path: '/arr/1'}
|
|
])
|
|
})
|
|
|
|
test('jsonpatch add: append to matrix', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 2}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'add', path: '/arr/-', value: 4}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
|
|
assertDeepEqualEson(t, patchedData, jsonToEson({
|
|
arr: [1,2,3,4],
|
|
obj: {a : 2}
|
|
}))
|
|
t.deepEqual(revert, [
|
|
{op: 'remove', path: '/arr/3'}
|
|
])
|
|
})
|
|
|
|
test('jsonpatch remove', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'remove', path: '/obj/a'},
|
|
{op: 'remove', path: '/arr/1'},
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
assertDeepEqualEson(t, patchedData, jsonToEson({
|
|
arr: [1,3],
|
|
obj: {}
|
|
}))
|
|
t.deepEqual(revert, [
|
|
{op: 'add', path: '/arr/1', value: 2, meta: {type: 'value'}},
|
|
{op: 'add', path: '/obj/a', value: 4, meta: {type: 'value', before: null}}
|
|
])
|
|
|
|
// test revert
|
|
const data2 = jsonToEson(patchedJson)
|
|
const result2 = patchEson(data2, revert)
|
|
const patchedData2 = result2.data
|
|
const revert2 = result2.revert
|
|
const patchedJson2 = esonToJson(patchedData2)
|
|
|
|
t.deepEqual(patchedJson2, json)
|
|
t.deepEqual(revert2, patch)
|
|
})
|
|
|
|
test('jsonpatch replace', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'replace', path: '/obj/a', value: 400},
|
|
{op: 'replace', path: '/arr/1', value: 200},
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
assertDeepEqualEson(t, patchedData, jsonToEson({
|
|
arr: [1,200,3],
|
|
obj: {a: 400}
|
|
}))
|
|
t.deepEqual(revert, [
|
|
{op: 'replace', path: '/arr/1', value: 2, meta: {type: 'value'}},
|
|
{op: 'replace', path: '/obj/a', value: 4, meta: {type: 'value'}}
|
|
])
|
|
|
|
// test revert
|
|
const data2 = jsonToEson(patchedJson)
|
|
const result2 = patchEson(data2, revert)
|
|
const patchedData2 = result2.data
|
|
const revert2 = result2.revert
|
|
const patchedJson2 = esonToJson(patchedData2)
|
|
|
|
t.deepEqual(patchedJson2, json)
|
|
t.deepEqual(revert2, [
|
|
{op: 'replace', path: '/obj/a', value: 400, meta: {type: 'value'}},
|
|
{op: 'replace', path: '/arr/1', value: 200, meta: {type: 'value'}}
|
|
])
|
|
})
|
|
|
|
test('jsonpatch replace (keep ids intact)', t => {
|
|
const json = { value: 42 }
|
|
const patch = [
|
|
{op: 'replace', path: '/value', value: 100}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const valueId = data.value[META].id
|
|
|
|
const patchedData = patchEson(data, patch).data
|
|
const patchedValueId = patchedData.value[META].id
|
|
|
|
t.is(patchedValueId, valueId)
|
|
})
|
|
|
|
test('jsonpatch copy', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'copy', from: '/obj', path: '/arr/2'},
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
t.deepEqual(patchedJson, {
|
|
arr: [1, 2, {a:4}, 3],
|
|
obj: {a: 4}
|
|
})
|
|
t.deepEqual(revert, [
|
|
{op: 'remove', path: '/arr/2'}
|
|
])
|
|
|
|
// test revert
|
|
const data2 = jsonToEson(patchedJson)
|
|
const result2 = patchEson(data2, revert)
|
|
const patchedData2 = result2.data
|
|
const revert2 = result2.revert
|
|
const patchedJson2 = esonToJson(patchedData2)
|
|
|
|
t.deepEqual(patchedJson2, json)
|
|
t.deepEqual(revert2, [
|
|
{op: 'add', path: '/arr/2', value: {a: 4}, meta: {type: 'Object'}}
|
|
])
|
|
})
|
|
|
|
test('jsonpatch copy (keeps the same ids)', t => {
|
|
const json = { foo: { bar: 42 } }
|
|
const patch = [
|
|
{op: 'copy', from: '/foo', path: '/copied'}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const fooId = data.foo[META].id
|
|
const barId = data.foo.bar[META].id
|
|
|
|
const patchedData = patchEson(data, patch).data
|
|
const patchedFooId = patchedData.foo[META].id
|
|
const patchedBarId = patchedData.foo.bar[META].id
|
|
const copiedId = patchedData.copied[META].id
|
|
const patchedCopiedBarId = patchedData.copied.bar[META].id
|
|
|
|
t.is(patchedFooId, fooId, 'same foo id')
|
|
t.is(patchedBarId, barId, 'same bar id')
|
|
|
|
t.not(copiedId, fooId, 'different id of property copied')
|
|
|
|
// The id's of the copied childs are the same, that's okish, they will not bite each other
|
|
t.is(patchedCopiedBarId, patchedBarId, 'same copied bar id')
|
|
})
|
|
|
|
test('jsonpatch move', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'move', from: '/obj', path: '/arr/2'},
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
t.is(result.error, null)
|
|
t.deepEqual(patchedJson, {
|
|
arr: [1, 2, {a:4}, 3]
|
|
})
|
|
t.deepEqual(revert, [
|
|
{op: 'move', from: '/arr/2', path: '/obj'}
|
|
])
|
|
|
|
// test revert
|
|
const data2 = jsonToEson(patchedJson)
|
|
const result2 = patchEson(data2, revert)
|
|
const patchedData2 = result2.data
|
|
const revert2 = result2.revert
|
|
const patchedJson2 = esonToJson(patchedData2)
|
|
|
|
t.deepEqual(patchedJson2, json)
|
|
t.deepEqual(revert2, patch)
|
|
})
|
|
|
|
test('jsonpatch move before', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4},
|
|
zzz: 'zzz'
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'move', from: '/obj', path: '/arr/2'},
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
t.is(result.error, null)
|
|
t.deepEqual(patchedJson, {
|
|
arr: [1, 2, {a:4}, 3],
|
|
zzz: 'zzz'
|
|
})
|
|
t.deepEqual(revert, [
|
|
{op: 'move', from: '/arr/2', path: '/obj', meta: {before: 'zzz'}}
|
|
])
|
|
|
|
// test revert
|
|
const data2 = jsonToEson(patchedJson)
|
|
const result2 = patchEson(data2, revert)
|
|
const patchedData2 = result2.data
|
|
const revert2 = result2.revert
|
|
const patchedJson2 = esonToJson(patchedData2)
|
|
|
|
t.deepEqual(patchedJson2, json)
|
|
t.deepEqual(revert2, patch)
|
|
})
|
|
|
|
test('jsonpatch move and replace', t => {
|
|
const json = { a: 2, b: 3 }
|
|
|
|
const patch = [
|
|
{op: 'move', from: '/a', path: '/b'},
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
// id of the replaced B must be kept intact
|
|
t.is(patchedData.b[META].id, data.b[META].id)
|
|
|
|
assertDeepEqualEson(t, patchedData, jsonToEson({b: 2}))
|
|
t.deepEqual(patchedJson, { b : 2 })
|
|
t.deepEqual(revert, [
|
|
{op:'move', from: '/b', path: '/a'},
|
|
{op:'add', path:'/b', value: 3, meta: {type: 'value', before: 'b'}}
|
|
])
|
|
|
|
// test revert
|
|
const data2 = jsonToEson(patchedJson)
|
|
const result2 = patchEson(data2, revert)
|
|
const patchedData2 = result2.data
|
|
const revert2 = result2.revert
|
|
const patchedJson2 = esonToJson(patchedData2)
|
|
|
|
t.deepEqual(patchedJson2, json)
|
|
t.deepEqual(revert2, [
|
|
{op: 'remove', path: '/b'},
|
|
{op: 'move', from: '/a', path: '/b'}
|
|
])
|
|
})
|
|
|
|
test('jsonpatch move and replace (nested)', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'move', from: '/obj', path: '/arr'},
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
t.deepEqual(patchedJson, {
|
|
arr: {a:4}
|
|
})
|
|
t.deepEqual(revert, [
|
|
{op:'move', from: '/arr', path: '/obj'},
|
|
{op:'add', path:'/arr', value: [1,2,3], meta: {type: 'Array'}}
|
|
])
|
|
|
|
// test revert
|
|
const data2 = jsonToEson(patchedJson)
|
|
const result2 = patchEson(data2, revert)
|
|
const patchedData2 = result2.data
|
|
const revert2 = result2.revert
|
|
const patchedJson2 = esonToJson(patchedData2)
|
|
|
|
t.deepEqual(patchedJson2, json)
|
|
t.deepEqual(revert2, [
|
|
{op: 'remove', path: '/arr'},
|
|
{op: 'move', from: '/obj', path: '/arr'}
|
|
])
|
|
})
|
|
|
|
test('jsonpatch move (keep id intact)', t => {
|
|
const json = { value: 42 }
|
|
const patch = [
|
|
{op: 'move', from: '/value', path: '/moved'}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const valueId = data.value[META].id
|
|
|
|
const patchedData = patchEson(data, patch).data
|
|
const patchedValueId = patchedData.moved[META].id
|
|
|
|
t.is(patchedValueId, valueId)
|
|
})
|
|
|
|
test('jsonpatch move and replace (keep ids intact)', t => {
|
|
const json = { a: 2, b: 3 }
|
|
const patch = [
|
|
{op: 'move', from: '/a', path: '/b'}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const bId = data.b[META].id
|
|
|
|
t.deepEqual(data[META].props, ['a', 'b'])
|
|
|
|
const patchedData = patchEson(data, patch).data
|
|
|
|
t.is(patchedData.b[META].id, bId)
|
|
t.deepEqual(patchedData[META].props, ['b'])
|
|
})
|
|
|
|
test('jsonpatch test (ok)', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'test', path: '/arr', value: [1,2,3]},
|
|
{op: 'add', path: '/added', value: 'ok'}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
t.deepEqual(patchedJson, {
|
|
arr: [1,2,3],
|
|
obj: {a : 4},
|
|
added: 'ok'
|
|
})
|
|
t.deepEqual(revert, [
|
|
{op: 'remove', path: '/added'}
|
|
])
|
|
|
|
})
|
|
|
|
test('jsonpatch test (fail: path not found)', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'test', path: '/arr/5', value: [1,2,3]},
|
|
{op: 'add', path: '/added', value: 'ok'}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
// patch shouldn't be applied
|
|
t.deepEqual(patchedJson, {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
})
|
|
t.deepEqual(revert, [])
|
|
t.is(result.error.toString(), 'Error: Test failed, path not found')
|
|
})
|
|
|
|
test('jsonpatch test (fail: value not equal)', t => {
|
|
const json = {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
}
|
|
|
|
const patch = [
|
|
{op: 'test', path: '/obj', value: {a:4, b: 6}},
|
|
{op: 'add', path: '/added', value: 'ok'}
|
|
]
|
|
|
|
const data = jsonToEson(json)
|
|
const result = patchEson(data, patch)
|
|
const patchedData = result.data
|
|
const revert = result.revert
|
|
const patchedJson = esonToJson(patchedData)
|
|
|
|
// patch shouldn't be applied
|
|
t.deepEqual(patchedJson, {
|
|
arr: [1,2,3],
|
|
obj: {a : 4}
|
|
})
|
|
t.deepEqual(revert, [])
|
|
t.is(result.error.toString(), 'Error: Test failed, value differs')
|
|
})
|
|
|
|
// helper function to print JSON in the console
|
|
function printJSON (json, message = null) {
|
|
if (message) {
|
|
console.log(message)
|
|
}
|
|
console.log(JSON.stringify(json, null, 2))
|
|
}
|
|
|
|
// helper function to load a JSON file
|
|
function loadJSON (filename) {
|
|
return JSON.parse(readFileSync(__dirname + '/' + filename, 'utf-8'))
|
|
}
|