@@ -177,4 +177,318 @@ public void AppendErrors_ShouldLogWhenCreatedWithNoLogger()
177177 // Assert
178178 Assert . Equal ( 1 , testLogger . LogMessages . Count ) ;
179179 }
180+
181+ [ Fact ]
182+ public void AppendErrors_NonGenericSource_To_GenericTarget_Retains_Generic_Type_And_MergesErrors ( )
183+ {
184+ // Arrange
185+ var source = new OperationResult ( ) ;
186+ source . AppendError ( "E1" , 101 , LogLevel . Warning , "D1" ) ;
187+
188+ var target = new OperationResult < string > ( ) ;
189+ target . AppendError ( "E0" , 100 , LogLevel . Information , "D0" ) ;
190+
191+ // Act
192+ var returned = target . AppendErrors ( source ) ;
193+
194+ // Assert
195+ Assert . Same ( target , returned ) ;
196+ Assert . True ( target . Fail ) ;
197+ Assert . Equal ( 2 , target . Errors . Count ) ;
198+ Assert . NotNull ( target . Errors . Single ( e => e is { Code : 100 , Message : "E0" } ) ) ;
199+ Assert . NotNull ( target . Errors . Single ( e => e is { Code : 101 , Message : "E1" } ) ) ;
200+ }
201+
202+ [ Fact ]
203+ public void AppendErrors_GenericSource_To_GenericTarget_Retains_Generic_Type_And_MergesErrors ( )
204+ {
205+ // Arrange
206+ var source = new OperationResult < double > ( ) ;
207+ source . AppendError ( "E1" , 101 , LogLevel . Warning , "D1" ) ;
208+
209+ var target = new OperationResult < string > ( ) ;
210+ target . AppendError ( "E0" , 100 , LogLevel . Information , "D0" ) ;
211+
212+ // Act
213+ var returned = target . AppendErrors ( source ) ;
214+
215+ // Assert
216+ Assert . Same ( target , returned ) ;
217+ Assert . True ( target . Fail ) ;
218+ Assert . Equal ( 2 , target . Errors . Count ) ;
219+ Assert . NotNull ( target . Errors . Single ( e => e is { Code : 100 , Message : "E0" } ) ) ;
220+ Assert . NotNull ( target . Errors . Single ( e => e is { Code : 101 , Message : "E1" } ) ) ;
221+ }
222+
223+ [ Fact ]
224+ public void AppendErrors_WithNullSource_On_NonGenericTarget_Returns_Same_Instance_And_NoChange ( )
225+ {
226+ // Arrange
227+ var target = new OperationResult ( ) ;
228+ target . AppendError ( "E0" , 100 , LogLevel . Information , "D0" ) ;
229+ var beforeCount = target . Errors . Count ;
230+
231+ // Act
232+ var returned = target . AppendErrors ( null ) ;
233+
234+ // Assert
235+ Assert . Same ( target , returned ) ;
236+ Assert . Equal ( beforeCount , target . Errors . Count ) ;
237+ }
238+
239+ [ Fact ]
240+ public void AppendErrors_WithNullSource_On_GenericTarget_Returns_Same_Instance_And_NoChange ( )
241+ {
242+ // Arrange
243+ var target = new OperationResult < object > ( ) ;
244+ target . AppendError ( "E0" , 100 , LogLevel . Information , "D0" ) ;
245+ var beforeCount = target . Errors . Count ;
246+
247+ // Act
248+ var returned = target . AppendErrors ( ( OperationResult ) null ) ;
249+
250+ // Assert
251+ Assert . Same ( target , returned ) ;
252+ Assert . Equal ( beforeCount , target . Errors . Count ) ;
253+ }
254+
255+ [ Fact ]
256+ public void AppendErrors_PreservesResultObject_WhenMergingErrors ( )
257+ {
258+ // Arrange
259+ var originalResult = new { Id = 42 , Name = "Test" } ;
260+ var target = new OperationResult < object > ( originalResult ) ;
261+
262+ var source = new OperationResult < int > ( ) ;
263+ source . AppendError ( "Source error" , 500 ) ;
264+
265+ // Act
266+ var returned = target . AppendErrors ( source ) ;
267+
268+ // Assert
269+ Assert . Same ( target , returned ) ;
270+ Assert . Same ( originalResult , target . ResultObject ) ;
271+ Assert . Single ( target . Errors ) ;
272+ Assert . True ( target . Fail ) ;
273+ }
274+
275+ [ Fact ]
276+ public void AppendErrors_MaintainsFluentChaining_WithGenericType ( )
277+ {
278+ // Arrange
279+ var source1 = new OperationResult < double > ( ) ;
280+ source1 . AppendError ( "E1" , 1 ) ;
281+
282+ var source2 = new OperationResult < int > ( ) ;
283+ source2 . AppendError ( "E2" , 2 ) ;
284+
285+ var target = new OperationResult < string > ( ) ;
286+
287+ // Act - Chain multiple AppendErrors calls
288+ var returned = target
289+ . AppendErrors ( source1 )
290+ . AppendErrors ( source2 )
291+ . AppendError ( "E3" , 3 ) ;
292+
293+ // Assert
294+ Assert . Same ( target , returned ) ;
295+ Assert . IsType < OperationResult < string > > ( returned ) ;
296+ Assert . Equal ( 3 , target . Errors . Count ) ;
297+ }
298+
299+ [ Fact ]
300+ public void AppendErrors_PreservesInitialException_FromSource ( )
301+ {
302+ // Arrange
303+ var sourceException = new InvalidOperationException ( "Source exception" ) ;
304+ var source = new OperationResult < int > ( ) ;
305+ source . AppendException ( sourceException , 999 ) ;
306+
307+ var target = new OperationResult < double > ( ) ;
308+
309+ // Act
310+ target . AppendErrors ( source ) ;
311+
312+ // Assert
313+ Assert . Null ( target . InitialException ) ; // Target doesn't inherit source's InitialException
314+ Assert . Single ( target . Errors ) ;
315+ Assert . Contains ( sourceException . ToString ( ) , target . Errors [ 0 ] . Message ) ;
316+ }
317+
318+ [ Fact ]
319+ public void AppendErrors_HandlesSourceWithMultipleErrorTypes ( )
320+ {
321+ // Arrange
322+ var source = new OperationResult < List < string > > ( ) ;
323+ source . AppendError ( "Standard error" , 100 ) ;
324+ source . AppendException ( new ArgumentNullException ( "param" ) , 200 ) ;
325+ source . AppendError ( "Another error" , 300 , LogLevel . Critical , "Critical details" ) ;
326+
327+ var target = new OperationResult < int > ( ) ;
328+
329+ // Act
330+ target . AppendErrors ( source ) ;
331+
332+ // Assert
333+ Assert . Equal ( 3 , target . Errors . Count ) ;
334+ Assert . NotNull ( target . Errors . Single ( e => e . Code == 100 ) ) ;
335+ Assert . NotNull ( target . Errors . Single ( e => e . Code == 200 ) ) ;
336+ Assert . NotNull ( target . Errors . Single ( e => e is { Code : 300 , Details : "Critical details" } ) ) ;
337+ }
338+
339+ [ Fact ]
340+ public void AppendErrors_MergesSuccessMessages_AreNotTransferred ( )
341+ {
342+ // Arrange
343+ var source = new OperationResult < double > ( ) ;
344+ source . AddSuccessMessage ( "Success from source" ) ;
345+ source . AppendError ( "But has error" , 1 ) ;
346+
347+ var target = new OperationResult < string > ( ) ;
348+ target . AddSuccessMessage ( "Success from target" ) ;
349+
350+ // Act
351+ target . AppendErrors ( source ) ;
352+
353+ // Assert - SuccessMessages are not merged in AppendErrors
354+ Assert . Single ( target . SuccessMessages ) ;
355+ Assert . Contains ( "Success from target" , target . SuccessMessages ) ;
356+ }
357+
358+ [ Fact ]
359+ public void AppendErrors_EmptySource_DoesNotAffectTarget ( )
360+ {
361+ // Arrange
362+ var source = new OperationResult < double > ( ) ;
363+ var target = new OperationResult < string > ( ) ;
364+ target . AppendError ( "Target error" , 1 ) ;
365+
366+ // Act
367+ var returned = target . AppendErrors ( source ) ;
368+
369+ // Assert
370+ Assert . Same ( target , returned ) ;
371+ Assert . Single ( target . Errors ) ;
372+ Assert . True ( target . Fail ) ;
373+ }
374+
375+ [ Fact ]
376+ public void AppendErrors_EmptyTarget_AcceptsSourceErrors ( )
377+ {
378+ // Arrange
379+ var source = new OperationResult < object > ( ) ;
380+ source . AppendError ( "Source error" , 100 ) ;
381+
382+ var target = new OperationResult < string > ( ) ;
383+
384+ // Act
385+ target . AppendErrors ( source ) ;
386+
387+ // Assert
388+ Assert . True ( target . Fail ) ;
389+ Assert . Single ( target . Errors ) ;
390+ Assert . Equal ( "Source error" , target . Errors [ 0 ] . Message ) ;
391+ }
392+
393+ [ Fact ]
394+ public void AppendErrors_WithDifferentGenericTypes_MaintainsTargetType ( )
395+ {
396+ // Arrange
397+ var sourceInt = new OperationResult < int > { ResultObject = 42 } ;
398+ sourceInt . AppendError ( "Int error" , 1 ) ;
399+
400+ var targetString = new OperationResult < string > { ResultObject = "test" } ;
401+
402+ // Act
403+ var returned = targetString . AppendErrors ( sourceInt ) ;
404+
405+ // Assert
406+ Assert . IsType < OperationResult < string > > ( returned ) ;
407+ Assert . Equal ( "test" , targetString . ResultObject ) ;
408+ Assert . Single ( targetString . Errors ) ;
409+ }
410+
411+ [ Fact ]
412+ public void AppendErrors_ChainedCalls_AccumulatesAllErrors ( )
413+ {
414+ // Arrange
415+ var s1 = new OperationResult ( ) ;
416+ s1 . AppendError ( "E1" , 1 ) ;
417+
418+ var s2 = new OperationResult < int > ( ) ;
419+ s2 . AppendError ( "E2" , 2 ) ;
420+
421+ var s3 = new OperationResult ( ) ;
422+ s3 . AppendError ( "E3" , 3 ) ;
423+
424+ var target = new OperationResult < string > ( ) ;
425+
426+ // Act
427+ target . AppendErrors ( s1 ) . AppendErrors ( s2 ) . AppendErrors ( s3 ) ;
428+
429+ // Assert
430+ Assert . Equal ( 3 , target . Errors . Count ) ;
431+ Assert . Contains ( target . Errors , e => e . Code == 1 ) ;
432+ Assert . Contains ( target . Errors , e => e . Code == 2 ) ;
433+ Assert . Contains ( target . Errors , e => e . Code == 3 ) ;
434+ }
435+
436+ [ Fact ]
437+ public void AppendErrors_WithComplexGenericType_PreservesTypeIntegrity ( )
438+ {
439+ // Arrange
440+ var complexObject = new Dictionary < string , List < int > >
441+ {
442+ [ "key1" ] = [ 1 , 2 , 3 ]
443+ } ;
444+
445+ var target = new OperationResult < Dictionary < string , List < int > > > ( complexObject ) ;
446+ var source = new OperationResult < int > ( ) ;
447+ source . AppendError ( "Complex type error" , 999 ) ;
448+
449+ // Act
450+ var returned = target . AppendErrors ( source ) ;
451+
452+ // Assert
453+ Assert . Same ( complexObject , target . ResultObject ) ;
454+ Assert . IsType < OperationResult < Dictionary < string , List < int > > > > ( returned ) ;
455+ Assert . Single ( target . Errors ) ;
456+ }
457+
458+ [ Fact ]
459+ public void AppendErrors_ReturnsCorrectType_AfterMultipleOperations ( )
460+ {
461+ // Arrange
462+ var target = new OperationResult < int > { ResultObject = 100 } ;
463+ var source1 = new OperationResult < double > ( ) ;
464+ source1 . AppendError ( "E1" , 1 ) ;
465+
466+ // Act
467+ var step1 = target . AppendErrors ( source1 ) ;
468+ var step2 = step1 . AppendError ( "E2" , 2 ) ;
469+ var step3 = step2 . AppendException ( new Exception ( "E3" ) , 3 ) ;
470+
471+ // Assert
472+ Assert . IsType < OperationResult < int > > ( step1 ) ;
473+ Assert . IsType < OperationResult < int > > ( step2 ) ;
474+ Assert . IsType < OperationResult < int > > ( step3 ) ;
475+ Assert . Same ( target , step3 ) ;
476+ Assert . Equal ( 3 , target . Errors . Count ) ;
477+ }
478+
479+ [ Fact ]
480+ public void AppendErrors_GenericTarget_ShouldLogWhenCreatedWithALogger ( )
481+ {
482+ // Arrange
483+ var testLogger = new TestLogger ( ) ;
484+ var operationResultNoLogger = new OperationResult ( ) ;
485+ var operationResultWithLogger = new OperationResult < string > ( testLogger ) ;
486+
487+ // Act
488+ operationResultNoLogger . AppendError ( "test" ) ;
489+ operationResultWithLogger . AppendErrors ( operationResultNoLogger ) ;
490+
491+ // Assert
492+ Assert . Single ( testLogger . LogMessages ) ;
493+ }
180494}
0 commit comments