Fixed `move`

This commit is contained in:
jos 2016-09-18 15:30:57 +02:00
parent c8b3bd2d7a
commit ad36723618
2 changed files with 55 additions and 38 deletions

View File

@ -131,7 +131,7 @@ export function patchData (data, patch) {
const result = add(updatedData, action.path, newValue, options) const result = add(updatedData, action.path, newValue, options)
updatedData = result.data updatedData = result.data
revert.unshift(result.revert) revert = result.revert.concat(revert)
break break
} }
@ -139,7 +139,7 @@ export function patchData (data, patch) {
case 'remove': { case 'remove': {
const result = remove(updatedData, action.path) const result = remove(updatedData, action.path)
updatedData = result.data updatedData = result.data
revert.unshift(result.revert) revert = result.revert.concat(revert)
break break
} }
@ -157,7 +157,7 @@ export function patchData (data, patch) {
const result = replace(updatedData, path, newValue) const result = replace(updatedData, path, newValue)
updatedData = result.data updatedData = result.data
revert.unshift(result.revert) revert = result.revert.concat(revert)
break break
} }
@ -165,7 +165,7 @@ export function patchData (data, patch) {
case 'copy': { case 'copy': {
const result = copy(updatedData, action.path, action.from, options) const result = copy(updatedData, action.path, action.from, options)
updatedData = result.data updatedData = result.data
revert.unshift(result.revert) revert = result.revert.concat(revert)
break break
} }
@ -206,23 +206,23 @@ export function patchData (data, patch) {
* @param {JSONData} data * @param {JSONData} data
* @param {Path} path * @param {Path} path
* @param {JSONData} value * @param {JSONData} value
* @return {{data: JSONData, revert: Object}} * @return {{data: JSONData, revert: JSONPatch}}
*/ */
export function replace (data, path, value) { export function replace (data, path, value) {
const dataPath = toDataPath(data, path) const dataPath = toDataPath(data, path)
const oldValue = dataToJson(getIn(data, dataPath)) const oldValue = getIn(data, dataPath)
return { return {
// FIXME: keep the expanded state where possible // FIXME: keep the expanded state where possible
data: setIn(data, dataPath, value), data: setIn(data, dataPath, value),
revert: { revert: [{
op: 'replace', op: 'replace',
path: compileJSONPointer(path), path: compileJSONPointer(path),
value: oldValue, value: dataToJson(oldValue),
jsoneditor: { jsoneditor: {
type: oldValue.type type: oldValue.type
} }
} }]
} }
} }
@ -230,7 +230,7 @@ export function replace (data, path, value) {
* Remove an item or property * Remove an item or property
* @param {JSONData} data * @param {JSONData} data
* @param {string} path * @param {string} path
* @return {{data: JSONData, revert: Object}} * @return {{data: JSONData, revert: JSONPatch}}
*/ */
export function remove (data, path) { export function remove (data, path) {
// console.log('remove', path) // console.log('remove', path)
@ -246,14 +246,14 @@ export function remove (data, path) {
return { return {
data: deleteIn(data, dataPath), data: deleteIn(data, dataPath),
revert: { revert: [{
op: 'add', op: 'add',
path, path,
value, value,
jsoneditor: { jsoneditor: {
type: dataValue.type type: dataValue.type
} }
} }]
} }
} }
else { // object.type === 'Object' else { // object.type === 'Object'
@ -263,7 +263,7 @@ export function remove (data, path) {
dataPath.pop() // remove the 'value' property, we want to remove the whole object property dataPath.pop() // remove the 'value' property, we want to remove the whole object property
return { return {
data: deleteIn(data, dataPath), data: deleteIn(data, dataPath),
revert: { revert: [{
op: 'add', op: 'add',
path, path,
value, value,
@ -271,7 +271,7 @@ export function remove (data, path) {
type: dataValue.type, type: dataValue.type,
before: findNextProp(parent, prop) before: findNextProp(parent, prop)
} }
} }]
} }
} }
} }
@ -281,7 +281,7 @@ export function remove (data, path) {
* @param {string} path * @param {string} path
* @param {JSONData} value * @param {JSONData} value
* @param {{before?: string}} [options] * @param {{before?: string}} [options]
* @return {{data: JSONData, revert: Object}} * @return {{data: JSONData, revert: JSONPatch}}
* @private * @private
*/ */
export function add (data, path, value, options) { export function add (data, path, value, options) {
@ -334,23 +334,23 @@ export function add (data, path, value, options) {
if (parent.type === 'Object' && oldValue !== undefined) { if (parent.type === 'Object' && oldValue !== undefined) {
return { return {
data: updatedData, data: updatedData,
revert: { revert: [{
op: 'replace', op: 'replace',
path: compileJSONPointer(resolvedPath), path: compileJSONPointer(resolvedPath),
value: dataToJson(oldValue), value: dataToJson(oldValue),
jsoneditor: { jsoneditor: {
type: oldValue.type type: oldValue.type
} }
} }]
} }
} }
else { else {
return { return {
data: updatedData, data: updatedData,
revert: { revert: [{
op: 'remove', op: 'remove',
path: compileJSONPointer(resolvedPath) path: compileJSONPointer(resolvedPath)
} }]
} }
} }
} }
@ -361,7 +361,7 @@ export function add (data, path, value, options) {
* @param {string} path * @param {string} path
* @param {string} from * @param {string} from
* @param {{before?: string}} [options] * @param {{before?: string}} [options]
* @return {{data: JSONData, revert: Object}} * @return {{data: JSONData, revert: JSONPatch}}
* @private * @private
*/ */
export function copy (data, path, from, options) { export function copy (data, path, from, options) {
@ -376,26 +376,35 @@ export function copy (data, path, from, options) {
* @param {string} path * @param {string} path
* @param {string} from * @param {string} from
* @param {{before?: string}} [options] * @param {{before?: string}} [options]
* @return {{data: JSONData, revert: Object}} * @return {{data: JSONData, revert: JSONPatch}}
* @private * @private
*/ */
export function move (data, path, from, options) { export function move (data, path, from, options) {
if (path !== from) { const dataValue = getIn(data, toDataPath(data, parseJSONPointer(from)))
const value = getIn(data, toDataPath(data, parseJSONPointer(from)))
const result1 = remove(data, from) const result1 = remove(data, from)
const result2 = add(result1.data, path, value, options) const result2 = add(result1.data, path, dataValue, options)
if (result2.revert[0].op === 'replace') {
return { return {
data: result2.data, data: result2.data,
revert: result1.revert.concat(result2.revert) revert: [
{ op: 'move', from: path, path: from },
{
op: 'add',
path,
value: result2.revert[0].value,
jsoneditor: result2.revert[0].jsoneditor
}
]
} }
} }
else { else { // result2.revert[0].op === 'remove'
// nothing to do
return { return {
data, data: result2.data,
revert: [] revert: [
{op: 'move', from: path, path: from}
]
} }
} }
} }

View File

@ -365,8 +365,8 @@ test('jsonpatch remove', t => {
obj: {} obj: {}
}) })
t.deepEqual(revert, [ t.deepEqual(revert, [
{op: 'add', path: '/arr/1', value: 2}, {op: 'add', path: '/arr/1', value: 2, jsoneditor: {type: 'value'}},
{op: 'add', path: '/obj/a', value: 4} {op: 'add', path: '/obj/a', value: 4, jsoneditor: {type: 'value', before: null}}
]) ])
// test revert // test revert
@ -402,8 +402,8 @@ test('jsonpatch replace', t => {
obj: {a: 400} obj: {a: 400}
}) })
t.deepEqual(revert, [ t.deepEqual(revert, [
{op: 'replace', path: '/arr/1', value: 2}, {op: 'replace', path: '/arr/1', value: 2, jsoneditor: {type: 'value'}},
{op: 'replace', path: '/obj/a', value: 4} {op: 'replace', path: '/obj/a', value: 4, jsoneditor: {type: 'value'}}
]) ])
// test revert // test revert
@ -414,7 +414,10 @@ test('jsonpatch replace', t => {
const patchedJson2 = dataToJson(patchedData2) const patchedJson2 = dataToJson(patchedData2)
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, patch) t.deepEqual(revert2, [
{op: 'replace', path: '/obj/a', value: 400, jsoneditor: {type: 'value'}},
{op: 'replace', path: '/arr/1', value: 200, jsoneditor: {type: 'value'}}
])
}) })
test('jsonpatch copy', t => { test('jsonpatch copy', t => {
@ -450,7 +453,7 @@ test('jsonpatch copy', t => {
t.deepEqual(patchedJson2, json) t.deepEqual(patchedJson2, json)
t.deepEqual(revert2, [ t.deepEqual(revert2, [
{op: 'add', path: '/arr/2', value: {a: 4}} {op: 'add', path: '/arr/2', value: {a: 4}, jsoneditor: {type: 'Object'}}
]) ])
}) })
@ -470,6 +473,7 @@ test('jsonpatch move', t => {
const revert = result.revert const revert = result.revert
const patchedJson = dataToJson(patchedData) const patchedJson = dataToJson(patchedData)
t.is(result.error, null)
t.deepEqual(patchedJson, { t.deepEqual(patchedJson, {
arr: [1, 2, {a:4}, 3] arr: [1, 2, {a:4}, 3]
}) })
@ -508,8 +512,8 @@ test('jsonpatch move and replace', t => {
arr: {a:4} arr: {a:4}
}) })
t.deepEqual(revert, [ t.deepEqual(revert, [
{op: 'move', from: '/arr', path: '/obj'}, {op:'move', from: '/arr', path: '/obj'},
{op: 'add', path: '/arr', value: [1,2,3]} {op:'add', path:'/arr', value: [1,2,3], jsoneditor: {type: 'Array'}}
]) ])
// test revert // test revert
@ -524,6 +528,8 @@ test('jsonpatch move and replace', t => {
{op: 'remove', path: '/arr'}, {op: 'remove', path: '/arr'},
{op: 'move', from: '/obj', path: '/arr'} {op: 'move', from: '/obj', path: '/arr'}
]) ])
// TODO: would be nice when dataPatch could simplify revert2: see that the 'remove' action is redundant
}) })
test('jsonpatch test (ok)', t => { test('jsonpatch test (ok)', t => {
@ -605,3 +611,5 @@ test('jsonpatch test (fail: value not equal)', t => {
t.deepEqual(revert, []) t.deepEqual(revert, [])
t.is(result.error.toString(), 'Error: Test failed, value differs') t.is(result.error.toString(), 'Error: Test failed, value differs')
}) })
// TODO: test `jsoneditor.before` JSONPatch property