From 31c5ff5f09d59b11ada77e238ab70137da31c9cd Mon Sep 17 00:00:00 2001 From: Giulio Caprino Date: Sat, 22 May 2021 10:53:41 +0100 Subject: [PATCH] fix(merge): ensure undefined is assigned when merging partial mock (#748) Co-authored-by: Vittorio Guerriero --- src/merge/merge.ts | 31 ++++++++++++++----- .../create-mock-values.test.ts | 22 +++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/merge/merge.ts b/src/merge/merge.ts index 40f857493..d6ae00f1c 100644 --- a/src/merge/merge.ts +++ b/src/merge/merge.ts @@ -1,16 +1,33 @@ -import { mergeWith, isObject } from 'lodash-es'; +import { mergeWith, isObject, set } from 'lodash-es'; import { ɵMarker as Marker } from 'ts-auto-mock/extension'; import { PartialDeep } from '../partial/partial'; export class Merge { public static merge(a: T, b: PartialDeep): T { - return mergeWith(a, b, (objValue: unknown, srcValue: unknown) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - if (isObject(srcValue) && srcValue[Marker.instance.get()]) { - return srcValue; + return mergeWith( + a, + b, + ( + objValue: unknown, + srcValue: unknown, + oneLevelPath: string, + objContainer: object, + srcContainer: object + ) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (isObject(srcValue) && srcValue[Marker.instance.get()]) { + return srcValue; + } + + if ( + srcContainer.hasOwnProperty(oneLevelPath) && + srcValue === undefined + ) { + set(objContainer, [oneLevelPath], undefined); + } } - }); + ); } public static mergeIterator( diff --git a/test/frameworkContext/create-mock-values.test.ts b/test/frameworkContext/create-mock-values.test.ts index 519008f82..7170e4231 100644 --- a/test/frameworkContext/create-mock-values.test.ts +++ b/test/frameworkContext/create-mock-values.test.ts @@ -38,4 +38,26 @@ describe('create-mock-values', () => { expect().nothing(); }); + + it('should replace values when providing undefined', () => { + interface InterfaceWithValues { + property: { + a: 123; + c: () => void; + }; + method(): void; + } + + const properties: InterfaceWithValues = createMock({ + property: { + a: undefined, + }, + }); + + properties.method(); + properties.property.c(); + expect(properties.method).toHaveBeenCalled(); + expect(properties.property.a).toBeUndefined(); + expect(properties.property.c).toHaveBeenCalled(); + }); });