+445
| 'use strict'; | ||
| const { performance } = require('perf_hooks'); | ||
| const arraySync = require('./index'); | ||
| const one = [ | ||
| { | ||
| active: true, | ||
| dateCreated: 1572332411, | ||
| dateModified: 1572332418, | ||
| id: '5db7e37b7b7171cee3269384', | ||
| label: 'Ardillio', | ||
| __typename: 'Label', | ||
| f: (s) => console.log(s), | ||
| b: Symbol('b') | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326989, | ||
| dateModified: 1572326989, | ||
| id: '5db7ce4d7b7171cee3269382', | ||
| label: | ||
| 'This is going to be a super long, really, really, really, really large label so that I can use it to test with', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326868, | ||
| dateModified: 1572326868, | ||
| id: '5db7cdd47b7171cee3269381', | ||
| label: 'Wombat E', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326856, | ||
| dateModified: 1572326856, | ||
| id: '5db7cdc87b7171cee3269380', | ||
| label: 'Wombat D', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326845, | ||
| dateModified: 1572326845, | ||
| id: '5db7cdbd7b7171cee326937f', | ||
| label: 'Wombat C', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326797, | ||
| dateModified: 1572326797, | ||
| id: '5db7cd8d7b7171cee326937e', | ||
| label: 'Wombat B', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326450, | ||
| dateModified: 1572326450, | ||
| id: '5db7cc327b7171cee326937d', | ||
| label: 'Wombat A', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572325988, | ||
| dateModified: 1572325988, | ||
| id: '5db7ca647b7171cee326937c', | ||
| label: 'Wombat', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572315421, | ||
| dateModified: 1572315421, | ||
| id: '5db7a11de904183c959e5f2e', | ||
| label: 'Management: New', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314634, | ||
| dateModified: 1572314634, | ||
| id: '5db79e0ae904183c959e5f20', | ||
| label: 'Zebra', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314754, | ||
| dateModified: 1572314754, | ||
| id: '5db79e82e904183c959e5f2c', | ||
| label: 'Kangaroo', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314747, | ||
| dateModified: 1572314747, | ||
| id: '5db79e7be904183c959e5f2b', | ||
| label: 'Walrus', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314715, | ||
| dateModified: 1572314715, | ||
| id: '5db79e5be904183c959e5f2a', | ||
| label: 'Kite', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314678, | ||
| dateModified: 1572314678, | ||
| id: '5db79e36e904183c959e5f28', | ||
| label: 'Giraffe', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314673, | ||
| dateModified: 1572314673, | ||
| id: '5db79e31e904183c959e5f27', | ||
| label: 'Hiena', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314664, | ||
| dateModified: 1572314664, | ||
| id: '5db79e28e904183c959e5f26', | ||
| label: 'Monkey', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314662, | ||
| dateModified: 1572314662, | ||
| id: '5db79e26e904183c959e5f25', | ||
| label: 'Lion', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314657, | ||
| dateModified: 1572314657, | ||
| id: '5db79e21e904183c959e5f24', | ||
| label: 'Tiger', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314652, | ||
| dateModified: 1572314652, | ||
| id: '5db79e1ce904183c959e5f23', | ||
| label: 'Cat', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314641, | ||
| dateModified: 1572314646, | ||
| id: '5db79e11e904183c959e5f22', | ||
| label: 'Donkey', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314638, | ||
| dateModified: 1572314638, | ||
| id: '5db79e0ee904183c959e5f21', | ||
| label: 'Elephant', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314089, | ||
| dateModified: 1572314089, | ||
| id: '5db79be9e904183c959e5f1e', | ||
| label: 'Colors one', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314081, | ||
| dateModified: 1572314081, | ||
| id: '5db79be1e904183c959e5f1d', | ||
| label: 'Colors', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1560982455, | ||
| dateModified: 1560982455, | ||
| id: '5d0ab3b76438e800fa2a5559', | ||
| label: 'Management: PDP', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1560833887, | ||
| dateModified: 1560833887, | ||
| id: '5d086f5ff6eba400fad96310', | ||
| label: 'Management: Security', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1560831978, | ||
| dateModified: 1560831978, | ||
| id: '5d0867ea46c75900fa76f407', | ||
| label: 'Management: Planning', | ||
| __typename: 'Label' | ||
| } | ||
| ]; | ||
| const two = [ | ||
| { | ||
| active: true, | ||
| dateCreated: 1572332411, | ||
| dateModified: 1572332418, | ||
| id: '5db7e37b7b7171cee3269384', | ||
| label: 'Ardillio', | ||
| __typename: 'Label', | ||
| f: (s) => console.log(s), | ||
| b: Symbol('b') | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326989, | ||
| dateModified: 1572326989, | ||
| id: '5db7ce4d7b7171cee3269382', | ||
| label: | ||
| 'This is going to be a super long, really, really, really, really large label so that I can use it to test with', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326868, | ||
| dateModified: 1572326868, | ||
| id: '5db7cdd47b7171cee3269381', | ||
| label: 'Wombat E', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326856, | ||
| dateModified: 1572326856, | ||
| id: '5db7cdc87b7171cee3269380', | ||
| label: 'Wombat D', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326845, | ||
| dateModified: 1572326845, | ||
| id: '5db7cdbd7b7171cee326937f', | ||
| label: 'Wombat C', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326797, | ||
| dateModified: 1572326797, | ||
| id: '5db7cd8d7b7171cee326937e', | ||
| label: 'Wombat B', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572326450, | ||
| dateModified: 1572326450, | ||
| id: '5db7cc327b7171cee326937d', | ||
| label: 'Wombat A', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572325988, | ||
| dateModified: 1572325988, | ||
| id: '5db7ca647b7171cee326937c', | ||
| label: 'Wombat', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572315421, | ||
| dateModified: 1572315421, | ||
| id: '5db7a11de904183c959e5f2e', | ||
| label: 'Management: New', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314634, | ||
| dateModified: 1572314634, | ||
| id: '5db79e0ae904183c959e5f20', | ||
| label: 'Zebra', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314754, | ||
| dateModified: 1572314754, | ||
| id: '5db79e82e904183c959e5f2c', | ||
| label: 'Kangaroo', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314747, | ||
| dateModified: 1572314747, | ||
| id: '5db79e7be904183c959e5f2b', | ||
| label: 'Walrus', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314715, | ||
| dateModified: 1572314715, | ||
| id: '5db79e5be904183c959e5f2a', | ||
| label: 'Kite', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314678, | ||
| dateModified: 1572314678, | ||
| id: '5db79e36e904183c959e5f28', | ||
| label: 'Giraffe', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314673, | ||
| dateModified: 1572314673, | ||
| id: '5db79e31e904183c959e5f27', | ||
| label: 'Hiena', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314664, | ||
| dateModified: 1572314664, | ||
| id: '5db79e28e904183c959e5f26', | ||
| label: 'Monkey', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314662, | ||
| dateModified: 1572314662, | ||
| id: '5db79e26e904183c959e5f25', | ||
| label: 'Lion', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314657, | ||
| dateModified: 1572314657, | ||
| id: '5db79e21e904183c959e5f24', | ||
| label: 'Tiger', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314652, | ||
| dateModified: 1572314652, | ||
| id: '5db79e1ce904183c959e5f23', | ||
| label: 'Cat', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314641, | ||
| dateModified: 1572314646, | ||
| id: '5db79e11e904183c959e5f22', | ||
| label: 'Donkey', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314638, | ||
| dateModified: 1572314638, | ||
| id: '5db79e0ee904183c959e5f21', | ||
| label: 'Elephant', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314089, | ||
| dateModified: 1572314089, | ||
| id: '5db79be9e904183c959e5f1e', | ||
| label: 'Colors one', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1572314081, | ||
| dateModified: 1572314081, | ||
| id: '5db79be1e904183c959e5f1d', | ||
| label: 'Colors', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1560982455, | ||
| dateModified: 1560982455, | ||
| id: '5d0ab3b76438e800fa2a5559', | ||
| label: 'Management: PDP', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1560833887, | ||
| dateModified: 1560833887, | ||
| id: '5d086f5ff6eba400fad96310', | ||
| label: 'Management: Security', | ||
| __typename: 'Label' | ||
| }, | ||
| { | ||
| active: true, | ||
| dateCreated: 1560831978, | ||
| dateModified: 1560831978, | ||
| id: '5d0867ea46c75900fa76f407', | ||
| label: 'Management: Planning', | ||
| __typename: 'Label' | ||
| } | ||
| ]; | ||
| const start = performance.now(); | ||
| const sync = arraySync(one, two); | ||
| const elapsed = performance.now() - start; | ||
| console.log({ | ||
| elapsed, | ||
| removed: sync.removed.length, | ||
| created: sync.created.length, | ||
| unchanged: sync.unchanged.length | ||
| }); |
+7
-0
@@ -5,2 +5,9 @@ # array-sync change log | ||
| ## 4.1.0 - 2019-11-01 | ||
| - Removed `assert` to provide a massive performance boost. | ||
| - Added support for comparison of Symbol(s) and Function(s). | ||
| - **Deprecated** the `remove` property, renaming it to `removed`. | ||
| - **Deprecated** the `create` property, renaming it to `created`. | ||
| ## 4.0.0 - 2019-07-15 | ||
@@ -7,0 +14,0 @@ |
+95
-20
@@ -1,5 +0,46 @@ | ||
| const assert = require('assert'); | ||
| /** | ||
| * Determine if something is an array. | ||
| * @param {String} valueType A string returned from the `type` function. | ||
| * @return {Boolean} Return `true` if the object is an array. | ||
| */ | ||
| const isArray = (valueType) => valueType === '[object Array]'; | ||
| /** | ||
| * The default comparator function. Simple strict equality all the way. | ||
| * Determine if something is a function. | ||
| * @param {String} valueType A string returned from the `type` function. | ||
| * @return {Boolean} Return `true` if the object is a function. | ||
| */ | ||
| const isFunction = (valueType) => valueType === '[object Function]'; | ||
| /** | ||
| * Determine if something is a symbol. | ||
| * @param {String} valueType A string returned from the `type` symbol. | ||
| * @return {Boolean} Return `true` if the object is a symbol. | ||
| */ | ||
| const isSymbol = (valueType) => valueType === '[object Symbol]'; | ||
| /** | ||
| * Determine if something is a plain object. | ||
| * @param {String} valueType A string returned from the `type` function. | ||
| * @return {Boolean} Return `true` if the object is a plain object. | ||
| */ | ||
| const isObject = (valueType) => valueType === '[object Object]'; | ||
| /** | ||
| * Determine if something is a plain object, or an array. | ||
| * @param {String} valueType A string returned from the `type` function. | ||
| * @return {Boolean} Return `true` if the object is a plain object, or an array. | ||
| */ | ||
| const isObjectOrArray = (valueType) => | ||
| isObject(valueType) || isArray(valueType); | ||
| /** | ||
| * Convert the type of an object to string for easy comparison. | ||
| * @param {Any} obj An object to determine the value of. | ||
| * @return {Boolean} Return a string representing the type of object (i.e. `[object Object]` or `[object Array]`). | ||
| */ | ||
| const type = (obj) => Object.prototype.toString.call(obj); | ||
| /** | ||
| * Used to compare if two items are equal. | ||
| * @param {Any} objOne The first object to compare. | ||
@@ -9,15 +50,37 @@ * @param {Any} objTwo Compare the first object to this object. | ||
| */ | ||
| const isEqual = (objOne, objTwo) => { | ||
| // Get the value type | ||
| const objOneType = type(objOne); | ||
| // Compare properties | ||
| if (isArray(objOneType)) { | ||
| return objOne.every((v, i) => comparator(v, objTwo[i])); | ||
| } | ||
| return Object.getOwnPropertyNames(objOne).every((key) => | ||
| comparator(objOne[key], objTwo[key]) | ||
| ); | ||
| }; | ||
| /** | ||
| * The default comparator function, which will loop through arrays to compare them. | ||
| * @param {Any} objOne The first object to compare. | ||
| * @param {Any} objTwo Compare the first object to this object. | ||
| * @return {Boolean} Return `true` if the object is the same, otherwise return `false`. | ||
| */ | ||
| const comparator = (objOne, objTwo) => { | ||
| // Compare an object to an object. | ||
| if (typeof objOne === 'object') { | ||
| try { | ||
| assert.deepStrictEqual(objOne, objTwo); | ||
| } catch (e) { | ||
| return false; | ||
| } | ||
| // Get the object type | ||
| const objOneType = type(objOne); | ||
| return true; | ||
| // If an object or array, compare recursively | ||
| if (isObjectOrArray(objOneType)) { | ||
| return isEqual(objOne, objTwo); | ||
| } | ||
| // Compare anything that is not (typeof objOne) === 'object' using the simple strict equals. | ||
| // If it's a function, convert to a string and compare. | ||
| if (isFunction(objOneType) || isSymbol(objOneType)) { | ||
| return objOne.toString() === objTwo.toString(); | ||
| } | ||
| // Otherwise, just compare. | ||
| return objOne === objTwo; | ||
@@ -86,3 +149,3 @@ }; | ||
| * @param {Array} source Source array. | ||
| * @param {Array} removeCreateAndChanged An updated version of the source array. | ||
| * @param {Array} removedCreatedChanged An updated version of the source array. | ||
| * @param {Object} opts An Object containing information to alter the outcome of the function. | ||
@@ -92,6 +155,6 @@ * @return {Array} An array of items that appear in the `update` array and exactly match | ||
| */ | ||
| const findUnchangedValues = (source, removeCreateAndChanged, opts) => | ||
| const findUnchangedValues = (source, removedCreatedChanged, opts) => | ||
| source.filter(function(sourceValue) { | ||
| return ( | ||
| removeCreateAndChanged.find(function(element, index, array) { | ||
| removedCreatedChanged.find(function(element, index, array) { | ||
| // If we have a key, we only want to compare the actual key is the same. | ||
@@ -190,12 +253,24 @@ if (opts.key) { | ||
| const r = { | ||
| remove: [], | ||
| get create() { | ||
| console.log( | ||
| 'DeprecationWarning: The create property has been deprecated, use the created property instead.' | ||
| ); | ||
| return this.removed; | ||
| }, | ||
| get remove() { | ||
| console.log( | ||
| 'DeprecationWarning: The remove property has been deprecated, use the removed property instead.' | ||
| ); | ||
| return this.removed; | ||
| }, | ||
| removed: [], | ||
| unchanged: [], | ||
| create: [] | ||
| created: [] | ||
| }; | ||
| // Find the missing values. | ||
| r.remove = findMissingValues(source, update, opts); | ||
| r.removed = findMissingValues(source, update, opts); | ||
| // Find the new values. | ||
| r.create = findNewValues(source, update, opts); | ||
| r.created = findNewValues(source, update, opts); | ||
@@ -210,3 +285,3 @@ // Add support for a more complex evaluation of Objects, if the `opts.key` has been provided. | ||
| source, | ||
| r.remove.concat(r.create, r.changed || []), | ||
| r.removed.concat(r.created, r.changed || []), | ||
| opts | ||
@@ -217,3 +292,3 @@ ); | ||
| if (opts.key && opts.keyOnly) { | ||
| r.remove = mapToKey(r.remove, opts.key); | ||
| r.removed = mapToKey(r.removed, opts.key); | ||
| r.unchanged = mapToKey(r.unchanged, opts.key); | ||
@@ -220,0 +295,0 @@ } |
+6
-6
| { | ||
| "name": "array-sync", | ||
| "version": "4.0.0", | ||
| "version": "4.1.0", | ||
| "description": "Data synchronisation module for Node.js", | ||
@@ -35,9 +35,9 @@ "main": "index.js", | ||
| "clone": "2.1.2", | ||
| "codecov": "3.5.0", | ||
| "eslint-config-prettier": "6.0.0", | ||
| "husky": "3.0.0", | ||
| "jest": "24.8.0", | ||
| "codecov": "3.6.1", | ||
| "eslint-config-prettier": "6.5.0", | ||
| "husky": "3.0.9", | ||
| "jest": "24.9.0", | ||
| "prettier": "1.18.2", | ||
| "pretty-quick": "1.11.1" | ||
| "pretty-quick": "2.0.0" | ||
| } | ||
| } |
+510
-307
@@ -7,6 +7,4 @@ 'use strict'; | ||
| describe('arraySync', () => { | ||
| test('must be passed a source Array', () => { | ||
| const fn = function () { | ||
| const fn = function() { | ||
| const middleware = arraySync(); // eslint-disable-line no-unused-vars | ||
@@ -16,8 +14,6 @@ }; | ||
| expect(fn).toThrowError(Error); | ||
| }); | ||
| test('must be passed an update Array', () => { | ||
| const fn = function () { | ||
| const fn = function() { | ||
| const middleware = arraySync([]); // eslint-disable-line no-unused-vars | ||
@@ -27,159 +23,174 @@ }; | ||
| expect(fn).toThrowError(Error); | ||
| }); | ||
| test( | ||
| 'must be passed a key when a comparator function is provided', | ||
| () => { | ||
| test('must be passed a key when a comparator function is provided', () => { | ||
| const fn = function() { | ||
| const middleware = arraySync([], [], { comparator: function() {} }); // eslint-disable-line no-unused-vars | ||
| }; | ||
| const fn = function () { | ||
| const middleware = arraySync([], [], { comparator: function () {} }); // eslint-disable-line no-unused-vars | ||
| }; | ||
| expect(fn).toThrowError(Error); | ||
| }); | ||
| expect(fn).toThrowError(Error); | ||
| } | ||
| ); | ||
| test('can accept an opts Object', () => { | ||
| const results = arraySync([], [], {}); | ||
| expect(results).toBeDefined(); | ||
| expect(results).toHaveProperty('remove'); | ||
| expect(results).toHaveProperty('removed'); | ||
| expect(results).toHaveProperty('unchanged'); | ||
| expect(results).toHaveProperty('create'); | ||
| expect(results).toHaveProperty('created'); | ||
| expect(results).not.toHaveProperty('changed'); | ||
| }); | ||
| test( | ||
| 'will resolve to an object with the keys remove, unchanged, create', | ||
| () => { | ||
| test('will resolve to an object with the keys removed, unchanged, created', () => { | ||
| const results = arraySync([], []); | ||
| const results = arraySync([], []); | ||
| expect(results).toBeDefined(); | ||
| expect(results).toHaveProperty('removed'); | ||
| expect(results).toHaveProperty('unchanged'); | ||
| expect(results).toHaveProperty('created'); | ||
| expect(results).not.toHaveProperty('changed'); | ||
| }); | ||
| expect(results).toBeDefined(); | ||
| expect(results).toHaveProperty('remove'); | ||
| expect(results).toHaveProperty('unchanged'); | ||
| expect(results).toHaveProperty('create'); | ||
| expect(results).not.toHaveProperty('changed'); | ||
| } | ||
| ); | ||
| test('will throw upon error', () => { | ||
| const fn = () => | ||
| arraySync( | ||
| [ | ||
| { | ||
| type: 'fruit', | ||
| _id: 1, | ||
| label: 'Apple', | ||
| stats: { views: 1, purchases: 1 } | ||
| }, | ||
| { | ||
| type: 'fruit', | ||
| _id: 2, | ||
| label: 'Cucumber', | ||
| stats: { views: 10, purchases: 2 } | ||
| } | ||
| ], | ||
| [ | ||
| { | ||
| type: 'fruit', | ||
| _id: 1, | ||
| label: 'Apple', | ||
| stats: { views: 20, purchases: 2 } | ||
| }, | ||
| { | ||
| type: 'vegetable', | ||
| _id: 2, | ||
| label: 'Cucumber', | ||
| stats: { views: 20, purchases: 5 } | ||
| } | ||
| ], | ||
| { | ||
| key: '_id', | ||
| comparator: function comparator(objOne, objTwo) { | ||
| throw new Error('Test error'); | ||
| } | ||
| } | ||
| ); | ||
| const fn = () => arraySync([ | ||
| { type: 'fruit', _id: 1, label: 'Apple', stats: { views: 1, purchases: 1 } }, | ||
| { type: 'fruit', _id: 2, label: 'Cucumber', stats: { views: 10, purchases: 2 } } | ||
| ], [ | ||
| { type: 'fruit', _id: 1, label: 'Apple', stats: { views: 20, purchases: 2 } }, | ||
| { type: 'vegetable', _id: 2, label: 'Cucumber', stats: {views: 20, purchases: 5 } } | ||
| ], { | ||
| key: '_id', | ||
| comparator: function comparator (objOne, objTwo) { | ||
| throw new Error('Test error'); | ||
| } | ||
| }); | ||
| expect(fn).toThrowError(); | ||
| }); | ||
| describe('will', () => { | ||
| describe('determine which items', () => { | ||
| describe('should be removed', () => { | ||
| test('when working with strings', () => { | ||
| const result = arraySync( | ||
| ['one', 'two', 'three', 'four'], | ||
| ['one', 'three', 'four'] | ||
| ); | ||
| const result = arraySync(['one', 'two', 'three', 'four'], ['one', 'three', 'four']); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toBe('two'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toBe('two'); | ||
| }); | ||
| test('when working with objects', () => { | ||
| const result = arraySync( | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' } | ||
| ], | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'three' } | ||
| ] | ||
| ); | ||
| const result = arraySync([ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' } | ||
| ], [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'three' } | ||
| ]); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toEqual({ type: 'node', label: 'two' }); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toEqual({ | ||
| type: 'node', | ||
| label: 'two' | ||
| }); | ||
| }); | ||
| }); | ||
| describe('should be created', () => { | ||
| describe('should be createdd', () => { | ||
| test('when working with strings', () => { | ||
| const result = arraySync( | ||
| ['one', 'two', 'three', 'four'], | ||
| ['one', 'two', 'three', 'four', 'five'] | ||
| ); | ||
| const result = arraySync(['one', 'two', 'three', 'four'], ['one', 'two', 'three', 'four', 'five']); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toBe('five'); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toBe('five'); | ||
| }); | ||
| test('when working with objects', () => { | ||
| const result = arraySync( | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' } | ||
| ], | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' } | ||
| ] | ||
| ); | ||
| const result = arraySync([ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' } | ||
| ], [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' } | ||
| ]); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toEqual({ type: 'node', label: 'three' }); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toEqual({ | ||
| type: 'node', | ||
| label: 'three' | ||
| }); | ||
| }); | ||
| }); | ||
| describe('are unchanged', () => { | ||
| test('when working with strings', () => { | ||
| const result = arraySync( | ||
| ['one', 'two', 'three', 'four'], | ||
| ['one', 'two', 'three', 'four', 'five'] | ||
| ); | ||
| const result = arraySync(['one', 'two', 'three', 'four'], ['one', 'two', 'three', 'four', 'five']); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result).not.toHaveProperty('changed'); | ||
@@ -193,19 +204,20 @@ | ||
| expect(result.unchanged[3]).toBe('four'); | ||
| }); | ||
| test('when working with objects', () => { | ||
| const result = arraySync( | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' } | ||
| ], | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' } | ||
| ] | ||
| ); | ||
| const result = arraySync([ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' } | ||
| ], [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' } | ||
| ]); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result).not.toHaveProperty('changed'); | ||
@@ -215,25 +227,30 @@ | ||
| expect(result.unchanged).toHaveLength(2); | ||
| expect(result.unchanged[0]).toEqual({ type: 'node', label: 'one' }); | ||
| expect(result.unchanged[1]).toEqual({ type: 'node', label: 'two' }); | ||
| expect(result.unchanged[0]).toEqual({ | ||
| type: 'node', | ||
| label: 'one' | ||
| }); | ||
| expect(result.unchanged[1]).toEqual({ | ||
| type: 'node', | ||
| label: 'two' | ||
| }); | ||
| }); | ||
| }); | ||
| describe('are unchanged, to be removed and to be created', () => { | ||
| describe('are unchanged, to be removed and to be createdd', () => { | ||
| test('when working with strings', () => { | ||
| const result = arraySync( | ||
| ['one', 'two', 'three', 'four'], | ||
| ['one', 'three', 'four', 'five'] | ||
| ); | ||
| const result = arraySync(['one', 'two', 'three', 'four'], ['one', 'three', 'four', 'five']); | ||
| expect(result).toBeDefined(); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toBe('two'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toBe('two'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toBe('five'); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toBe('five'); | ||
@@ -245,49 +262,59 @@ expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged[2]).toBe('four'); | ||
| }); | ||
| test('when working with objects', () => { | ||
| const result = arraySync( | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' }, | ||
| { type: 'node', label: 'four' } | ||
| ], | ||
| [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' }, | ||
| { type: 'node', label: 'five' } | ||
| ] | ||
| ); | ||
| const result = arraySync([ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' }, | ||
| { type: 'node', label: 'four' } | ||
| ], [ | ||
| { type: 'node', label: 'one' }, | ||
| { type: 'node', label: 'two' }, | ||
| { type: 'node', label: 'three' }, | ||
| { type: 'node', label: 'five' } | ||
| ]); | ||
| expect(result).toBeDefined(); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toEqual({ type: 'node', label: 'four' }); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toEqual({ | ||
| type: 'node', | ||
| label: 'four' | ||
| }); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toEqual({ type: 'node', label: 'five' }); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toEqual({ | ||
| type: 'node', | ||
| label: 'five' | ||
| }); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(3); | ||
| expect(result.unchanged[0]).toEqual({ type: 'node', label: 'one' }); | ||
| expect(result.unchanged[1]).toEqual({ type: 'node', label: 'two' }); | ||
| expect(result.unchanged[2]).toEqual({ type: 'node', label: 'three' }); | ||
| expect(result.unchanged[0]).toEqual({ | ||
| type: 'node', | ||
| label: 'one' | ||
| }); | ||
| expect(result.unchanged[1]).toEqual({ | ||
| type: 'node', | ||
| label: 'two' | ||
| }); | ||
| expect(result.unchanged[2]).toEqual({ | ||
| type: 'node', | ||
| label: 'three' | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('use a key, to compare complex items', () => { | ||
| test( | ||
| 'and determine which items are unchanged, to be removed and to be created', | ||
| () => { | ||
| const result = arraySync([ | ||
| test('and determine which items are unchanged, to be removed and to be createdd', () => { | ||
| const result = arraySync( | ||
| [ | ||
| { type: 'fruit', _id: 'one', label: 'Apple' }, | ||
@@ -298,3 +325,4 @@ { type: 'fruit', _id: 'two', label: 'Orange' }, | ||
| { type: 'fruit', _id: 'five', label: 'Plum' } | ||
| ], [ | ||
| ], | ||
| [ | ||
| { type: 'fruit', _id: 'one', label: 'Apple' }, | ||
@@ -305,48 +333,59 @@ { type: 'fruit', _id: 'two', label: 'Orange' }, | ||
| { type: 'vegetable', _id: 'six', label: 'Pumpkin' } | ||
| ], { | ||
| ], | ||
| { | ||
| key: '_id' | ||
| }); | ||
| } | ||
| ); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(3); | ||
| expect(result.unchanged[0]).toBe('one'); | ||
| expect(result.unchanged[1]).toBe('two'); | ||
| expect(result.unchanged[2]).toBe('three'); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(3); | ||
| expect(result.unchanged[0]).toBe('one'); | ||
| expect(result.unchanged[1]).toBe('two'); | ||
| expect(result.unchanged[2]).toBe('three'); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toEqual({ type: 'vegetable', _id: 'six', label: 'Pumpkin' }); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toEqual({ | ||
| type: 'vegetable', | ||
| _id: 'six', | ||
| label: 'Pumpkin' | ||
| }); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toBe('five'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toBe('five'); | ||
| expect(result).toHaveProperty('changed'); | ||
| expect(result.changed).toHaveLength(1); | ||
| expect(result.changed[0]).toEqual({ type: 'vegetable', _id: 'four', label: 'Cucumber' }); | ||
| expect(result).toHaveProperty('changed'); | ||
| expect(result.changed).toHaveLength(1); | ||
| expect(result.changed[0]).toEqual({ | ||
| type: 'vegetable', | ||
| _id: 'four', | ||
| label: 'Cucumber' | ||
| }); | ||
| }); | ||
| } | ||
| ); | ||
| test('and return complete objects', () => { | ||
| const result = arraySync( | ||
| [ | ||
| { type: 'fruit', _id: 'one', label: 'Apple' }, | ||
| { type: 'fruit', _id: 'two', label: 'Orange' }, | ||
| { type: 'fruit', _id: 'three', label: 'Grape' }, | ||
| { type: 'fruit', _id: 'four', label: 'Cucumber' }, | ||
| { type: 'fruit', _id: 'five', label: 'Plum' } | ||
| ], | ||
| [ | ||
| { type: 'fruit', _id: 'one', label: 'Apple' }, | ||
| { type: 'fruit', _id: 'two', label: 'Orange' }, | ||
| { type: 'fruit', _id: 'three', label: 'Grape' }, | ||
| { type: 'vegetable', _id: 'four', label: 'Cucumber' }, | ||
| { type: 'vegetable', _id: 'six', label: 'Pumpkin' } | ||
| ], | ||
| { | ||
| key: '_id', | ||
| keyOnly: false | ||
| } | ||
| ); | ||
| const result = arraySync([ | ||
| { type: 'fruit', _id: 'one', label: 'Apple' }, | ||
| { type: 'fruit', _id: 'two', label: 'Orange' }, | ||
| { type: 'fruit', _id: 'three', label: 'Grape' }, | ||
| { type: 'fruit', _id: 'four', label: 'Cucumber' }, | ||
| { type: 'fruit', _id: 'five', label: 'Plum' } | ||
| ], [ | ||
| { type: 'fruit', _id: 'one', label: 'Apple' }, | ||
| { type: 'fruit', _id: 'two', label: 'Orange' }, | ||
| { type: 'fruit', _id: 'three', label: 'Grape' }, | ||
| { type: 'vegetable', _id: 'four', label: 'Cucumber' }, | ||
| { type: 'vegetable', _id: 'six', label: 'Pumpkin' } | ||
| ], { | ||
| key: '_id', | ||
| keyOnly: false, | ||
| }); | ||
| expect(result).toBeDefined(); | ||
@@ -356,40 +395,80 @@ | ||
| expect(result.unchanged).toHaveLength(3); | ||
| expect(result.unchanged[0]).toEqual({ type: 'fruit', _id: 'one', label: 'Apple' }); | ||
| expect(result.unchanged[1]).toEqual({ type: 'fruit', _id: 'two', label: 'Orange' }); | ||
| expect(result.unchanged[2]).toEqual({ type: 'fruit', _id: 'three', label: 'Grape' }); | ||
| expect(result.unchanged[0]).toEqual({ | ||
| type: 'fruit', | ||
| _id: 'one', | ||
| label: 'Apple' | ||
| }); | ||
| expect(result.unchanged[1]).toEqual({ | ||
| type: 'fruit', | ||
| _id: 'two', | ||
| label: 'Orange' | ||
| }); | ||
| expect(result.unchanged[2]).toEqual({ | ||
| type: 'fruit', | ||
| _id: 'three', | ||
| label: 'Grape' | ||
| }); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toEqual({ type: 'vegetable', _id: 'six', label: 'Pumpkin' }); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toEqual({ | ||
| type: 'vegetable', | ||
| _id: 'six', | ||
| label: 'Pumpkin' | ||
| }); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toEqual({ type: 'fruit', _id: 'five', label: 'Plum' }); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toEqual({ | ||
| type: 'fruit', | ||
| _id: 'five', | ||
| label: 'Plum' | ||
| }); | ||
| expect(result).toHaveProperty('changed'); | ||
| expect(result.changed).toHaveLength(1); | ||
| expect(result.changed[0]).toEqual({ type: 'vegetable', _id: 'four', label: 'Cucumber' }); | ||
| expect(result.changed[0]).toEqual({ | ||
| type: 'vegetable', | ||
| _id: 'four', | ||
| label: 'Cucumber' | ||
| }); | ||
| }); | ||
| }); | ||
| describe('use a key, and a custom comparator', () => { | ||
| test('and determine which items are unchanged, to be removed and to be createdd', () => { | ||
| let called = false; | ||
| test( | ||
| 'and determine which items are unchanged, to be removed and to be created', | ||
| () => { | ||
| let called = false; | ||
| const result = arraySync([ | ||
| { type: 'fruit', _id: 1, label: 'Apple', stats: { views: 1, purchases: 1 } }, | ||
| { type: 'fruit', _id: 2, label: 'Cucumber', stats: { views: 10, purchases: 2 } } | ||
| ], [ | ||
| { type: 'fruit', _id: 1, label: 'Apple', stats: { views: 20, purchases: 2 } }, | ||
| { type: 'vegetable', _id: 2, label: 'Cucumber', stats: {views: 20, purchases: 5 } } | ||
| ], { | ||
| const result = arraySync( | ||
| [ | ||
| { | ||
| type: 'fruit', | ||
| _id: 1, | ||
| label: 'Apple', | ||
| stats: { views: 1, purchases: 1 } | ||
| }, | ||
| { | ||
| type: 'fruit', | ||
| _id: 2, | ||
| label: 'Cucumber', | ||
| stats: { views: 10, purchases: 2 } | ||
| } | ||
| ], | ||
| [ | ||
| { | ||
| type: 'fruit', | ||
| _id: 1, | ||
| label: 'Apple', | ||
| stats: { views: 20, purchases: 2 } | ||
| }, | ||
| { | ||
| type: 'vegetable', | ||
| _id: 2, | ||
| label: 'Cucumber', | ||
| stats: { views: 20, purchases: 5 } | ||
| } | ||
| ], | ||
| { | ||
| key: '_id', | ||
| comparator: function comparator (objOne, objTwo) { | ||
| comparator: function comparator(objOne, objTwo) { | ||
| called = true; | ||
@@ -399,3 +478,2 @@ | ||
| if (typeof objOne === 'object') { | ||
| const oOne = clone(objOne); | ||
@@ -415,3 +493,2 @@ const oTwo = clone(objTwo); | ||
| return true; | ||
| } | ||
@@ -421,35 +498,33 @@ | ||
| return objOne === objTwo; | ||
| } | ||
| }); | ||
| } | ||
| ); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(1); | ||
| expect(result.unchanged[0]).toBe(1); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(1); | ||
| expect(result.unchanged[0]).toBe(1); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(0); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(0); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(0); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(0); | ||
| expect(result).toHaveProperty('changed'); | ||
| expect(result.changed).toHaveLength(1); | ||
| expect(result.changed[0]).toEqual( | ||
| { type: 'vegetable', _id: 2, label: 'Cucumber', stats: {views: 20, purchases: 5 } } | ||
| ); | ||
| expect(result).toHaveProperty('changed'); | ||
| expect(result.changed).toHaveLength(1); | ||
| expect(result.changed[0]).toEqual({ | ||
| type: 'vegetable', | ||
| _id: 2, | ||
| label: 'Cucumber', | ||
| stats: { views: 20, purchases: 5 } | ||
| }); | ||
| expect(called).toBe(true); | ||
| } | ||
| ); | ||
| expect(called).toBe(true); | ||
| }); | ||
| }); | ||
| describe('work with', () => { | ||
| test('numbers', () => { | ||
| const result = arraySync([1, 2, 3, 4], [1, 3, 4, 5]); | ||
@@ -465,25 +540,26 @@ | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toBe(5); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toBe(5); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toBe(2); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toBe(2); | ||
| }); | ||
| test('arrays', () => { | ||
| const result = arraySync( | ||
| [ | ||
| ['a', 'b', 'c'], | ||
| ['one', 'two', 'three'], | ||
| ['cat', 'mouse', 'dog'], | ||
| ['orange', 'apple', 'pear'] | ||
| ], | ||
| [ | ||
| ['letter-a', 'letter-b', 'letter-c'], | ||
| ['one', 'two', 'three'], | ||
| ['orange', 'apple', 'pear'] | ||
| ] | ||
| ); | ||
| const result = arraySync([ | ||
| ['a', 'b', 'c'], | ||
| ['one', 'two', 'three'], | ||
| ['cat', 'mouse', 'dog'], | ||
| ['orange', 'apple', 'pear'] | ||
| ], [ | ||
| ['letter-a', 'letter-b', 'letter-c'], | ||
| ['one', 'two', 'three'], | ||
| ['orange', 'apple', 'pear'] | ||
| ]); | ||
| expect(result).toBeDefined(); | ||
@@ -494,25 +570,34 @@ | ||
| expect(result.unchanged[0]).toEqual(['one', 'two', 'three']); | ||
| expect(result.unchanged[1]).toEqual(['orange', 'apple', 'pear']); | ||
| expect(result.unchanged[1]).toEqual([ | ||
| 'orange', | ||
| 'apple', | ||
| 'pear' | ||
| ]); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toEqual(['letter-a', 'letter-b', 'letter-c']); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toEqual([ | ||
| 'letter-a', | ||
| 'letter-b', | ||
| 'letter-c' | ||
| ]); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(2); | ||
| expect(result.remove[0]).toEqual(['a', 'b', 'c']); | ||
| expect(result.remove[1]).toEqual(['cat', 'mouse', 'dog']); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(2); | ||
| expect(result.removed[0]).toEqual(['a', 'b', 'c']); | ||
| expect(result.removed[1]).toEqual(['cat', 'mouse', 'dog']); | ||
| }); | ||
| test('objects', () => { | ||
| const result = arraySync( | ||
| [ | ||
| { type: 'fruit', _id: 1, label: 'Apple' }, | ||
| { type: 'fruit', _id: 2, label: 'Cucumber' } | ||
| ], | ||
| [ | ||
| { type: 'fruit', _id: 1, label: 'Apple' }, | ||
| { type: 'vegetable', _id: 2, label: 'Cucumber' } | ||
| ] | ||
| ); | ||
| const result = arraySync([ | ||
| { type: 'fruit', _id: 1, label: 'Apple' }, | ||
| { type: 'fruit', _id: 2, label: 'Cucumber' } | ||
| ], [ | ||
| { type: 'fruit', _id: 1, label: 'Apple' }, | ||
| { type: 'vegetable', _id: 2, label: 'Cucumber' } | ||
| ]); | ||
| expect(result).toBeDefined(); | ||
@@ -522,26 +607,33 @@ | ||
| expect(result.unchanged).toHaveLength(1); | ||
| expect(result.unchanged[0]).toEqual({ type: 'fruit', _id: 1, label: 'Apple' }); | ||
| expect(result.unchanged[0]).toEqual({ | ||
| type: 'fruit', | ||
| _id: 1, | ||
| label: 'Apple' | ||
| }); | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toEqual({ type: 'vegetable', _id: 2, label: 'Cucumber' }); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toEqual({ | ||
| type: 'vegetable', | ||
| _id: 2, | ||
| label: 'Cucumber' | ||
| }); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toEqual({ type: 'fruit', _id: 2, label: 'Cucumber' }); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toEqual({ | ||
| type: 'fruit', | ||
| _id: 2, | ||
| label: 'Cucumber' | ||
| }); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| }); | ||
| test('strings', () => { | ||
| const result = arraySync( | ||
| ['Apple', 'Cucumber'], | ||
| ['Apple', 'Pear'] | ||
| ); | ||
| const result = arraySync([ | ||
| 'Apple', | ||
| 'Cucumber' | ||
| ], [ | ||
| 'Apple', | ||
| 'Pear' | ||
| ]); | ||
| expect(result).toBeDefined(); | ||
@@ -553,18 +645,129 @@ | ||
| expect(result).toHaveProperty('create'); | ||
| expect(result.create).toHaveLength(1); | ||
| expect(result.create[0]).toBe('Pear'); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0]).toBe('Pear'); | ||
| expect(result).toHaveProperty('remove'); | ||
| expect(result.remove).toHaveLength(1); | ||
| expect(result.remove[0]).toBe('Cucumber'); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0]).toBe('Cucumber'); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| }); | ||
| test('functions', () => { | ||
| let result = arraySync( | ||
| [(v) => v(), (i) => i()], | ||
| [(v) => v(), (g) => g()] | ||
| ); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(1); | ||
| expect(result.unchanged[0].toString()).toBe( | ||
| ((v) => v()).toString() | ||
| ); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0].toString()).toBe( | ||
| ((g) => g()).toString() | ||
| ); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0].toString()).toBe( | ||
| ((i) => i()).toString() | ||
| ); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| }); | ||
| test('symbols', () => { | ||
| let result = arraySync( | ||
| [Symbol('v'), Symbol('i')], | ||
| [Symbol('v'), Symbol('g')] | ||
| ); | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(1); | ||
| expect(result.unchanged[0].toString()).toBe( | ||
| Symbol('v').toString() | ||
| ); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0].toString()).toBe( | ||
| Symbol('g').toString() | ||
| ); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(1); | ||
| expect(result.removed[0].toString()).toBe( | ||
| Symbol('i').toString() | ||
| ); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| }); | ||
| }); | ||
| }); | ||
| describe('deprecations', () => { | ||
| test('create -> created', () => { | ||
| let result = arraySync([], [Symbol('g')]); | ||
| const original = console.log; | ||
| const mockFn = jest.fn(); | ||
| console.log = mockFn; | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(0); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0].toString()).toBe(Symbol('g').toString()); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(0); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| result.create; | ||
| console.log = original; | ||
| expect(mockFn.mock.calls).toHaveLength(1); | ||
| expect(mockFn.mock.calls[0][0]).toMatch(/DeprecationWarning/); | ||
| }); | ||
| test('remove -> removed', () => { | ||
| let result = arraySync([], [Symbol('g')]); | ||
| const original = console.log; | ||
| const mockFn = jest.fn(); | ||
| console.log = mockFn; | ||
| expect(result).toBeDefined(); | ||
| expect(result).toHaveProperty('unchanged'); | ||
| expect(result.unchanged).toHaveLength(0); | ||
| expect(result).toHaveProperty('created'); | ||
| expect(result.created).toHaveLength(1); | ||
| expect(result.created[0].toString()).toBe(Symbol('g').toString()); | ||
| expect(result).toHaveProperty('removed'); | ||
| expect(result.removed).toHaveLength(0); | ||
| expect(result).not.toHaveProperty('changed'); | ||
| result.remove; | ||
| console.log = original; | ||
| expect(mockFn.mock.calls).toHaveLength(1); | ||
| expect(mockFn.mock.calls[0][0]).toMatch(/DeprecationWarning/); | ||
| }); | ||
| }); | ||
| }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
61861
53.8%12
9.09%1346
123.59%