@@ -436,6 +436,91 @@ public async Task ErrorBoundaryHandlesCallOnParametersSetAsyncReturnFaultedTask(
436436 Assert . Equal ( typeof ( InvalidTimeZoneException ) , capturedBoundary ! . ReceivedException . GetType ( ) ) ;
437437 }
438438
439+ [ Fact ]
440+ public void ErrorBoundaryStaysInTheErrorStateAfterRerender ( )
441+ {
442+ // Arrange
443+ var renderer = new TestRenderer ( ) ;
444+ TestErrorBoundary capturedBoundary = null ;
445+ var shouldThrow = true ;
446+ var rootComponent = new TestComponent ( ) ;
447+
448+ rootComponent . ChildContent = builder =>
449+ {
450+ builder . OpenComponent < TestErrorBoundary > ( 0 ) ;
451+ builder . AddAttribute ( 1 , nameof ( TestErrorBoundary . ChildContent ) , ( RenderFragment ) ( builder2 =>
452+ {
453+ builder2 . OpenComponent < TestComponentErrorBuildRenderTree > ( 1 ) ;
454+ builder2 . AddAttribute ( 2 , nameof ( TestComponentErrorBuildRenderTree . ThrowDuringRender ) , shouldThrow ) ;
455+ builder2 . CloseComponent ( ) ;
456+ } ) ) ;
457+ builder . AddComponentReferenceCapture ( 2 , obj => capturedBoundary = ( TestErrorBoundary ) obj ) ;
458+ builder . CloseComponent ( ) ;
459+ } ;
460+
461+ // Render first time
462+ var rootComponentId = renderer . AssignRootComponentId ( rootComponent ) ;
463+ renderer . RenderRootComponent ( rootComponentId ) ;
464+
465+ Assert . NotNull ( capturedBoundary ) ;
466+ Assert . NotNull ( capturedBoundary . ReceivedException ) ;
467+ var errorBoundaryId = renderer . Batches . Single ( ) . GetComponentFrames < TestErrorBoundary > ( ) . Single ( ) . ComponentId ;
468+ var frames = renderer . GetCurrentRenderTreeFrames ( errorBoundaryId ) . AsEnumerable ( ) ;
469+ Assert . Collection ( frames ,
470+ frame => AssertFrame . Element ( frame , "div" , subtreeLength : 2 ) ,
471+ frame => AssertFrame . Attribute ( frame , "class" , "blazor-error-boundary" ) ) ;
472+
473+ // Render second time with no error
474+ shouldThrow = false ;
475+ renderer . RenderRootComponent ( rootComponentId ) ;
476+
477+ Assert . NotNull ( capturedBoundary ) ;
478+ Assert . NotNull ( capturedBoundary . ReceivedException ) ;
479+ frames = renderer . GetCurrentRenderTreeFrames ( errorBoundaryId ) . AsEnumerable ( ) ;
480+ Assert . Collection ( frames ,
481+ frame => AssertFrame . Element ( frame , "div" , subtreeLength : 2 ) ,
482+ frame => AssertFrame . Attribute ( frame , "class" , "blazor-error-boundary" ) ) ;
483+ }
484+
485+ [ Fact ]
486+ public async Task ErrorBoundaryStaysInTheErrorStateAfterRerenderInTheSameBatch ( )
487+ {
488+ // Arrange
489+ var renderer = new TestRenderer ( ) ;
490+ TestErrorBoundary capturedBoundary = null ;
491+ var shouldThrow = true ;
492+ var rootComponent = new TestComponent ( ) ;
493+
494+ rootComponent . ChildContent = builder =>
495+ {
496+ builder . OpenComponent < TestErrorBoundary > ( 0 ) ;
497+ builder . AddAttribute ( 1 , nameof ( TestErrorBoundary . ChildContent ) , ( RenderFragment ) ( builder2 =>
498+ {
499+ builder2 . OpenComponent < TestComponentErrorBuildRenderTree > ( 1 ) ;
500+ builder2 . AddAttribute ( 2 , nameof ( TestComponentErrorBuildRenderTree . ThrowDuringRender ) , shouldThrow ) ;
501+ builder2 . CloseComponent ( ) ;
502+
503+ builder2 . OpenComponent < TestComponentErrorBuildRenderTree > ( 2 ) ;
504+ builder2 . AddAttribute ( 3 , nameof ( TestComponentErrorBuildRenderTree . ThrowDuringRender ) , shouldThrow ) ;
505+ builder2 . CloseComponent ( ) ;
506+ } ) ) ;
507+ builder . AddComponentReferenceCapture ( 2 , obj => capturedBoundary = ( TestErrorBoundary ) obj ) ;
508+ builder . CloseComponent ( ) ;
509+ } ;
510+
511+ // Render first time
512+ var rootComponentId = renderer . AssignRootComponentId ( rootComponent ) ;
513+ renderer . RenderRootComponent ( rootComponentId ) ;
514+
515+ Assert . NotNull ( capturedBoundary ) ;
516+ Assert . NotNull ( capturedBoundary . ReceivedException ) ;
517+ var errorBoundaryId = renderer . Batches . Single ( ) . GetComponentFrames < TestErrorBoundary > ( ) . Single ( ) . ComponentId ;
518+ var frames = renderer . GetCurrentRenderTreeFrames ( errorBoundaryId ) . AsEnumerable ( ) ;
519+ Assert . Collection ( frames ,
520+ frame => AssertFrame . Element ( frame , "div" , subtreeLength : 2 ) ,
521+ frame => AssertFrame . Attribute ( frame , "class" , "blazor-error-boundary" ) ) ;
522+ }
523+
439524 [ Fact ]
440525 public async Task ComponentBaseDoesntRenderWhenOnInitializedAsyncFaultedTask ( )
441526 {
@@ -729,6 +814,8 @@ private class TestComponentErrorBuildRenderTree : ComponentBase
729814 [ Parameter ] public bool FaultedTaskOnInitializedAsync { get ; set ; } = false ;
730815 [ Parameter ] public bool FaultedTaskOnParametersSetAsync { get ; set ; } = false ;
731816
817+ [ Parameter ] public bool ThrowDuringRender { get ; set ; } = true ;
818+
732819 public int StateHasChangedCalled { get ; set ; } = 0 ;
733820
734821 protected new void StateHasChanged ( )
@@ -739,7 +826,10 @@ private class TestComponentErrorBuildRenderTree : ComponentBase
739826
740827 protected override void BuildRenderTree ( RenderTreeBuilder builder )
741828 {
742- throw new InvalidOperationException ( "Error in BuildRenderTree" ) ;
829+ if ( ThrowDuringRender )
830+ {
831+ throw new InvalidOperationException ( "Error in BuildRenderTree" ) ;
832+ }
743833 }
744834
745835 protected override Task OnInitializedAsync ( )
0 commit comments