array-changes-async
Advanced tools
Comparing version 2.0.2 to 2.1.0
/*global setTimeout */ | ||
var arrayDiff = require('arraydiff-async'); | ||
var MAX_STACK_DEPTH = 1000; | ||
@@ -16,3 +15,7 @@ | ||
module.exports = function arrayChanges(actual, expected, equal, similar, arrayChangesCallback) { | ||
module.exports = function arrayChanges(actual, expected, equal, similar, includeNonNumericalProperties, arrayChangesCallback) { | ||
if (typeof includeNonNumericalProperties === 'function') { | ||
arrayChangesCallback = includeNonNumericalProperties; | ||
includeNonNumericalProperties = false; | ||
} | ||
var mutatedArray = new Array(actual.length); | ||
@@ -28,6 +31,2 @@ | ||
if (mutatedArray.length > 0) { | ||
mutatedArray[mutatedArray.length - 1].last = true; | ||
} | ||
similar = similar || function (a, b, aIndex, bIndex, callback) { | ||
@@ -129,4 +128,2 @@ return callback(false); | ||
var stackCallsRemaining = MAX_STACK_DEPTH; | ||
var countConflicts = function (i, c, stackCallsRemaining, callback) { | ||
@@ -194,10 +191,6 @@ | ||
} | ||
if (mutatedArray.length > 0) { | ||
mutatedArray[mutatedArray.length - 1].last = true; | ||
} | ||
} | ||
var mutatedArrayLength = mutatedArray.length; | ||
var setEqual = function (i, stackCallsRemaining, callback) { | ||
if (i >= mutatedArrayLength) { | ||
if (i >= mutatedArray.length) { | ||
return callback(); | ||
@@ -208,9 +201,9 @@ } | ||
return equal(diffItem.value, diffItem.expected, diffItem.actualIndex, diffItem.expectedIndex, function (areEqual) { | ||
if (areEqual) { | ||
mutatedArray[i].type = 'equal'; | ||
} | ||
if (areEqual) { | ||
mutatedArray[i].type = 'equal'; | ||
} | ||
if (stackCallsRemaining === 0) { | ||
return setTimeout(function () { | ||
setEqual(i + 1, MAX_STACK_DEPTH, callback); | ||
}) | ||
}); | ||
} | ||
@@ -223,3 +216,3 @@ setEqual(i + 1, stackCallsRemaining - 1, callback); | ||
setEqual(i + 1, MAX_STACK_DEPTH, callback); | ||
}) | ||
}); | ||
} | ||
@@ -229,8 +222,62 @@ return setEqual(i + 1, stackCallsRemaining - 1, callback); | ||
if (includeNonNumericalProperties) { | ||
var nonNumericalKeys; | ||
if (Array.isArray(includeNonNumericalProperties)) { | ||
nonNumericalKeys = includeNonNumericalProperties; | ||
} else { | ||
var isSeenByNonNumericalKey = {}; | ||
nonNumericalKeys = []; | ||
[actual, expected].forEach(function (obj) { | ||
Object.keys(obj).forEach(function (key) { | ||
if (!/^(?:0|[1-9][0-9]*)$/.test(key) && !isSeenByNonNumericalKey[key]) { | ||
isSeenByNonNumericalKey[key] = true; | ||
nonNumericalKeys.push(key); | ||
} | ||
}); | ||
if (Object.getOwnPropertySymbols) { | ||
Object.getOwnPropertySymbols(obj).forEach(function (symbol) { | ||
if (!isSeenByNonNumericalKey[symbol]) { | ||
isSeenByNonNumericalKey[symbol] = true; | ||
nonNumericalKeys.push(symbol); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
nonNumericalKeys.forEach(function (key) { | ||
if (key in actual) { | ||
if (key in expected) { | ||
mutatedArray.push({ | ||
type: 'similar', | ||
expectedIndex: key, | ||
actualIndex: key, | ||
value: actual[key], | ||
expected: expected[key] | ||
}); | ||
} else { | ||
mutatedArray.push({ | ||
type: 'remove', | ||
actualIndex: key, | ||
value: actual[key] | ||
}); | ||
} | ||
} else { | ||
mutatedArray.push({ | ||
type: 'insert', | ||
expectedIndex: key, | ||
value: expected[key] | ||
}); | ||
} | ||
}); | ||
} | ||
setEqual(0, MAX_STACK_DEPTH, function () { | ||
if (mutatedArray.length > 0) { | ||
mutatedArray[mutatedArray.length - 1].last = true; | ||
} | ||
arrayChangesCallback(mutatedArray); | ||
}); | ||
}); | ||
}); | ||
}; |
{ | ||
"name": "array-changes-async", | ||
"version": "2.0.2", | ||
"version": "2.1.0", | ||
"description": "Array diffing", | ||
@@ -15,3 +15,3 @@ "main": "./lib/arrayChanges.js", | ||
"type": "git", | ||
"url": "https://github.com/unexpectedjs/array-changes" | ||
"url": "https://github.com/bruderstein/array-changes-async" | ||
}, | ||
@@ -21,6 +21,6 @@ "keywords": [ | ||
], | ||
"author": "Sune Simonsen <sss@one.com>", | ||
"author": "Dave Brotherstone <davegb@pobox.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/unexpectedjs/array-changes-async/issues" | ||
"url": "https://github.com/bruderstein/array-changes-async/issues" | ||
}, | ||
@@ -27,0 +27,0 @@ "homepage": "https://github.com/bruderstein/array-changes-async", |
@@ -1,2 +0,2 @@ | ||
/*global describe, it, setTimeout*/ | ||
/*global describe, it, setTimeout, Symbol*/ | ||
var arrayChanges = require('../lib/arrayChanges'); | ||
@@ -8,6 +8,6 @@ var expect = require('unexpected'); | ||
} | ||
function promiseArrayChanges(actual, expected, equal, similar) { | ||
function promiseArrayChanges(actual, expected, equal, similar, includeNonNumericalProperties) { | ||
var isCalled = 0; | ||
return expect.promise(function (resolve, reject) { | ||
arrayChanges(actual, expected, equal, similar, function (itemDiff) { | ||
arrayChanges(actual, expected, equal, similar, includeNonNumericalProperties, function (itemDiff) { | ||
isCalled += 1; | ||
@@ -26,7 +26,3 @@ var stack = ''; | ||
if (isCalled !== 1) { | ||
try { | ||
throw new Error(); | ||
} catch (e) { | ||
return reject('callback called more than once' + stack); | ||
} | ||
return reject('callback called more than once' + stack); | ||
} | ||
@@ -40,3 +36,3 @@ resolve(itemDiff); | ||
describe('array-changes', function () { | ||
describe('array-changes-async', function () { | ||
it('returns an empty change-list when the two arrays are both empty', function () { | ||
@@ -223,3 +219,3 @@ return expect(promiseArrayChanges([], [], function (a, b, callback) { | ||
return expect(promiseArrayChanges([ 1, 2, 4 ], [ 1, 2, 3, 4 ], function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b) | ||
callback(a === b); | ||
}, null), 'when fulfilled', 'to satisfy', [ | ||
@@ -239,3 +235,3 @@ { type: 'equal', value: 1 }, | ||
function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b) | ||
callback(a === b); | ||
}, function (a, b, aIndex, bIndex, callback) { | ||
@@ -253,2 +249,87 @@ if (Math.floor(a) === Math.floor(b)) { | ||
}); | ||
it('does not provide the value from the expected if the value moves', function () { | ||
// If the `similar` callback returns false when `equal` returns true, the algorithm | ||
// gets the wrong answer, and includes the expected value as `value` in the result | ||
// This isn't a problem with the algorithm, as an equal value must be similar, | ||
// but this test just checks that for a move operation, we don't get values from the | ||
// "wrong" side | ||
return expect(promiseArrayChanges( | ||
[ 4, 2, 3, 1 ], [ 100, 200, 300, 400 ], function (a, b, aIndex, bIndex, callback){ | ||
return callback(a * 100 === b); | ||
}, function (a, b, aIndex, bIndex, callback) { return callback(a * 100 === b); }), | ||
'when fulfilled', 'to satisfy', [ | ||
{ type: 'similar', value: 4, expected: 100 }, | ||
{ type: 'equal', value: 2, expected: 200 }, | ||
{ type: 'equal', value: 3, expected: 300 }, | ||
{ type: 'similar', value: 1, expected: 400 } | ||
]); | ||
}); | ||
it('should diff arrays that have non-numerical property names', function () { | ||
var a = [1, 2, 3]; | ||
a.foo = 123; | ||
a.bar = 456; | ||
a.quux = {}; | ||
var b = [1, 2, 3]; | ||
b.bar = 456; | ||
b.baz = 789; | ||
b.quux = false; | ||
return expect(promiseArrayChanges(a, b, function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b); | ||
}, function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b); | ||
}, true), 'when fulfilled', 'to equal', [ | ||
{ type: 'equal', value: 1, expected: 1, actualIndex: 0, expectedIndex: 0 }, | ||
{ type: 'equal', value: 2, expected: 2, actualIndex: 1, expectedIndex: 1 }, | ||
{ type: 'equal', value: 3, expected: 3, actualIndex: 2, expectedIndex: 2 }, | ||
{ type: 'remove', value: 123, actualIndex: 'foo' }, | ||
{ type: 'equal', value: 456, expected: 456, actualIndex: 'bar', expectedIndex: 'bar' }, | ||
{ type: 'similar', value: {}, expected: false, actualIndex: 'quux', expectedIndex: 'quux' }, | ||
{ type: 'insert', value: 789, expectedIndex: 'baz', last: true } | ||
]); | ||
}); | ||
it('should support an array of specific non-numerical keys to diff', function () { | ||
var a = [1]; | ||
a.foo = 123; | ||
a.bar = 789; | ||
var b = [1]; | ||
a.foo = 456; | ||
a.bar = false; | ||
return expect(promiseArrayChanges(a, b, function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b); | ||
}, function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b); | ||
}, [ 'foo' ]), 'when fulfilled', 'to equal', [ | ||
{ type: 'equal', actualIndex: 0, expectedIndex: 0, value: 1, expected: 1 }, | ||
{ type: 'remove', actualIndex: 'foo', value: 456, last: true } | ||
]); | ||
}); | ||
if (typeof Symbol !== 'undefined') { | ||
it('should diff arrays that have Symbol property names', function () { | ||
var aSymbol = Symbol('a'); | ||
var bSymbol = Symbol('b'); | ||
var a = [1, 2]; | ||
a[aSymbol] = 123; | ||
var b = [1, 2]; | ||
b[bSymbol] = 456; | ||
return expect(promiseArrayChanges(a, b, function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b); | ||
}, function (a, b, aIndex, bIndex, callback) { | ||
callback(a === b); | ||
}, true), 'when fulfilled', 'to equal', [ | ||
{ type: 'equal', value: 1, expected: 1, actualIndex: 0, expectedIndex: 0 }, | ||
{ type: 'equal', value: 2, expected: 2, actualIndex: 1, expectedIndex: 1 }, | ||
{ type: 'remove', value: 123, actualIndex: aSymbol }, | ||
{ type: 'insert', value: 456, expectedIndex: bSymbol, last: true } | ||
]); | ||
}); | ||
} | ||
}); | ||
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
66446
565