fix(utils): deepMerge failing to correctly merge basic data types (#2872)
This commit is contained in:
parent
a0fdceeae7
commit
7535db377f
|
|
@ -4,6 +4,30 @@ import { describe, expect, test } from 'vitest';
|
||||||
import { deepMerge } from '@/utils';
|
import { deepMerge } from '@/utils';
|
||||||
|
|
||||||
describe('deepMerge function', () => {
|
describe('deepMerge function', () => {
|
||||||
|
test('should correctly merge basic data types', () => {
|
||||||
|
const source = { a: 1, b: 2, c: null };
|
||||||
|
const target = {
|
||||||
|
a: 2,
|
||||||
|
b: undefined,
|
||||||
|
c: 3,
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
a: 2,
|
||||||
|
b: 2,
|
||||||
|
c: 3,
|
||||||
|
};
|
||||||
|
expect(deepMerge(source, target)).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return the same date if only 1 is passed', () => {
|
||||||
|
const foo = new Date();
|
||||||
|
const merged = deepMerge(foo, null);
|
||||||
|
const merged2 = deepMerge(undefined, foo);
|
||||||
|
expect(merged).toStrictEqual(foo);
|
||||||
|
expect(merged2).toStrictEqual(foo);
|
||||||
|
expect(merged).toStrictEqual(merged2);
|
||||||
|
});
|
||||||
|
|
||||||
test('should merge two objects recursively', () => {
|
test('should merge two objects recursively', () => {
|
||||||
const source = {
|
const source = {
|
||||||
a: { b: { c: 1 }, d: [1, 2] },
|
a: { b: { c: 1 }, d: [1, 2] },
|
||||||
|
|
@ -15,6 +39,7 @@ describe('deepMerge function', () => {
|
||||||
too: [1, 2, 3],
|
too: [1, 2, 3],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
r: { a: 1 },
|
||||||
};
|
};
|
||||||
const target = {
|
const target = {
|
||||||
a: { b: { d: [3] } },
|
a: { b: { d: [3] } },
|
||||||
|
|
@ -30,6 +55,7 @@ describe('deepMerge function', () => {
|
||||||
really: 'yes',
|
really: 'yes',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
r: { a: 2 },
|
||||||
};
|
};
|
||||||
const expected = {
|
const expected = {
|
||||||
a: { b: { c: 1, d: [3] }, d: [1, 2] },
|
a: { b: { c: 1, d: [3] }, d: [1, 2] },
|
||||||
|
|
@ -48,8 +74,9 @@ describe('deepMerge function', () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
qu: 5,
|
qu: 5,
|
||||||
|
r: { a: 2 },
|
||||||
};
|
};
|
||||||
expect(deepMerge(source, target)).toEqual(expected);
|
expect(deepMerge(source, target)).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should replace arrays by default', () => {
|
test('should replace arrays by default', () => {
|
||||||
|
|
@ -65,7 +92,7 @@ describe('deepMerge function', () => {
|
||||||
a: { b: { d: [3] } },
|
a: { b: { d: [3] } },
|
||||||
e: [3],
|
e: [3],
|
||||||
};
|
};
|
||||||
expect(deepMerge(source, target)).toEqual(expected);
|
expect(deepMerge(source, target)).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should union arrays using mergeArrays = 'union'", () => {
|
test("should union arrays using mergeArrays = 'union'", () => {
|
||||||
|
|
@ -75,13 +102,13 @@ describe('deepMerge function', () => {
|
||||||
};
|
};
|
||||||
const target = {
|
const target = {
|
||||||
a: { b: { d: [2, 3] } },
|
a: { b: { d: [2, 3] } },
|
||||||
e: [3],
|
e: [1, 3],
|
||||||
};
|
};
|
||||||
const expected = {
|
const expected = {
|
||||||
a: { b: { d: [1, 2, 3] } },
|
a: { b: { d: [1, 2, 3] } },
|
||||||
e: [1, 2, 3],
|
e: [1, 2, 3],
|
||||||
};
|
};
|
||||||
expect(deepMerge(source, target, 'union')).toEqual(expected);
|
expect(deepMerge(source, target, 'union')).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should intersect arrays using mergeArrays = 'intersection'", () => {
|
test("should intersect arrays using mergeArrays = 'intersection'", () => {
|
||||||
|
|
@ -97,7 +124,7 @@ describe('deepMerge function', () => {
|
||||||
a: { b: { d: [2] } },
|
a: { b: { d: [2] } },
|
||||||
e: [],
|
e: [],
|
||||||
};
|
};
|
||||||
expect(deepMerge(source, target, 'intersection')).toEqual(expected);
|
expect(deepMerge(source, target, 'intersection')).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("should concatenate arrays using mergeArrays = 'concat'", () => {
|
test("should concatenate arrays using mergeArrays = 'concat'", () => {
|
||||||
|
|
@ -113,6 +140,6 @@ describe('deepMerge function', () => {
|
||||||
a: { b: { d: [1, 2, 2, 3] } },
|
a: { b: { d: [1, 2, 2, 3] } },
|
||||||
e: [1, 2, 3],
|
e: [1, 2, 3],
|
||||||
};
|
};
|
||||||
expect(deepMerge(source, target, 'concat')).toEqual(expected);
|
expect(deepMerge(source, target, 'concat')).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -58,27 +58,26 @@ export function deepMerge<T extends object | null | undefined, U extends object
|
||||||
if (!source) {
|
if (!source) {
|
||||||
return target as T & U;
|
return target as T & U;
|
||||||
}
|
}
|
||||||
if (isArray(target) && isArray(source)) {
|
return mergeWith({}, source, target, (sourceValue, targetValue) => {
|
||||||
switch (mergeArrays) {
|
if (isArray(targetValue) && isArray(sourceValue)) {
|
||||||
case 'union':
|
switch (mergeArrays) {
|
||||||
return unionWith(target, source, isEqual) as T & U;
|
case 'union':
|
||||||
case 'intersection':
|
return unionWith(sourceValue, targetValue, isEqual);
|
||||||
return intersectionWith(target, source, isEqual) as T & U;
|
case 'intersection':
|
||||||
case 'concat':
|
return intersectionWith(sourceValue, targetValue, isEqual);
|
||||||
return target.concat(source) as T & U;
|
case 'concat':
|
||||||
case 'replace':
|
return sourceValue.concat(targetValue);
|
||||||
return source as T & U;
|
case 'replace':
|
||||||
default:
|
return targetValue;
|
||||||
throw new Error(`Unknown merge array strategy: ${mergeArrays}`);
|
default:
|
||||||
|
throw new Error(`Unknown merge array strategy: ${mergeArrays as string}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (isObject(targetValue) && isObject(sourceValue)) {
|
||||||
if (isObject(target) && isObject(source)) {
|
return deepMerge(sourceValue, targetValue, mergeArrays);
|
||||||
return mergeWith({}, target, source, (targetValue, sourceValue) => {
|
}
|
||||||
return deepMerge(targetValue, sourceValue, mergeArrays);
|
return undefined;
|
||||||
}) as T & U;
|
});
|
||||||
}
|
|
||||||
return source as T & U;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openWindow(
|
export function openWindow(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue