UNPKG

crud-object-diff

Version:

Helper utilities to compare objects or arrays for obtaining created, updated, & deleted values.

405 lines (372 loc) 15.9 kB
const { compareObjectVals, compareArrayVals, isEqualObject, isEqualArray } = require('./dist/index.js'); const originalArrayOfObjects = [ {'commonKey': 1, 'anotherkey': 'test'}, {'commonKey': 2} ]; const newArrayOfObjects = [ {'commonKey': 2, 'newkey': 'test'}, {'commonKey': 7} ]; describe('CompareObjectVals tests', () => { test('basic compareObjectVals functionality', () => { const { createdVals, updatedVals, deletedVals } = compareObjectVals( [ originalArrayOfObjects, newArrayOfObjects ]); expect(deletedVals).toStrictEqual([{'commonKey': 1, 'anotherkey': 'test'}]); expect(updatedVals).toStrictEqual([{'commonKey': 2, 'newkey': 'test'}]); expect(createdVals).toStrictEqual([{'commonKey': 7}]); }); test('compareObjectVals functionality w/ nested objects', () => { const orgOb1 = [ {'test': 11, 'key2': 22}, {'test': 23, 1: [1,3]}, {'test': [{'test33': 22}, {1: 22}]} ]; const newOb1 = [ {'test': 11, 'key2': 33}, {'test': 22}, {'test': 23, 1: [1,8,3]}]; const { createdVals, updatedVals, deletedVals } = compareObjectVals([orgOb1, newOb1]); expect(deletedVals).toStrictEqual([{'test': [{'test33': 22}, {1: 22}]}]); expect(updatedVals).toStrictEqual([{'test': 11, 'key2': 33}, {'test': 23, 1: [1,8,3]}]); expect(createdVals).toStrictEqual([{'test': 22}]); }); test('compareObjectVals functionality w/ undefined value given', () => { const originalArrayOfObjects = [{ one: 1, two: 2 }, { test: undefined }]; const newArrayOfObjects = [{ one: 1, two: null }, { one: 22, five: 5 }] const relatedObjectKey = 'one'; const { createdVals, updatedVals, deletedVals } = compareObjectVals( [originalArrayOfObjects, newArrayOfObjects], relatedObjectKey // Not required, but suggested for speed. ); expect(createdVals).toStrictEqual([{ one: 22, five: 5 }]); expect(updatedVals).toStrictEqual([{ one: 1, two: null }]); expect(deletedVals).toStrictEqual([{ test: undefined }]); }); test('compareObjectVals functionality w/ only updated objects', () => { const orgOb1 = [ {'test': 11, 'key2': 32}, {'test': 23, 1: [1,3]} ]; const newOb1 = [ {'test': 11, 'key2': 22}, {'test': 23, 1: [1,18,3]} ]; const { createdVals, updatedVals, deletedVals } = compareObjectVals([orgOb1, newOb1]); expect(deletedVals).toStrictEqual(null); expect(updatedVals).toStrictEqual([ {'test': 11, 'key2': 22}, {'test': 23, 1: [1,18,3]}] ); expect(createdVals).toStrictEqual(null); }); test('compareObjectVals functionality w/ nested objects given the key', () => { const orgOb1 = [ {'test': 11, 'key2': 22}, {'test': 23, 1: [1,3]}, {'test': [{'test33': 22}, {1: 22}]} ]; const newOb1 = [ {'test': 11, 'key2': 33}, {'test': 23, 1: [1,8,3]}, {'test': 22} ] const { createdVals, updatedVals, deletedVals } = compareObjectVals([orgOb1, newOb1], 'test'); expect(deletedVals).toStrictEqual([{'test': [{'test33': 22}, {1: 22}]}]); expect(updatedVals).toStrictEqual([{'test': 11, 'key2': 33}, {'test': 23, 1: [1,8,3]}]); expect(createdVals).toStrictEqual([{'test': 22}]); }); test('compareObjectVals functionality w/ nested objects given an incorrect key', () => { const key = Symbol('3434'); const orgOb1 = [ { [key]: 11, 'key2': 22}, { [key]: 23, 1: [1,3]}, { [key]: [{'test33': 22}, {1: 22}]} ]; const newOb1 = [ { [key]: 11, 'key2': 33}, { [key]: 23, 1: [1,8,3]}, { [key]: 22} ]; const { createdVals, updatedVals, deletedVals } = compareObjectVals([orgOb1, newOb1], [key, [33,3,3,3,33]]); expect(deletedVals).toStrictEqual([ { [key]: 11, 'key2': 22}, { [key]: 23, 1: [1,3]}, { [key]: [{'test33': 22}, {1: 22}]} ]); expect(updatedVals).toStrictEqual(null); expect(createdVals).toStrictEqual([ { [key]: 11, 'key2': 33}, { [key]: 23, 1: [1,8,3]}, { [key]: 22} ]); }); test('compareObjectVals functionality w/ composite keys', () => { const symKey = Symbol('44'); const orgOb1 = [ {[symKey]: 11, 'key2': 22}, {[symKey]: 55, 'key2': 90, 'anotherkey': 'keyval'}, {[symKey]: 23, 'key2': 88, 1: [1,3]}, ]; const newOb1 = [ {[symKey]: 11, 'key2': 22, 'key5': 'test'}, {[symKey]: 22, 'key2': 'newkeyval'}, {[symKey]: 23, 'key2': 88, 1: [1,8,3]} ]; const { createdVals, updatedVals, deletedVals } = compareObjectVals([orgOb1, newOb1], [symKey, 'key2']); expect(deletedVals).toStrictEqual([{[symKey]: 55, 'key2': 90, 'anotherkey': 'keyval'}]); expect(updatedVals).toStrictEqual([{[symKey]: 11, 'key2': 22, 'key5': 'test'}, {[symKey]: 23, 'key2': 88, 1: [1,8,3]}]); expect(createdVals).toStrictEqual([{[symKey]: 22, 'key2': 'newkeyval'}]); }); test('empty original array of objects', () => { const { createdVals, updatedVals, deletedVals } = compareObjectVals([[], newArrayOfObjects], 'commonKey'); expect(createdVals).toStrictEqual([{'commonKey': 2, 'newkey': 'test'},{'commonKey': 7}]); expect(updatedVals).toStrictEqual(null); expect(deletedVals).toStrictEqual(null); }); test('Incorrect compare key type, non-array key.', () => { try { compareObjectVals([[], newArrayOfObjects], {'test': 1}); } catch (e) { expect(e.message).toBe('The given compare key must be of type "string" or "symbol" if one is provided!') } }); test('Incorrect compare key type, array key.', () => { try { compareObjectVals([[], newArrayOfObjects], [{'test': 1}]); } catch (e) { expect(e.message).toBe('The key values must be primatives!') } }); test('No key w/ incorrect original object type.', () => { const orginalArrObjs = [{ 'one': 1 }, [2, 33]]; const activeArrObjs = [{ 'one': 1 }, { 'two': 2 }, [2, 33]]; try { compareObjectVals([orginalArrObjs, activeArrObjs]); } catch (e) { expect(e.message).toBe('Original item array must consist of only objects!'); } }); test('compareObjectVals input wrong length', () => { try { compareObjectVals([originalArrayOfObjects],'commonKey'); } catch (e) { expect(e.message).toBe('Compare arguments are of the wrong length!'); } }); test('compareObjectVals input validation', () => { const origArray = [ [{'commonKey': 1, 'anotherkey': 'test'}], [{'commonKey': 2}] ] const newArray = [ [{'commonKey': 2, 'anotherkey': 'test'}], [{'commonKey': 5}] ] const newFakeArray2 = { 'commonKey': 2, 'anotherkey': 'test' } try { const compareVals = compareObjectVals([origArray, newArray],'commonKey'); const { createdVals, updatedVals, deletedVals } = compareVals; } catch (e) { expect(e.message).toBe('The provided originalArray, is not an array of objects!') } try { const compareVals = compareObjectVals([originalArrayOfObjects, newArray],'commonKey'); const { createdVals, updatedVals, deletedVals } = compareVals; } catch (e) { expect(e.message).toBe('The provided stateUpdatedArray, is not an array of objects!') } try { const compareVals = compareObjectVals([originalArrayOfObjects, newFakeArray2],'commonKey'); const { createdVals, updatedVals, deletedVals } = compareVals; } catch (e) { expect(e.message).toBe('The originalArray and stateUpdatedArray must both be arrays!') } try { const compareVals = compareObjectVals({originalArrayOfObjects, newFakeArray2},'commonKey'); const { createdVals, updatedVals, deletedVals } = compareVals; } catch (e) { expect(e.message).toBe(`toCompareVals must be an array of the originalArray and stateUpdatedArray you want to compare!`); } }); test('receive both as empty arrays', () => { const compareVals = compareObjectVals([[], []],'commonKey'); expect(compareVals.createdVals).toBe(null); expect(compareVals.updatedVals).toBe(null); expect(compareVals.deletedVals).toBe(null); }); test('mirror values w/ multiple rows', () => { const ob1 = [ { id: 1, key2: 'test1' }, { id: 2, key2: 'test' } ]; const { createdVals, updatedVals, deletedVals } = compareObjectVals([ob1, ob1], 'id'); expect(deletedVals).toStrictEqual(null); expect(updatedVals).toStrictEqual(null); expect(createdVals).toStrictEqual(null); }); test('values have nonmatching key values', () => { const ob1 = [ { id: 1, key2: 'test1' }, { other: 2, key2: 'test' } ]; const ob2 = [ { id: 1, key2: 'anothertest' }, { other: 5, key2: 'testd' } ] const { createdVals, updatedVals, deletedVals } = compareObjectVals([ob1, ob2]); expect(deletedVals).toStrictEqual([{ key2: "test", other: 2}]); expect(updatedVals).toStrictEqual([{ id: 1, key2: 'anothertest' }]); expect(createdVals).toStrictEqual([{ other: 5, key2: 'testd' }]); }) }); const originalArrayItem = [1, 2, 'five', true, 33]; const updatedArrayItem = [1, 'seven', true, 33]; describe('CompareArrayVals tests', () => { test('compareArrayVals functionality', () => { const { createdVals, deletedVals } = compareArrayVals( [originalArrayItem, updatedArrayItem]); expect(createdVals).toStrictEqual(['seven']); expect(deletedVals).toStrictEqual([2, 'five']); }); test('input wrong length', () => { try { compareArrayVals([originalArrayItem]); } catch (e) { expect(e.message).toBe('ToCompareVal arguments are of the wrong length!') } }); test('Empty original item', () => { const { createdVals, deletedVals } = compareArrayVals([[], updatedArrayItem]); expect(createdVals).toStrictEqual([1, 'seven', true, 33]); expect(deletedVals).toStrictEqual(null); }); test('Received two empty array items', () => { const { createdVals, deletedVals } = compareArrayVals([[], []]); expect(createdVals).toStrictEqual(null); expect(deletedVals).toStrictEqual(null); }); test('Received first undefined value', () => { const { createdVals, deletedVals } = compareArrayVals([undefined, [33]]); expect(createdVals).toStrictEqual([33]); expect(deletedVals).toStrictEqual(null); }); test('Received second undefined value', () => { const { createdVals, deletedVals } = compareArrayVals([[33], undefined]); expect(createdVals).toStrictEqual(null); expect(deletedVals).toStrictEqual([33]); }); test('Received both undefined values', () => { const { createdVals, deletedVals } = compareArrayVals([undefined, undefined]); expect(createdVals).toStrictEqual(null); expect(deletedVals).toStrictEqual(null); }); test('Created Values only.', () => { const uniqueSymbol = Symbol('3'); const { createdVals, deletedVals } = compareArrayVals([['1'], ['1', 2, uniqueSymbol]]); expect(createdVals).toStrictEqual([2, uniqueSymbol]); expect(deletedVals).toBe(null); }); test('Deleted Values only.', () => { const uniqueSymbol = Symbol('3'); const { createdVals, deletedVals } = compareArrayVals([['1', 2, uniqueSymbol], [2, uniqueSymbol]]); expect(createdVals).toBe(null); expect(deletedVals).toStrictEqual(['1']); }); }); const ob1 = { 'test': 1, 'test2': 2 }; const ob2 = { 'test': 1, 'test2': 2 }; const ob3 = { 'a': undefined }; const ob4 = { 'b': 'something' }; const ob5 = { 'a': Number.NaN }; const ob6 = { 'a': NaN }; const ob7 = { 'a': 'test', b: 5, c: 22, d: undefined }; const ob8 = { 'a': 'test', b: 55, c: 22, d: undefined }; const ob9 = { 'a': null , b: 55 }; const ob10 = { 'a': 1, b: 55 }; const ob11 = { a: undefined, b: 55 }; const ob12 = { a: undefined, b: 55 }; const ob13 = { a: null, b: undefined }; const ob14 = { a: null, b: undefined }; describe('isEqualObject helper tests', () => { test('isEqualObject basic truthy tests', () => { expect(isEqualObject(ob1, ob2)).toBe(true); expect(isEqualObject(ob3, ob3)).toBe(true); expect(isEqualObject(ob5, ob6)).toBe(true); expect(isEqualObject(ob11, ob12)).toBe(true); expect(isEqualObject(ob13, ob14)).toBe(true); expect(isEqualObject(ob5, ob5)).toBe(true); expect(isEqualObject(ob6, ob6)).toBe(true); }); test('isEqualObject basic falsy tests', () => { expect(isEqualObject(originalArrayOfObjects[0], newArrayOfObjects[0])).toBe(false); expect(isEqualObject(ob3, ob4)).toBe(false); expect(isEqualObject(ob4, ob3)).toBe(false); expect(isEqualObject(ob7, ob8)).toBe(false); expect(isEqualObject(ob9, ob10)).toBe(false); expect(isEqualObject(ob10, ob11)).toBe(false); expect(isEqualObject(ob10, undefined)).toBe(false); expect(isEqualObject(null, undefined)).toBe(false); expect(isEqualObject(null, ob10)).toBe(false); expect(isEqualObject(ob12, ob13)).toBe(false); }); test('isEqualObject with nested objects containing array of objects', () => { const oba1 = {a: 1, b: 2, c: {'one': 1, 'two': [{ 2: 1, 44:1 }]}}; const oba2 = {a: 1, b: 2, c: {'one': 1, 'two': [{ 2: 1, 44:1 }]}}; const oba3 = {a: 1, b: 2, c: {'one': 1, 'two': [{ 2: 1, 44:3 }]}}; const oba4 = {a: 1, b: 2, c: {'one': 1, 'two': [{ 44:1 }]}}; const oba5 = {a: 1, b: 2, c: {'one': 1, 'two': [22]}}; const oba6 = {a: 1, b: 2, c: {'one': 1, 'two': [22]}}; expect(isEqualObject(oba1, oba2)).toBe(true); expect(isEqualObject(oba2, oba3)).toBe(false); expect(isEqualObject(oba3, oba4)).toBe(false); expect(isEqualObject(oba4, oba5)).toBe(false); expect(isEqualObject(oba5, oba6)).toBe(true); }); test('isEqualObject with nested basic identical array', () => { const obb1 = {a: 1, b: [2]}; const obb2 = {a: 1, b: [2]}; const obb3 = {a: 1, b: [2, 33]}; const obb4 = {a: 1, b: [2, 33]}; const obb5 = {a: 1, b: {1: 33}}; const obb6 = {a: 1, b: {1: 33, 5: 11}}; const obb7 = {a: 1, b: {1: 33, 5: undefined}}; const obb8 = {a: 1, b: {1: 33, null: 3}}; const obb9 = {a: 1, b: {1: 33, null: 3}}; expect(isEqualObject(obb1, obb2)).toBe(true); expect(isEqualObject(obb2, obb3)).toBe(false); expect(isEqualObject(obb3, obb4)).toBe(true); expect(isEqualObject(obb4, obb5)).toBe(false); expect(isEqualObject(obb5, obb6)).toBe(false); expect(isEqualObject(obb6, obb7)).toBe(false); expect(isEqualObject(obb7, obb8)).toBe(false); expect(isEqualObject(obb8, obb9)).toBe(true); expect(isEqualObject(obb7, obb7)).toBe(true); }); }); describe ('isEqualArray helper tests', () => { test('Edge case array compare helper tests.', () => { expect(isEqualArray([1], [2])).toBe(false); expect(isEqualArray(['one','two'], [Symbol('33')])).toBe(false); expect(isEqualArray([[Symbol('33')]], [['one', 'two']])).toBe(false); expect(isEqualArray(null, [['one', 'two']])).toBe(false); expect(isEqualArray(undefined, [['one', 'two']])).toBe(false); expect(isEqualArray(null, undefined)).toBe(false); expect(isEqualArray(null, null)).toBe(true); expect(isEqualArray(undefined, undefined)).toBe(true); expect(isEqualArray(NaN, NaN)).toBe(true); expect(isEqualArray(Number.NaN, NaN)).toBe(true); }); });