diff --git a/src/jsoneditor/actions.js b/src/jsoneditor/actions.js index d8bbeef..6bb5b36 100644 --- a/src/jsoneditor/actions.js +++ b/src/jsoneditor/actions.js @@ -313,7 +313,7 @@ export function removeAll (paths) { /** * Create a JSONPatch to order the items of an array or the properties of an object in ascending - * or descending order + * or descending order. In case of ESON, this will maintain state of expanded items * @param {JSON} json * @param {Path} path * @param {'asc' | 'desc' | null} [order=null] If not provided, will toggle current ordering @@ -374,15 +374,13 @@ function sortWithComparator (items, comparator) { if (i !== firstIndex) { const item = orderedItems[firstIndex] - const beforeItem = orderedItems[i] orderedItems.splice(firstIndex, 1) orderedItems.unshift(item) moveActions.push({ item, fromIndex: firstIndex, - toIndex: i, - beforeItem + toIndex: i }) } } diff --git a/src/jsoneditor/actions.test.js b/src/jsoneditor/actions.test.js index 7deb4ec..74ad044 100644 --- a/src/jsoneditor/actions.test.js +++ b/src/jsoneditor/actions.test.js @@ -17,12 +17,42 @@ const assertEqualEson = createAssertEqualEson(expect) // TODO: test remove // TODO: test removeAll -it('sort root Array', () => { - const eson = syncEson([1,3,2]) +it('sort root Array (json)', () => { + const json = [1,3,2] + const sorted1 = immutableJSONPatch(json, sort(json, [])).json + const sorted2 = immutableJSONPatch(json, sort(json, [], 'asc')).json + const sorted3 = immutableJSONPatch(json, sort(json, [], 'desc')).json - assertEqualEson(immutableJSONPatch(eson, sort(eson, [])).json, syncEson([1,2,3])) - assertEqualEson(immutableJSONPatch(eson, sort(eson, [], 'asc')).json, syncEson([1,2,3])) - assertEqualEson(immutableJSONPatch(eson, sort(eson, [], 'desc')).json, syncEson([3,2,1])) + console.log(json) + console.log(sorted1) + + assertEqualEson(json, [1,3, 2]) // should be untouched + assertEqualEson(sorted1, [1,2,3]) + assertEqualEson(sorted2, [1,2,3]) + assertEqualEson(sorted3, [3,2,1]) +}) + +it('sort root Array (eson)', () => { + const eson = syncEson([1,3,2]) + const sorted1 = immutableJSONPatch(eson, sort(eson, [])).json + const sorted2 = immutableJSONPatch(eson, sort(eson, [], 'asc')).json + const sorted3 = immutableJSONPatch(eson, sort(eson, [], 'desc')).json + + assertEqualEson(sorted1, syncEson([1, 2, 3])) + assertEqualEson(sorted1[0], eson[0], false) + assertEqualEson(sorted1[1], eson[2], false) + assertEqualEson(sorted1[2], eson[1], false) + expect(sorted1).not.toBe(eson) + + assertEqualEson(sorted2[0], eson[0], false) + assertEqualEson(sorted2[1], eson[2], false) + assertEqualEson(sorted2[2], eson[1], false) + expect(sorted2).not.toBe(eson) + + assertEqualEson(sorted3[0], eson[1], false) + assertEqualEson(sorted3[1], eson[2], false) + assertEqualEson(sorted3[2], eson[0], false) + expect(sorted3).not.toBe(eson) }) it('sort nested Array', () => { diff --git a/src/jsoneditor/eson.js b/src/jsoneditor/eson.js index 80c66e8..ede3680 100644 --- a/src/jsoneditor/eson.js +++ b/src/jsoneditor/eson.js @@ -52,7 +52,6 @@ export function syncEson(json, eson) { if (changed) { updatedEson[ID] = sameType ? eson[ID] : createId() updatedEson[TYPE] = jsonType - updatedEson[VALUE] = json updatedEson[EXPANDED] = sameType ? eson[EXPANDED] : false return updatedEson @@ -83,7 +82,6 @@ export function syncEson(json, eson) { if (changed) { updatedEson[ID] = sameType ? eson[ID] : createId() updatedEson[TYPE] = jsonType - updatedEson[VALUE] = json updatedEson[EXPANDED] = sameType ? eson[EXPANDED] : false return updatedEson @@ -93,7 +91,7 @@ export function syncEson(json, eson) { } } else if (jsonType === 'value') { // json is a value - if (sameType && eson[VALUE] === json) { + if (sameType && eson && eson[VALUE] === json) { return eson } else { @@ -103,6 +101,7 @@ export function syncEson(json, eson) { updatedEson[TYPE] = jsonType updatedEson[VALUE] = json updatedEson[EXPANDED] = false + updatedEson.valueOf = () => json return updatedEson } @@ -182,7 +181,7 @@ export function applyErrors (eson, errors = []) { }, eson) // cleanup any old error messages - return cleanupMetaData(esonWithErrors, 'error', errorPaths) + return cleanupMetaData(esonWithErrors, ERROR, errorPaths) } /** diff --git a/src/jsoneditor/eson.test.js b/src/jsoneditor/eson.test.js index ffd52ff..a4410b0 100644 --- a/src/jsoneditor/eson.test.js +++ b/src/jsoneditor/eson.test.js @@ -32,14 +32,34 @@ test('syncEson', () => { const nodeState1 = syncEson(json1, undefined) - expect(nodeState1).toEqual({ - arr: [{}, {}, {}], - obj: {a: {}} - }) + expect(nodeState1[ID]).toBeDefined() + expect(nodeState1[TYPE]).toEqual('object') + expect(nodeState1[EXPANDED]).toEqual(false) + expect(nodeState1[VALUE]).toBeUndefined() + expect(nodeState1.arr[ID]).toBeDefined() + expect(nodeState1.arr[TYPE]).toEqual('array') + expect(nodeState1.arr[VALUE]).toBeUndefined() + expect(nodeState1.arr[EXPANDED]).toEqual(false) expect(nodeState1.arr[0][ID]).toBeDefined() expect(nodeState1.arr[0][TYPE]).toEqual('value') - expect(nodeState1.arr[TYPE]).toEqual('array') - expect(nodeState1[TYPE]).toEqual('object') + expect(nodeState1.arr[0][VALUE]).toEqual(1) + expect(nodeState1.arr[0][EXPANDED]).toEqual(false) + expect(nodeState1.arr[1][ID]).toBeDefined() + expect(nodeState1.arr[1][TYPE]).toEqual('value') + expect(nodeState1.arr[1][VALUE]).toEqual(2) + expect(nodeState1.arr[1][EXPANDED]).toEqual(false) + expect(nodeState1.arr[2][ID]).toBeDefined() + expect(nodeState1.arr[2][TYPE]).toEqual('value') + expect(nodeState1.arr[2][VALUE]).toEqual(3) + expect(nodeState1.arr[2][EXPANDED]).toEqual(false) + expect(nodeState1.obj[ID]).toBeDefined() + expect(nodeState1.obj[TYPE]).toEqual('object') + expect(nodeState1.obj[VALUE]).toBeUndefined() + expect(nodeState1.obj[EXPANDED]).toEqual(false) + expect(nodeState1.obj.a[ID]).toBeDefined() + expect(nodeState1.obj.a[TYPE]).toEqual('value') + expect(nodeState1.obj.a[VALUE]).toEqual(2) + expect(nodeState1.obj.a[EXPANDED]).toEqual(false) const json2 = { arr: [1, 2], @@ -47,11 +67,6 @@ test('syncEson', () => { } const nodeState2 = syncEson(json2, nodeState1) - expect(nodeState2).toEqual({ - arr: [{}, {}], - obj: {a: {}, b: {}} - }) - // ID's should be the same for unchanged contents expect(nodeState2[ID]).toEqual(nodeState1[ID]) expect(nodeState2.arr[ID]).toEqual(nodeState1.arr[ID]) @@ -145,7 +160,6 @@ test('expand a callback', () => { }) function callback (path) { - console.log('callback') return (path.length >= 1) ? true // expand : undefined // leave untouched @@ -188,9 +202,6 @@ test('add and remove errors', () => { expected = setIn(expected, ['obj', 'arr', '2', 'last', ERROR], jsonSchemaErrors[0]) expected = setIn(expected, ['nill', ERROR], jsonSchemaErrors[1]) - console.log(actual1) - console.log(expected) - assertEqualEson(actual1, expected) // re-applying the same errors should not change eson diff --git a/src/jsoneditor/utils/assertEqualEson.js b/src/jsoneditor/utils/assertEqualEson.js index 2c68fb4..45a1cd4 100644 --- a/src/jsoneditor/utils/assertEqualEson.js +++ b/src/jsoneditor/utils/assertEqualEson.js @@ -1,6 +1,5 @@ -import { ID, TYPE, VALUE } from '../eson' -import uniq from 'lodash/uniq' -import each from 'lodash/each' +import { ID } from '../eson' +import { deleteIn, transform } from './immutabilityHelpers' export function createAssertEqualEson(expect) { @@ -9,31 +8,23 @@ export function createAssertEqualEson(expect) { throw new Error('Argument "expected" is undefined') } - // regular deep equal - expect(actual).toEqual(expected) + if (ignoreIds) { + const actualWithoutIds = stripValueOf(stripIdSymbols(actual)) + const expectedWithoutIds = stripValueOf(stripIdSymbols(expected)) - assertEqualEsonKeys(actual, expected, ignoreIds) + expect(actualWithoutIds).toEqual(expectedWithoutIds) + } + else { + expect(actual).toEqual(expected) + } } - function assertEqualEsonKeys (actual, expected, ignoreIds = true) { - // collect all symbols - const symbols = uniq(Object.getOwnPropertySymbols(actual) - .concat(Object.getOwnPropertySymbols(expected))) + function stripIdSymbols (eson) { + return transform(eson, (value) => deleteIn(value, [ID])) + } - // test whether all meta data is the same - symbols - .filter(symbol => symbol !== ID || ignoreIds) - .forEach(symbol => expect(actual[symbol]).toEqual(expected[symbol])) - - if (actual[TYPE] === 'array') { - each(expected, (item, index) => assertEqualEsonKeys(actual[index], expected[index], ignoreIds)) - } - else if (actual[TYPE] === 'object') { - each(actual, (value, key) => assertEqualEsonKeys(actual[key], expected[key]), ignoreIds) - } - else { // actual[TYPE] === 'value' - expect(actual[VALUE]).toEqual(expected[VALUE]) - } + function stripValueOf (eson) { + return transform(eson, (value) => deleteIn(value, ['valueOf'])) } return assertEqualEson diff --git a/src/jsoneditor/utils/immutabilityHelpers.js b/src/jsoneditor/utils/immutabilityHelpers.js index 8247cf2..a1ec569 100644 --- a/src/jsoneditor/utils/immutabilityHelpers.js +++ b/src/jsoneditor/utils/immutabilityHelpers.js @@ -161,7 +161,7 @@ export function deleteIn (object, path) { else { const updatedObject = shallowCloneWithSymbols(object) - if (Array.isArray(updatedObject)) { + if (Array.isArray(updatedObject) && typeof key !== 'symbol') { updatedObject.splice(key, 1) } else {