Skip to content

Commit 923d88c

Browse files
committed
[minor] allow option to ignore array ordering
1 parent 9123b8e commit 923d88c

File tree

2 files changed

+128
-33
lines changed

2 files changed

+128
-33
lines changed

src/index.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,24 @@
33
* Author: Gary Chisholm @omgaz
44
*/
55

6+
function isArray(toCheck) {
7+
return typeof toCheck === 'object' && Boolean(toCheck.length);
8+
}
9+
10+
const defaultOptions = {
11+
respectArrayOrder: true,
12+
};
13+
614
/**
715
* Read in two objects. Iterate over them and return the differences.
816
*
917
* @param {object} obj1 First object to compare from.
1018
* @param {object} obj2 Second object to compare against obj1.
19+
* @param {object} options Configure custom behaviour of diffler.
20+
* @param {boolean} options.respectArrayOrder Whether to care if arrays are ordered defaults to true.
1121
* @returns {object} Nested json object of changed properties containing a from and to key.
1222
*/
13-
function diffler(obj1, obj2) {
23+
function diffler(obj1, obj2, options = defaultOptions) {
1424
var diff = {};
1525

1626
// Iterate over obj1 looking for removals and differences in existing values
@@ -29,7 +39,13 @@ function diffler(obj1, obj2) {
2939

3040
// If property is an object then we need to recursively go down the rabbit hole
3141
else if (typeof obj1Val === 'object') {
32-
var tempDiff = diffler(obj1Val, obj2Val);
42+
let obj1ValForDiff = obj1Val;
43+
let obj2ValForDiff = obj2Val;
44+
if (!options.respectArrayOrder && isArray(obj1Val) && isArray(obj2Val)) {
45+
obj1ValForDiff = obj1Val.sort();
46+
obj2ValForDiff = obj2Val.sort();
47+
}
48+
var tempDiff = diffler(obj1ValForDiff, obj2ValForDiff);
3349
if (Object.keys(tempDiff).length > 0) {
3450
if (tempDiff) {
3551
diff[key] = tempDiff;

tests/index.js

Lines changed: 110 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,119 @@ describe('getDiff', () => {
77
const testObjectA = { name: 'gary' };
88
const testObjectB = { name: 'gary' };
99
const difference = diffler(testObjectA, testObjectB);
10-
assert.equal(Object.keys(difference).length, 0);
11-
assert.deepEqual(difference, {});
10+
assert.strictEqual(Object.keys(difference).length, 0);
11+
assert.deepStrictEqual(difference, {});
1212
});
1313

1414
it('should detect a single property change', () => {
1515
const testObjectA = { name: 'gary' };
1616
const testObjectB = { name: 'cindy' };
1717
const difference = diffler(testObjectA, testObjectB);
1818

19-
assert.equal(Object.keys(difference).length, 1);
20-
assert.equal(Object.keys(difference.name).length, 2);
19+
assert.strictEqual(Object.keys(difference).length, 1);
20+
assert.strictEqual(Object.keys(difference.name).length, 2);
2121

22-
assert.equal(difference.name.from, 'gary');
23-
assert.equal(difference.name.to, 'cindy');
22+
assert.strictEqual(difference.name.from, 'gary');
23+
assert.strictEqual(difference.name.to, 'cindy');
2424
});
2525

2626
it('should detect no changes', () => {
2727
const testObjectA = { name: 'gary' };
2828
const testObjectB = { name: 'gary' };
2929
const difference = diffler(testObjectA, testObjectB);
3030

31-
assert.equal(Object.keys(difference).length, 0);
31+
assert.strictEqual(Object.keys(difference).length, 0);
3232
});
3333

3434
it('should detect type changes', () => {
3535
const testObjectA = { name: '1' };
3636
const testObjectB = { name: 1 };
3737
const difference = diffler(testObjectA, testObjectB);
3838

39-
assert.equal(Object.keys(difference).length, 1);
40-
assert.equal(Object.keys(difference.name).length, 2);
39+
assert.strictEqual(Object.keys(difference).length, 1);
40+
assert.strictEqual(Object.keys(difference.name).length, 2);
4141

42-
assert.equal(difference.name.from, '1');
43-
assert.equal(difference.name.to, 1);
42+
assert.strictEqual(difference.name.from, '1');
43+
assert.strictEqual(difference.name.to, 1);
44+
});
45+
});
46+
47+
describe('array checks', () => {
48+
it('returns false when no changes detected', () => {
49+
const testObjectA = { arr: ['one', 'two'] };
50+
const testObjectB = { arr: ['one', 'two'] };
51+
const difference = diffler(testObjectA, testObjectB);
52+
assert.strictEqual(Object.keys(difference).length, 0);
53+
assert.deepStrictEqual(difference, {});
54+
});
55+
56+
it('returns change when array order shifted', () => {
57+
const testObjectA = { arr: ['one', 'two', 'three'] };
58+
const testObjectB = { arr: ['three', 'two', 'one'] };
59+
const difference = diffler(testObjectA, testObjectB);
60+
assert.strictEqual(Object.keys(difference).length, 1);
61+
assert.deepStrictEqual(difference, { arr: { 0: { from: 'one', to: 'three' }, 2: { from: 'three', to: 'one' } } });
62+
});
63+
64+
it('returns false when array order shifted but respectArrayOrder is false', () => {
65+
const testObjectA = { arr: ['one', 'two', 'three'] };
66+
const testObjectB = { arr: ['three', 'two', 'one'] };
67+
const difference = diffler(testObjectA, testObjectB, { respectArrayOrder: false });
68+
assert.strictEqual(Object.keys(difference).length, 0);
69+
assert.deepStrictEqual(difference, {});
70+
});
71+
72+
it('returns false when array order shifted but respectArrayOrder is false as numbers', () => {
73+
const testObjectA = { arr: [1, 2, 3] };
74+
const testObjectB = { arr: [2, 3, 1] };
75+
const difference = diffler(testObjectA, testObjectB, { respectArrayOrder: false });
76+
assert.strictEqual(Object.keys(difference).length, 0);
77+
assert.deepStrictEqual(difference, {});
78+
});
79+
80+
it('returns false when array order shifted but respectArrayOrder is false as mixed', () => {
81+
const testObjectA = { arr: [1, 'two', 3] };
82+
const testObjectB = { arr: ['two', 3, 1] };
83+
const difference = diffler(testObjectA, testObjectB, { respectArrayOrder: false });
84+
assert.strictEqual(Object.keys(difference).length, 0);
85+
assert.deepStrictEqual(difference, {});
86+
});
87+
88+
it('returns diff when array order shifted for non-primitives and respectArrayOrder is false', () => {
89+
const testObjectA = {
90+
myArray: [{ foo: 'bar' }, { baz: 'bat' }],
91+
};
92+
93+
const testObjectB = {
94+
myArray: [{ baz: 'bat' }, { foo: 'bar' }],
95+
};
96+
const difference = diffler(testObjectA, testObjectB, { respectArrayOrder: false });
97+
assert.strictEqual(Object.keys(difference).length, 1);
98+
assert.deepStrictEqual(difference, {});
99+
});
100+
101+
it('returns change when array item added', () => {
102+
const testObjectA = { arr: ['one', 'two'] };
103+
const testObjectB = { arr: ['one', 'two', 'three'] };
104+
const difference = diffler(testObjectA, testObjectB);
105+
assert.strictEqual(Object.keys(difference).length, 1);
106+
assert.deepStrictEqual(difference, { arr: { 2: { from: null, to: 'three' } } });
107+
});
108+
109+
it('returns change when array item removed', () => {
110+
const testObjectA = { arr: ['one', 'two', 'three'] };
111+
const testObjectB = { arr: ['one', 'two'] };
112+
const difference = diffler(testObjectA, testObjectB);
113+
assert.strictEqual(Object.keys(difference).length, 1);
114+
assert.deepStrictEqual(difference, { arr: { 2: { from: 'three', to: null } } });
115+
});
116+
117+
it('returns change and removal when array item removed from middle', () => {
118+
const testObjectA = { arr: ['one', 'two', 'three'] };
119+
const testObjectB = { arr: ['one', 'three'] };
120+
const difference = diffler(testObjectA, testObjectB);
121+
assert.strictEqual(Object.keys(difference).length, 1);
122+
assert.deepStrictEqual(difference, { arr: { 1: { from: 'two', to: 'three' }, 2: { from: 'three', to: null } } });
44123
});
45124
});
46125

@@ -58,11 +137,11 @@ describe('getDiff', () => {
58137
};
59138
const difference = diffler(testObjectA, testObjectB);
60139

61-
assert.equal(Object.keys(difference).length, 1);
62-
assert.equal(Object.keys(difference.weight.value).length, 2);
140+
assert.strictEqual(Object.keys(difference).length, 1);
141+
assert.strictEqual(Object.keys(difference.weight.value).length, 2);
63142

64-
assert.equal(difference.weight.value.from, 80);
65-
assert.equal(difference.weight.value.to, 79);
143+
assert.strictEqual(difference.weight.value.from, 80);
144+
assert.strictEqual(difference.weight.value.to, 79);
66145
});
67146

68147
it('should detect multiple nested property change', () => {
@@ -78,17 +157,17 @@ describe('getDiff', () => {
78157
};
79158
const difference = diffler(testObjectA, testObjectB);
80159

81-
assert.equal(Object.keys(difference).length, 2);
82-
assert.equal(Object.keys(difference.weight).length, 2);
160+
assert.strictEqual(Object.keys(difference).length, 2);
161+
assert.strictEqual(Object.keys(difference.weight).length, 2);
83162

84-
assert.equal(difference.age.from, 33);
85-
assert.equal(difference.age.to, 34);
163+
assert.strictEqual(difference.age.from, 33);
164+
assert.strictEqual(difference.age.to, 34);
86165

87-
assert.equal(difference.weight.value.from, 80);
88-
assert.equal(difference.weight.value.to, 12.4);
166+
assert.strictEqual(difference.weight.value.from, 80);
167+
assert.strictEqual(difference.weight.value.to, 12.4);
89168

90-
assert.equal(difference.weight.unit.from, 'kg');
91-
assert.equal(difference.weight.unit.to, 'stone');
169+
assert.strictEqual(difference.weight.unit.from, 'kg');
170+
assert.strictEqual(difference.weight.unit.to, 'stone');
92171
});
93172
});
94173

@@ -98,11 +177,11 @@ describe('getDiff', () => {
98177
const testObjectB = {};
99178
const difference = diffler(testObjectA, testObjectB);
100179

101-
assert.equal(Object.keys(difference).length, 1);
102-
assert.equal(Object.keys(difference.name).length, 2);
180+
assert.strictEqual(Object.keys(difference).length, 1);
181+
assert.strictEqual(Object.keys(difference.name).length, 2);
103182

104-
assert.equal(difference.name.from, 'gary');
105-
assert.equal(difference.name.to, null);
183+
assert.strictEqual(difference.name.from, 'gary');
184+
assert.strictEqual(difference.name.to, null);
106185
});
107186

108187
it('should detect a nested property removal as null', () => {
@@ -114,11 +193,11 @@ describe('getDiff', () => {
114193
const testObjectB = { name: 'gary', age: 33 };
115194
const difference = diffler(testObjectA, testObjectB);
116195

117-
assert.equal(Object.keys(difference).length, 1);
118-
assert.equal(Object.keys(difference.weight).length, 2);
196+
assert.strictEqual(Object.keys(difference).length, 1);
197+
assert.strictEqual(Object.keys(difference.weight).length, 2);
119198

120-
assert.deepEqual(difference.weight.from, { unit: 'kg', value: 80 });
121-
assert.equal(difference.weight.to, null);
199+
assert.deepStrictEqual(difference.weight.from, { unit: 'kg', value: 80 });
200+
assert.strictEqual(difference.weight.to, null);
122201
});
123202
});
124203
});

0 commit comments

Comments
 (0)