Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
20 changes: 20 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Checks

on: [push]

jobs:
ci:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [12, 14, 16, 18, 20, 22, 24]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm run ci
29 changes: 23 additions & 6 deletions lib/arrayChanges.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ module.exports = function arrayChanges(actual, expected, equal, similar, options
return i;
}


function findMoveTargetWithId(id) {
return mutatedArray.find(function (diffItem) {
return diffItem.type === 'moveTarget' && diffItem.id === id;
});
}

var removes = itemsDiff.filter(function (diffItem) {
return diffItem.type === 'remove';
});
Expand All @@ -76,15 +83,13 @@ module.exports = function arrayChanges(actual, expected, equal, similar, options
return diffItem.type === 'move';
});


var ids = 0;
moves.forEach(function (diffItem) {
var moveFromIndex = offsetIndex(diffItem.from + 1) - 1;
var removed = mutatedArray.slice(moveFromIndex, diffItem.howMany + moveFromIndex);
removed.forEach(function (v, index) {
v.type = 'moveSource';
v.expectedIndex = offsetIndex(diffItem.to + index);
v.expected = expected[v.expectedIndex];
v.equal = equal(v.value, v.expected);
v.id = ids++;
});
var added = removed.map(function (v, index) {
return extend({}, v, { last: false, type: 'moveTarget' });
Expand All @@ -93,7 +98,6 @@ module.exports = function arrayChanges(actual, expected, equal, similar, options
Array.prototype.splice.apply(mutatedArray, [insertIndex, 0].concat(added));
});


var inserts = itemsDiff.filter(function (diffItem) {
return diffItem.type === 'insert';
});
Expand All @@ -114,14 +118,27 @@ module.exports = function arrayChanges(actual, expected, equal, similar, options
var offset = 0;
mutatedArray.forEach(function (diffItem, index) {
var type = diffItem.type;
if (type === 'remove' || type === 'moveSource') {
if (type === 'moveTarget') {
diffItem.expected = expected[offset + index];
diffItem.expectedIndex = offset + index;
diffItem.equal = equal(diffItem.value, diffItem.expected);
} else if (type === 'remove' || type === 'moveSource') {
offset -= 1;
} else if (type === 'similar') {
diffItem.expected = expected[offset + index];
diffItem.expectedIndex = offset + index;
}
});

mutatedArray.forEach(function (diffItem) {
if (diffItem.type === 'moveSource') {
var moveTarget = findMoveTargetWithId(diffItem.id);
diffItem.expected = moveTarget.expected;
diffItem.expectedIndex = moveTarget.expectedIndex;
diffItem.equal = moveTarget.equal;
}
});

var conflicts = mutatedArray.reduce(function (conflicts, item) {
return item.type === 'similar' || item.type === 'moveSource' || item.type === 'moveTarget' ? conflicts : conflicts + 1;
}, 0);
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"main": "./lib/arrayChanges.js",
"scripts": {
"lint": "eslint .",
"test": "mocha && npm run lint",
"travis": "npm test && npm run coverage && (<coverage/lcov.info coveralls || true)",
"test": "mocha",
"ci": "npm run lint && npm test && npm run coverage && (<coverage/lcov.info coveralls || true)",
"coverage": "NODE_ENV=development istanbul cover _mocha -- --reporter dot && echo google-chrome coverage/lcov-report/index.html",
"prepublish": "(echo '/*!' && <LICENSE sed -e's/^/ * /' | sed -e's/\\s+$//' && echo ' */' && browserify -p bundle-collapser/plugin -e lib/arrayChanges -s weknowhow.arrayChanges) > array-changes.js"
},
Expand Down
46 changes: 42 additions & 4 deletions test/arrayChanges.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ describe('array-changes', function () {
expect(arrayChanges([1, 2, 3, 0], [0, 1, 2, 3], function (a, b) {
return a === b;
}), 'to equal', [
{ type: 'moveTarget', value: 0, actualIndex: 3, expected: 0, expectedIndex: 0, equal: true, last: false },
{ type: 'moveTarget', value: 0, actualIndex: 3, expected: 0, expectedIndex: 0, id: 0, equal: true, last: false },
{ type: 'equal', value: 1, actualIndex: 0, expected: 1, expectedIndex: 1 },
{ type: 'equal', value: 2, actualIndex: 1, expected: 2, expectedIndex: 2 },
{ type: 'equal', value: 3, actualIndex: 2, expected: 3, expectedIndex: 3 },
{ type: 'moveSource', value: 0, actualIndex: 3, expected: 0, expectedIndex: 0, equal: true, last: true }
{ type: 'moveSource', value: 0, actualIndex: 3, expected: 0, expectedIndex: 0, id: 0, equal: true, last: true }
]);
});

Expand All @@ -122,9 +122,9 @@ describe('array-changes', function () {
return a === b;
}), 'to equal', [
{ type: 'equal', value: 0, actualIndex: 0, expected: 0, expectedIndex: 0 },
{ type: 'moveTarget', value: 2, actualIndex: 2, expected: 2, expectedIndex: 1, equal: true, last: false },
{ type: 'moveTarget', value: 2, actualIndex: 2, expected: 2, expectedIndex: 1, id: 0, equal: true, last: false },
{ type: 'equal', value: 1, actualIndex: 1, expected: 1, expectedIndex: 2 },
{ type: 'moveSource', value: 2, actualIndex: 2, expected: 2, expectedIndex: 1, equal: true },
{ type: 'moveSource', value: 2, actualIndex: 2, expected: 2, expectedIndex: 1, id: 0, equal: true },
{ type: 'equal', value: 3, actualIndex: 3, expected: 3, expectedIndex: 3, last: true }
]);
});
Expand Down Expand Up @@ -451,6 +451,7 @@ describe('array-changes', function () {
expected: { kind: 1, type: 'tag', name: 'p', children: [{ data: 'Hello world 2025', type: 'text' }], attribs: {} },
actualIndex: 1,
expectedIndex: 0,
id: 0,
equal: false,
last: false
},
Expand All @@ -467,9 +468,46 @@ describe('array-changes', function () {
expected: { kind: 1, type: 'tag', name: 'p', children: [{ data: 'Hello world 2025', type: 'text' }], attribs: {} },
actualIndex: 1,
expectedIndex: 0,
id: 0,
equal: false,
last: true
}
]);
});

it("handles moves where no items are similar", function () {
var a = ['a', 'b', 'c'];
var b = ['c', 'b', 'a'];

expect(arrayChanges(a, b, function (a, b) {
return expect.equal(a, b);
}, function () {
return false;
}), 'to equal', [
{ type: 'moveTarget', value: 'c', actualIndex: 2, last: false, expected: 'c', expectedIndex: 0, id: 1, equal: true },
{ type: 'moveTarget', value: 'b', actualIndex: 1, last: false, expected: 'b', expectedIndex: 1, id: 0, equal: true },
{ type: 'equal', value: 'a', actualIndex: 0, expected: 'a', expectedIndex: 2 },
{ type: 'moveSource', value: 'b', actualIndex: 1, expected: 'b', expectedIndex: 1, id: 0, equal: true },
{ type: 'moveSource', value: 'c', actualIndex: 2, expected: 'c', expectedIndex: 0, id: 1, equal: true, last: true }
]);
});

it("handles moves with a mix of equal and similar items", function () {
var a = ['aaa', 'bbb', 'ccc', 'dddd'];
var b = ['ddd', 'ccc', 'bbb', 'aaa'];

expect(arrayChanges(a, b, function (a, b) {
return expect.equal(a, b);
}, function (a, b) {
return expect.equal(a.slice(0, 3), b.slice(0, 3));
}), 'to equal', [
{ type: 'moveTarget', value: 'dddd', actualIndex: 3, id: 2, last: false, expected: 'ddd', expectedIndex: 0, equal: false },
{ type: 'moveTarget', value: 'ccc', actualIndex: 2, id: 1, last: false, expected: 'ccc', expectedIndex: 1, equal: true },
{ type: 'moveTarget', value: 'bbb', actualIndex: 1, id: 0, last: false, expected: 'bbb', expectedIndex: 2, equal: true },
{ type: 'equal', value: 'aaa', actualIndex: 0, expected: 'aaa', expectedIndex: 3 },
{ type: 'moveSource', value: 'bbb', actualIndex: 1, id: 0, expected: 'bbb', expectedIndex: 2, equal: true },
{ type: 'moveSource', value: 'ccc', actualIndex: 2, id: 1, expected: 'ccc', expectedIndex: 1, equal: true },
{ type: 'moveSource', value: 'dddd', actualIndex: 3, id: 2, expected: 'ddd', expectedIndex: 0, equal: false, last: true }
]);
});
});
1 change: 0 additions & 1 deletion test/arraydiff.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ describe('arraydiff', function () {
var out = before.slice();
for (var i = 0; i < diff.length; i++) {
var item = diff[i];
// console.log 'applying:', out, item
if (item.type === 'insert') {
insert(out, item.index, item.values);
} else if (item.type === 'remove') {
Expand Down