Fix comparison for arrays (#208171)

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.
This commit is contained in:
Joe Reuter 2025-01-24 16:05:06 +01:00 committed by GitHub
parent f0eb5d6957
commit 938f471781
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 48 additions and 0 deletions

View file

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

View file

@ -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.
@ -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];
}