New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

array-sync

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

array-sync - npm Package Compare versions

Comparing version

to
4.1.0

demo.js

7

CHANGELOG.md

@@ -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 @@

115

index.js

@@ -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 @@ }

12

package.json
{
"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"
}
}

@@ -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/);
});
});
});