jsoneditor/test/jsonData.test.js

1243 lines
29 KiB
JavaScript
Raw Normal View History

import test from 'ava';
2016-09-09 17:01:06 +08:00
import {
jsonToData, dataToJson, patchData, pathExists, transform, traverse,
2016-11-12 21:10:10 +08:00
parseJSONPointer, compileJSONPointer,
expand, addErrors, search, addSearchResults, nextSearchResult, previousSearchResult
2016-09-09 17:01:06 +08:00
} from '../src/jsonData'
const JSON_EXAMPLE = {
obj: {
arr: [1,2, {first:3,last:4}]
},
str: 'hello world',
nill: null,
bool: false
}
const JSON_DATA_EXAMPLE = {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'obj',
value: {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'arr',
value: {
type: 'Array',
expanded: true,
items: [
{
id: '[ID]',
value: {
type: 'value',
value: 1
}
},
{
id: '[ID]',
value: {
type: 'value',
value: 2
}
},
{
id: '[ID]',
value: {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'first',
value: {
type: 'value',
value: 3
}
},
{
id: '[ID]',
name: 'last',
value: {
type: 'value',
value: 4
}
}
]
}
}
]
}
}
]
}
},
{
id: '[ID]',
name: 'str',
value: {
type: 'value',
value: 'hello world'
}
},
{
id: '[ID]',
name: 'nill',
value: {
type: 'value',
value: null
}
},
{
id: '[ID]',
name: 'bool',
value: {
type: 'value',
value: false
}
}
]
}
// TODO: instead of all slightly different copies of JSON_DATA_EXAMPLE, built them up via setIn, updateIn based on JSON_DATA_EXAMPLE
const JSON_DATA_EXAMPLE_COLLAPSED_1 = {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'obj',
value: {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'arr',
value: {
type: 'Array',
expanded: true,
items: [
{
id: '[ID]',
value: {
type: 'value',
value: 1
}
},
{
id: '[ID]',
value: {
type: 'value',
value: 2
}
},
{
id: '[ID]',
value: {
type: 'Object',
expanded: false,
props: [
{
id: '[ID]',
name: 'first',
value: {
type: 'value',
value: 3
}
},
{
id: '[ID]',
name: 'last',
value: {
type: 'value',
value: 4
}
}
]
}
}
]
}
}
]
}
},
{
id: '[ID]',
name: 'str',
value: {
type: 'value',
value: 'hello world'
}
},
{
id: '[ID]',
name: 'nill',
value: {
type: 'value',
value: null
}
},
{
id: '[ID]',
name: 'bool',
value: {
type: 'value',
value: false
}
}
]
}
const JSON_DATA_EXAMPLE_COLLAPSED_2 = {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'obj',
value: {
type: 'Object',
expanded: false,
props: [
{
id: '[ID]',
name: 'arr',
value: {
type: 'Array',
expanded: false,
items: [
{
id: '[ID]',
value: {
type: 'value',
value: 1
}
},
{
id: '[ID]',
value: {
type: 'value',
value: 2
}
},
{
id: '[ID]',
value: {
type: 'Object',
expanded: false,
props: [
{
id: '[ID]',
name: 'first',
value: {
type: 'value',
value: 3
}
},
{
id: '[ID]',
name: 'last',
value: {
type: 'value',
value: 4
}
}
]
}
}
]
}
}
]
}
},
{
id: '[ID]',
name: 'str',
value: {
type: 'value',
value: 'hello world'
}
},
{
id: '[ID]',
name: 'nill',
value: {
type: 'value',
value: null
}
},
{
id: '[ID]',
name: 'bool',
value: {
type: 'value',
value: false
}
}
]
}
// after search for 'L' (case insensitive)
const JSON_DATA_EXAMPLE_SEARCH_L = {
2016-11-20 04:21:09 +08:00
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'obj',
value: {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'arr',
value: {
type: 'Array',
expanded: true,
items: [
{
id: '[ID]',
value: {
type: 'value',
value: 1
}
2016-11-20 04:21:09 +08:00
},
{
id: '[ID]',
value: {
type: 'value',
value: 2
}
2016-11-20 04:21:09 +08:00
},
{
id: '[ID]',
value: {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'first',
value: {
type: 'value',
value: 3
}
2016-12-30 20:45:43 +08:00
},
{
id: '[ID]',
name: 'last',
value: {
type: 'value',
value: 4
},
searchResult: 'active'
}
]
}
}
2016-11-20 04:21:09 +08:00
]
}
}
]
}
},
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'str',
value: {
type: 'value',
value: 'hello world',
2016-12-30 20:45:43 +08:00
searchResult: 'normal'
2016-11-20 04:21:09 +08:00
}
},
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'nill',
value: {
type: 'value',
value: null,
2016-12-30 20:45:43 +08:00
searchResult: 'normal'
},
searchResult: 'normal'
2016-11-20 04:21:09 +08:00
},
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'bool',
value: {
type: 'value',
value: false,
2016-12-30 20:45:43 +08:00
searchResult: 'normal'
},
searchResult: 'normal'
2016-11-20 04:21:09 +08:00
}
]
}
const JSON_DATA_SMALL = {
type: 'Object',
props: [
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'obj',
value: {
type: 'Object',
props: [
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'a',
value: {
type: 'value',
value: 2
}
}
]
}
},
{
id: '[ID]',
2016-11-20 04:21:09 +08:00
name: 'arr',
value: {
type: 'Array',
items: [
{
id: '[ID]',
value: {
type: 'value',
value: 3
}
2016-11-20 04:21:09 +08:00
}
]
}
}
]
}
2016-11-12 21:10:10 +08:00
const JSON_SCHEMA_ERRORS = [
{dataPath: '/obj/arr/2/last', message: 'String expected'},
2016-11-12 21:10:10 +08:00
{dataPath: '/nill', message: 'Null expected'}
]
const JSON_DATA_EXAMPLE_ERRORS = {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
2016-11-12 21:10:10 +08:00
name: 'obj',
value: {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
2016-11-12 21:10:10 +08:00
name: 'arr',
value: {
type: 'Array',
expanded: true,
items: [
{
id: '[ID]',
value: {
type: 'value',
value: 1
}
2016-11-12 21:10:10 +08:00
},
{
id: '[ID]',
value: {
type: 'value',
value: 2
}
2016-11-12 21:10:10 +08:00
},
{
id: '[ID]',
value: {
type: 'Object',
expanded: true,
props: [
{
id: '[ID]',
name: 'first',
value: {
type: 'value',
value: 3
}
},
{
id: '[ID]',
name: 'last',
value: {
type: 'value',
value: 4,
error: JSON_SCHEMA_ERRORS[0]
}
2016-11-12 21:10:10 +08:00
}
]
}
}
2016-11-12 21:10:10 +08:00
]
}
}
]
}
},
{
id: '[ID]',
2016-11-12 21:10:10 +08:00
name: 'str',
value: {
type: 'value',
value: 'hello world'
}
},
{
id: '[ID]',
2016-11-12 21:10:10 +08:00
name: 'nill',
value: {
type: 'value',
value: null,
error: JSON_SCHEMA_ERRORS[1]
}
},
{
id: '[ID]',
2016-11-12 21:10:10 +08:00
name: 'bool',
value: {
type: 'value',
value: false
}
}
]
}
test('jsonToData', t => {
function expand (path) {
return true
}
const jsonData = jsonToData(JSON_EXAMPLE, expand, [])
replaceIds(jsonData)
t.deepEqual(jsonData, JSON_DATA_EXAMPLE)
})
test('dataToJson', t => {
t.deepEqual(dataToJson(JSON_DATA_EXAMPLE), JSON_EXAMPLE)
})
test('expand a single path', t => {
const collapsed = expand(JSON_DATA_EXAMPLE, ['obj', 'arr', 2], false)
t.deepEqual(collapsed, JSON_DATA_EXAMPLE_COLLAPSED_1)
})
test('expand a callback', t => {
function callback (path) {
return path.length >= 1
}
const expanded = false
const collapsed = expand(JSON_DATA_EXAMPLE, callback, expanded)
t.deepEqual(collapsed, JSON_DATA_EXAMPLE_COLLAPSED_2)
})
test('expand a callback should not change the object when nothing happens', t => {
function callback (path) {
return false
}
const expanded = false
const collapsed = expand(JSON_DATA_EXAMPLE, callback, expanded)
t.is(collapsed, JSON_DATA_EXAMPLE)
})
2016-09-09 17:01:06 +08:00
test('pathExists', t => {
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'arr', 2, 'first']), true)
2016-09-09 17:01:06 +08:00
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'foo']), false)
t.is(pathExists(JSON_DATA_EXAMPLE, ['obj', 'foo', 'bar']), false)
t.is(pathExists(JSON_DATA_EXAMPLE, []), true)
})
test('parseJSONPointer', t => {
t.deepEqual(parseJSONPointer('/obj/a'), ['obj', 'a'])
t.deepEqual(parseJSONPointer('/arr/-'), ['arr', '-'])
t.deepEqual(parseJSONPointer('/foo/~1~0 ~0~1'), ['foo', '/~ ~/'])
t.deepEqual(parseJSONPointer('/obj'), ['obj'])
2016-10-28 17:04:06 +08:00
t.deepEqual(parseJSONPointer('/'), [''])
t.deepEqual(parseJSONPointer(''), [])
2016-09-09 17:01:06 +08:00
})
test('compileJSONPointer', t => {
t.deepEqual(compileJSONPointer(['foo', 'bar']), '/foo/bar')
t.deepEqual(compileJSONPointer(['foo', '/~ ~/']), '/foo/~1~0 ~0~1')
2016-10-28 17:04:06 +08:00
t.deepEqual(compileJSONPointer(['']), '/')
t.deepEqual(compileJSONPointer([]), '')
2016-09-09 17:01:06 +08:00
})
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 = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
t.deepEqual(patchedJson, {
arr: [1,2,3],
obj: {a : 2, b: {foo: 'bar'}}
})
t.deepEqual(revert, [
{op: 'remove', path: '/obj/b'}
])
})
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 = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
t.deepEqual(patchedJson, {
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 = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
t.deepEqual(patchedJson, {
arr: [1,3],
obj: {}
})
t.deepEqual(revert, [
2016-09-18 21:30:57 +08:00
{op: 'add', path: '/arr/1', value: 2, jsoneditor: {type: 'value'}},
{op: 'add', path: '/obj/a', value: 4, jsoneditor: {type: 'value', before: null}}
2016-09-09 17:01:06 +08:00
])
// test revert
const data2 = jsonToData(patchedJson)
2016-09-09 17:01:06 +08:00
const result2 = patchData(data2, revert)
const patchedData2 = result2.data
const revert2 = result2.revert
const patchedJson2 = dataToJson(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 = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
t.deepEqual(patchedJson, {
arr: [1,200,3],
obj: {a: 400}
})
t.deepEqual(revert, [
2016-09-18 21:30:57 +08:00
{op: 'replace', path: '/arr/1', value: 2, jsoneditor: {type: 'value'}},
{op: 'replace', path: '/obj/a', value: 4, jsoneditor: {type: 'value'}}
2016-09-09 17:01:06 +08:00
])
// test revert
const data2 = jsonToData(patchedJson)
2016-09-09 17:01:06 +08:00
const result2 = patchData(data2, revert)
const patchedData2 = result2.data
const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2)
t.deepEqual(patchedJson2, json)
2016-09-18 21:30:57 +08:00
t.deepEqual(revert2, [
{op: 'replace', path: '/obj/a', value: 400, jsoneditor: {type: 'value'}},
{op: 'replace', path: '/arr/1', value: 200, jsoneditor: {type: 'value'}}
])
2016-09-09 17:01:06 +08:00
})
test('jsonpatch replace (keep ids intact)', t => {
const json = { value: 42 }
const patch = [
{op: 'replace', path: '/value', value: 100}
]
const data = jsonToData(json)
const valueId = data.props[0].id
const patchedData = patchData(data, patch).data
const patchedValueId = patchedData.props[0].id
t.is(patchedValueId, valueId)
})
2016-09-09 17:01:06 +08:00
test('jsonpatch copy', t => {
const json = {
arr: [1,2,3],
obj: {a : 4}
}
const patch = [
{op: 'copy', from: '/obj', path: '/arr/2'},
]
const data = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
2016-09-09 17:01:06 +08:00
t.deepEqual(patchedJson, {
arr: [1, 2, {a:4}, 3],
obj: {a: 4}
})
t.deepEqual(revert, [
{op: 'remove', path: '/arr/2'}
])
2016-09-09 17:01:06 +08:00
// test revert
const data2 = jsonToData(patchedJson)
2016-09-09 17:01:06 +08:00
const result2 = patchData(data2, revert)
const patchedData2 = result2.data
const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2)
t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [
2016-09-18 21:30:57 +08:00
{op: 'add', path: '/arr/2', value: {a: 4}, jsoneditor: {type: 'Object'}}
2016-09-09 17:01:06 +08:00
])
})
test('jsonpatch copy (keeps the same ids)', t => {
const json = { foo: { bar: 42 } }
const patch = [
{op: 'copy', from: '/foo', path: '/copied'}
]
const data = jsonToData(json)
const fooId = data.props[0].id
const barId = data.props[0].value.props[0].id
const patchedData = patchData(data, patch).data
const patchedFooId = patchedData.props[0].id
const patchedBarId = patchedData.props[0].value.props[0].id
const copiedId = patchedData.props[1].id
const patchedCopiedBarId = patchedData.props[1].value.props[0].id
t.is(patchedData.props[0].name, 'foo')
t.is(patchedData.props[1].name, 'copied')
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
// FIXME: better solution for id's either always unique, or unique per object/array
t.is(patchedCopiedBarId, patchedBarId, 'same copied bar id')
})
2016-09-09 17:01:06 +08:00
test('jsonpatch move', t => {
const json = {
arr: [1,2,3],
obj: {a : 4}
}
const patch = [
{op: 'move', from: '/obj', path: '/arr/2'},
]
const data = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
2016-09-18 21:30:57 +08:00
t.is(result.error, null)
2016-09-09 17:01:06 +08:00
t.deepEqual(patchedJson, {
arr: [1, 2, {a:4}, 3]
})
t.deepEqual(revert, [
{op: 'move', from: '/arr/2', path: '/obj'}
])
// test revert
const data2 = jsonToData(patchedJson)
2016-09-09 17:01:06 +08:00
const result2 = patchData(data2, revert)
const patchedData2 = result2.data
const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2)
t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, patch)
})
2016-09-23 17:15:56 +08:00
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 = jsonToData(json)
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(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', jsoneditor: {before: 'zzz'}}
])
// test revert
const data2 = jsonToData(patchedJson)
const result2 = patchData(data2, revert)
const patchedData2 = result2.data
const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2)
t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, patch)
})
2016-09-09 17:01:06 +08:00
test('jsonpatch move and replace', t => {
const json = { a: 2, b: 3 }
const patch = [
{op: 'move', from: '/a', path: '/b'},
]
const data = jsonToData(json)
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
// id of the replaced B must be kept intact
t.is(patchedData.props[0].id, data.props[1].id)
replaceIds(patchedData)
t.deepEqual(patchedData, {
"type": "Object",
"expanded": true,
"props": [
{
"id": "[ID]",
"name": "b",
"value": {
"type": "value",
"value": 2
}
}
]
})
t.deepEqual(patchedJson, { b : 2 })
t.deepEqual(revert, [
{op:'move', from: '/b', path: '/a'},
{op:'add', path:'/b', value: 3, jsoneditor: {type: 'value', before: 'b'}}
])
// test revert
const data2 = jsonToData(patchedJson)
const result2 = patchData(data2, revert)
const patchedData2 = result2.data
const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2)
t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [
{op: 'move', from: '/a', path: '/b'}
])
})
test('jsonpatch move and replace (nested)', t => {
2016-09-09 17:01:06 +08:00
const json = {
arr: [1,2,3],
obj: {a : 4}
}
const patch = [
{op: 'move', from: '/obj', path: '/arr'},
]
const data = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(patchedData)
t.deepEqual(patchedJson, {
arr: {a:4}
})
t.deepEqual(revert, [
2016-09-18 21:30:57 +08:00
{op:'move', from: '/arr', path: '/obj'},
{op:'add', path:'/arr', value: [1,2,3], jsoneditor: {type: 'Array'}}
2016-09-09 17:01:06 +08:00
])
// test revert
const data2 = jsonToData(patchedJson)
2016-09-09 17:01:06 +08:00
const result2 = patchData(data2, revert)
const patchedData2 = result2.data
const revert2 = result2.revert
const patchedJson2 = dataToJson(patchedData2)
t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [
{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 = jsonToData(json)
const valueId = data.props[0].id
const patchedData = patchData(data, patch).data
const patchedValueId = patchedData.props[0].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 = jsonToData(json)
const bId = data.props[1].id
t.is(data.props[0].name, 'a')
t.is(data.props[1].name, 'b')
const patchedData = patchData(data, patch).data
t.is(patchedData.props[0].name, 'b')
t.is(patchedData.props[0].id, bId)
})
2016-09-09 17:01:06 +08:00
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 = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(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 = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(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 = jsonToData(json)
2016-09-09 17:01:06 +08:00
const result = patchData(data, patch)
const patchedData = result.data
const revert = result.revert
const patchedJson = dataToJson(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')
})
2016-11-12 21:10:10 +08:00
test('add and remove errors', t => {
const dataWithErrors = addErrors(JSON_DATA_EXAMPLE, JSON_SCHEMA_ERRORS)
t.deepEqual(dataWithErrors, JSON_DATA_EXAMPLE_ERRORS)
2016-11-20 03:44:58 +08:00
})
test('transform', t => {
// {obj: {a: 2}, arr: [3]}
2016-11-20 03:44:58 +08:00
let log = []
2016-11-20 04:21:09 +08:00
const transformed = transform(JSON_DATA_SMALL, function (value, path, root) {
t.is(root, JSON_DATA_SMALL)
2016-11-20 03:44:58 +08:00
log.push([value, path, root])
if (path.length === 2 && path[0] === 'obj' && path[1] === 'a') {
// change the value
return { type: 'value', value: 42 }
}
// leave the value unchanged
return value
})
// console.log('transformed', JSON.stringify(transformed, null, 2))
const EXPECTED_LOG = [
2016-11-20 04:21:09 +08:00
[JSON_DATA_SMALL, [], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[0].value, ['obj'], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[0].value.props[0].value, ['obj', 'a'], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[1].value, ['arr'], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[1].value.items[0].value, ['arr', '0'], JSON_DATA_SMALL],
2016-11-20 03:44:58 +08:00
]
log.forEach((row, index) => {
t.deepEqual(log[index], EXPECTED_LOG[index], 'should have equal log at index ' + index )
})
2016-11-20 03:44:58 +08:00
t.deepEqual(log, EXPECTED_LOG)
t.not(transformed, JSON_DATA_SMALL)
t.not(transformed.props[0].value, JSON_DATA_SMALL.props[0].value)
t.not(transformed.props[0].value.props[0].value, JSON_DATA_SMALL.props[0].value.props[0].value)
t.is(transformed.props[1].value, JSON_DATA_SMALL.props[1].value)
t.is(transformed.props[1].value.items[0].value, JSON_DATA_SMALL.props[1].value.items[0].value)
2016-11-20 04:21:09 +08:00
})
test('traverse', t => {
// {obj: {a: 2}, arr: [3]}
let log = []
const returnValue = traverse(JSON_DATA_SMALL, function (value, path, root) {
t.is(root, JSON_DATA_SMALL)
log.push([value, path, root])
})
t.is(returnValue, undefined)
const EXPECTED_LOG = [
[JSON_DATA_SMALL, [], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[0].value, ['obj'], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[0].value.props[0].value, ['obj', 'a'], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[1].value, ['arr'], JSON_DATA_SMALL],
[JSON_DATA_SMALL.props[1].value.items[0].value, ['arr', '0'], JSON_DATA_SMALL],
]
log.forEach((row, index) => {
t.deepEqual(log[index], EXPECTED_LOG[index], 'should have equal log at index ' + index )
})
t.deepEqual(log, EXPECTED_LOG)
})
2016-11-20 04:21:09 +08:00
test('search', t => {
const searchResults = search(JSON_DATA_EXAMPLE, 'L')
// printJSON(searchResults)
t.deepEqual(searchResults, [
2017-01-05 22:15:53 +08:00
{path: ['obj', 'arr', '2', 'last'], type: 'property'},
{path: ['str'], type: 'value'},
{path: ['nill'], type: 'property'},
{path: ['nill'], type: 'value'},
{path: ['bool'], type: 'property'},
{path: ['bool'], type: 'value'}
])
const activeSearchResult = searchResults[0]
const updatedData = addSearchResults(JSON_DATA_EXAMPLE, searchResults, activeSearchResult)
// printJSON(updatedData)
2016-11-12 21:10:10 +08:00
t.deepEqual(updatedData, JSON_DATA_EXAMPLE_SEARCH_L)
2016-11-12 21:10:10 +08:00
})
test('nextSearchResult', t => {
const searchResults = [
2017-01-05 22:15:53 +08:00
{path: ['obj', 'arr', '2', 'last'], type: 'property'},
{path: ['str'], type: 'value'},
{path: ['nill'], type: 'property'},
{path: ['nill'], type: 'value'},
{path: ['bool'], type: 'property'},
{path: ['bool'], type: 'value'}
]
t.deepEqual(nextSearchResult(searchResults,
2017-01-05 22:15:53 +08:00
{path: ['nill'], type: 'property'}),
{path: ['nill'], type: 'value'})
// wrap around
t.deepEqual(nextSearchResult(searchResults,
2017-01-05 22:15:53 +08:00
{path: ['bool'], type: 'value'}),
{path: ['obj', 'arr', '2', 'last'], type: 'property'})
// return first when current is not found
t.deepEqual(nextSearchResult(searchResults,
2017-01-05 22:15:53 +08:00
{path: ['non', 'existing'], type: 'value'}),
{path: ['obj', 'arr', '2', 'last'], type: 'property'})
// return null when searchResults are empty
2017-01-05 22:15:53 +08:00
t.deepEqual(nextSearchResult([], {path: ['non', 'existing'], type: 'value'}), null)
})
test('previousSearchResult', t => {
const searchResults = [
2017-01-05 22:15:53 +08:00
{path: ['obj', 'arr', '2', 'last'], type: 'property'},
{path: ['str'], type: 'value'},
{path: ['nill'], type: 'property'},
{path: ['nill'], type: 'value'},
{path: ['bool'], type: 'property'},
{path: ['bool'], type: 'value'}
]
t.deepEqual(previousSearchResult(searchResults,
2017-01-05 22:15:53 +08:00
{path: ['nill'], type: 'property'}),
{path: ['str'], type: 'value'})
// wrap around
t.deepEqual(previousSearchResult(searchResults,
2017-01-05 22:15:53 +08:00
{path: ['obj', 'arr', '2', 'last'], type: 'property'}),
{path: ['bool'], type: 'value'})
// return first when current is not found
t.deepEqual(previousSearchResult(searchResults,
2017-01-05 22:15:53 +08:00
{path: ['non', 'existing'], type: 'value'}),
{path: ['obj', 'arr', '2', 'last'], type: 'property'})
// return null when searchResults are empty
2017-01-05 22:15:53 +08:00
t.deepEqual(previousSearchResult([], {path: ['non', 'existing'], type: 'value'}), null)
})
// helper function to replace all id properties with a constant value
function replaceIds (data, value = '[ID]') {
if (data.type === 'Object') {
data.props.forEach(prop => {
prop.id = value
replaceIds(prop.value, value)
})
}
if (data.type === 'Array') {
data.items.forEach(item => {
item.id = value
replaceIds(item.value, value)
})
}
}
// 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))
}