Skip to content

Commit

Permalink
Fix comparison for arrays (elastic#208171)
Browse files Browse the repository at this point in the history
The comparison helper is not considering arrays - this means when
comparing two objects with arrays, it will always find a diff because to
the `!==` operator, the arrays are not the same:
```ts
calculateObjectDiff(
 { alpha: [1, 2, 3], beta: [4, 5, 6] },
 { alpha: [1, 2, 3], beta: [4, 5, 6] })
```

This PR fixes this by recursing into each element of the array.
  • Loading branch information
flash1293 authored Jan 24, 2025
1 parent f0eb5d6 commit 938f471
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,34 @@ describe('calculateObjectDiff', () => {
expect(removed).toEqual({});
expect(updated).toEqual({});
});

it('should handle array fields correctly', () => {
const { added, removed, updated } = calculateObjectDiff(
{ alpha: [1, 2, 3], beta: [4, 5, 6] },
{ alpha: [1, 2, 3], beta: [4, 5, 7] }
);
expect(added).toEqual({});
expect(removed).toEqual({});
expect(updated).toEqual({ beta: [undefined, undefined, 7] });
});

it('should detect added and removed array fields', () => {
const { added, removed, updated } = calculateObjectDiff(
{ alpha: [1, 2, 3] },
{ beta: [4, 5, 6] }
);
expect(added).toEqual({ beta: [4, 5, 6] });
expect(removed).toEqual({ alpha: [1, 2, 3] });
expect(updated).toEqual({});
});

it('should handle arrays containing objects correctly', () => {
const { added, removed, updated } = calculateObjectDiff(
{ alpha: [{ beta: 1 }, { gamma: 2 }] },
{ alpha: [{ beta: 1 }, { gamma: 3 }] }
);
expect(added).toEqual({});
expect(removed).toEqual({});
expect(updated).toEqual({ alpha: [{}, { gamma: 3 }] });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ interface ObjectDiffResult<TBase, TCompare> {
};
}

function isAllUndefined(obj: unknown): boolean {
return Array.isArray(obj) && obj.every((value) => value === undefined);
}

/**
* Compares two JSON objects and calculates the added and removed properties, including nested properties.
* @param oldObj - The base object.
Expand Down Expand Up @@ -66,6 +70,20 @@ export function calculateObjectDiff<TBase extends Obj, TCompare extends Obj>(
);
if (isEmpty(addedMap[key])) delete addedMap[key];
if (isEmpty(removedMap[key])) delete removedMap[key];
} else if (Array.isArray(base[key]) && Array.isArray(compare[key])) {
addedMap[key] = [];
removedMap[key] = [];
updatedMap[key] = [];
diffRecursive(
base[key] as Obj,
compare[key] as Obj,
addedMap[key] as Obj,
removedMap[key] as Obj,
updatedMap[key] as Obj
);
if (isAllUndefined(addedMap[key])) delete addedMap[key];
if (isAllUndefined(removedMap[key])) delete removedMap[key];
if (isAllUndefined(updatedMap[key])) delete updatedMap[key];
} else if (base[key] !== compare[key]) {
updatedMap[key] = compare[key];
}
Expand Down

0 comments on commit 938f471

Please sign in to comment.