@@ -205,6 +205,8 @@ describe('fastMerge', () => {
205205 [ 'a number' , 1000 ] ,
206206 [ 'a boolean' , true ] ,
207207 [ 'an array' , [ ] ] ,
208+ [ 'null' , null ] ,
209+ [ 'undefined' , undefined ] ,
208210 ] ) ( 'should replace %s with an object' , ( _label , data ) => {
209211 const result = utils . fastMerge < unknown > ( data , testObject ) ;
210212 expect ( result . result ) . toEqual ( testObject ) ;
@@ -274,6 +276,32 @@ describe('fastMerge', () => {
274276 const result = utils . fastMerge ( target , source ) ;
275277 expect ( result . result ) . toBe ( target ) ;
276278 } ) ;
279+
280+ it ( 'should skip undefined source values and preserve target reference' , ( ) => {
281+ const target = { a : 1 , b : 2 } ;
282+ const source = { a : undefined } ;
283+ const result = utils . fastMerge ( target , source ) ;
284+ expect ( result . result ) . toBe ( target ) ;
285+ } ) ;
286+
287+ it ( 'should preserve references through deeply nested merges (3+ levels)' , ( ) => {
288+ const deepNested = { x : 1 } ;
289+ const target = { a : { b : { c : deepNested } } , d : 'hello' } ;
290+ const source = { d : 'hello' } ;
291+ const result = utils . fastMerge < GenericDeepRecord > ( target , source ) ;
292+ expect ( result . result ) . toBe ( target ) ;
293+ expect ( result . result . a . b . c ) . toBe ( deepNested ) ;
294+ } ) ;
295+
296+ it ( 'should return a new reference at each changed level in a deep merge' , ( ) => {
297+ const target = { a : { b : { c : 1 , d : 2 } } , e : 'unchanged' } ;
298+ const source = { a : { b : { c : 99 } } } ;
299+ const result = utils . fastMerge < GenericDeepRecord > ( target , source ) ;
300+ expect ( result . result ) . not . toBe ( target ) ;
301+ expect ( result . result . a ) . not . toBe ( target . a ) ;
302+ expect ( result . result . a . b ) . not . toBe ( target . a . b ) ;
303+ expect ( result . result . a . b ) . toEqual ( { c : 99 , d : 2 } ) ;
304+ } ) ;
277305 } ) ;
278306
279307 describe ( 'removeNestedNullValues' , ( ) => {
@@ -333,5 +361,26 @@ describe('fastMerge', () => {
333361 expect ( result ) . toBe ( value ) ;
334362 expect ( ( result as Record < string , unknown > ) . items ) . toBe ( arr ) ;
335363 } ) ;
364+
365+ it ( 'should pass through primitives unchanged' , ( ) => {
366+ expect ( utils . removeNestedNullValues ( 'hello' ) ) . toBe ( 'hello' ) ;
367+ expect ( utils . removeNestedNullValues ( 42 ) ) . toBe ( 42 ) ;
368+ expect ( utils . removeNestedNullValues ( true ) ) . toBe ( true ) ;
369+ expect ( utils . removeNestedNullValues ( null ) ) . toBe ( null ) ;
370+ expect ( utils . removeNestedNullValues ( undefined ) ) . toBe ( undefined ) ;
371+ } ) ;
372+
373+ it ( 'should return the same reference for an empty object' , ( ) => {
374+ const value = { } ;
375+ const result = utils . removeNestedNullValues ( value ) ;
376+ expect ( result ) . toBe ( value ) ;
377+ } ) ;
378+
379+ it ( 'should return a new empty object when all properties are null/undefined' , ( ) => {
380+ const value = { a : null , b : undefined , c : null } ;
381+ const result = utils . removeNestedNullValues ( value ) ;
382+ expect ( result ) . not . toBe ( value ) ;
383+ expect ( result ) . toEqual ( { } ) ;
384+ } ) ;
336385 } ) ;
337386} ) ;
0 commit comments