Skip to content

Commit a7a74c4

Browse files
committed
Added fixing CallOnParametersSetAsync
1 parent f7501e3 commit a7a74c4

File tree

2 files changed

+118
-2
lines changed

2 files changed

+118
-2
lines changed

src/Components/Components/src/ComponentBase.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,10 @@ private Task CallOnParametersSetAsync()
322322

323323
// We always call StateHasChanged here as we want to trigger a rerender after OnParametersSet and
324324
// the synchronous part of OnParametersSetAsync has run.
325-
StateHasChanged();
325+
if (task.Status != TaskStatus.Faulted)
326+
{
327+
StateHasChanged();
328+
}
326329

327330
return shouldAwaitTask ?
328331
CallStateHasChangedOnAsyncCompletion(task) :

src/Components/Components/test/ComponentBaseTest.cs

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ public async Task ErrorBoundaryHandlesOnInitializedAsyncReturnFaultedTask()
387387
builder.AddComponentParameter(1, nameof(TestErrorBoundary.ChildContent), (RenderFragment)(childBuilder =>
388388
{
389389
childBuilder.OpenComponent<TestComponentErrorBuildRenderTree>(0);
390+
childBuilder.AddComponentParameter(1, nameof(TestComponentErrorBuildRenderTree.FaultedTaskOnInitializedAsync), true);
390391
childBuilder.CloseComponent();
391392
}));
392393
builder.AddComponentReferenceCapture(2, inst => capturedBoundary = (TestErrorBoundary)inst);
@@ -403,6 +404,94 @@ public async Task ErrorBoundaryHandlesOnInitializedAsyncReturnFaultedTask()
403404
Assert.Equal(typeof(InvalidTimeZoneException), capturedBoundary!.ReceivedException.GetType());
404405
}
405406

407+
[Fact]
408+
public async Task ErrorBoundaryHandlesCallOnParametersSetAsyncReturnFaultedTask()
409+
{
410+
// Arrange
411+
var renderer = new TestRenderer();
412+
TestErrorBoundary capturedBoundary = null;
413+
414+
// Create root component that wraps the TestComponentErrorBuildRenderTree in an TestErrorBoundary
415+
var rootComponent = new TestComponent();
416+
rootComponent.ChildContent = builder =>
417+
{
418+
builder.OpenComponent<TestErrorBoundary>(0);
419+
builder.AddComponentParameter(1, nameof(TestErrorBoundary.ChildContent), (RenderFragment)(childBuilder =>
420+
{
421+
childBuilder.OpenComponent<TestComponentErrorBuildRenderTree>(0);
422+
childBuilder.AddComponentParameter(1, nameof(TestComponentErrorBuildRenderTree.FaultedTaskOnParametersSetAsync), true);
423+
childBuilder.CloseComponent();
424+
}));
425+
builder.AddComponentReferenceCapture(2, inst => capturedBoundary = (TestErrorBoundary)inst);
426+
builder.CloseComponent();
427+
};
428+
429+
// Act
430+
var rootComponentId = renderer.AssignRootComponentId(rootComponent);
431+
await renderer.RenderRootComponentAsync(rootComponentId);
432+
433+
// Assert
434+
Assert.NotNull(capturedBoundary);
435+
Assert.NotNull(capturedBoundary!.ReceivedException);
436+
Assert.Equal(typeof(InvalidTimeZoneException), capturedBoundary!.ReceivedException.GetType());
437+
}
438+
439+
[Fact]
440+
public async Task ComponentBaseDoesntRenderWhenOnInitializedAsyncFaultedTask()
441+
{
442+
// Arrange
443+
var renderer = new TestRenderer();
444+
renderer.ShouldHandleExceptions = true;
445+
TestComponentErrorBuildRenderTree testComponentErrorBuildRenderTree = null;
446+
447+
// Create root component that wraps the TestComponentErrorBuildRenderTree in an TestErrorBoundary
448+
var rootComponent = new TestComponent();
449+
rootComponent.ChildContent = builder =>
450+
{
451+
builder.OpenComponent<TestComponentErrorBuildRenderTree>(0);
452+
builder.AddComponentParameter(1, nameof(TestComponentErrorBuildRenderTree.FaultedTaskOnInitializedAsync), true);
453+
builder.AddComponentReferenceCapture(2, inst => testComponentErrorBuildRenderTree = (TestComponentErrorBuildRenderTree)inst);
454+
builder.CloseComponent();
455+
};
456+
457+
// Act
458+
var rootComponentId = renderer.AssignRootComponentId(rootComponent);
459+
await renderer.RenderRootComponentAsync(rootComponentId);
460+
461+
// Assert
462+
Assert.IsType<InvalidTimeZoneException>(renderer.HandledExceptions[0]);
463+
Assert.NotNull(testComponentErrorBuildRenderTree);
464+
Assert.Equal(0, testComponentErrorBuildRenderTree.StateHasChangedCalled);
465+
}
466+
467+
[Fact]
468+
public async Task ComponentBaseDoesntRenderWhenOnSetParametersSetAsyncFaultedTask()
469+
{
470+
// Arrange
471+
var renderer = new TestRenderer();
472+
renderer.ShouldHandleExceptions = true;
473+
TestComponentErrorBuildRenderTree testComponentErrorBuildRenderTree = null;
474+
475+
// Create root component that wraps the TestComponentErrorBuildRenderTree in an TestErrorBoundary
476+
var rootComponent = new TestComponent();
477+
rootComponent.ChildContent = builder =>
478+
{
479+
builder.OpenComponent<TestComponentErrorBuildRenderTree>(0);
480+
builder.AddComponentParameter(1, nameof(TestComponentErrorBuildRenderTree.FaultedTaskOnParametersSetAsync), true);
481+
builder.AddComponentReferenceCapture(2, inst => testComponentErrorBuildRenderTree = (TestComponentErrorBuildRenderTree)inst);
482+
builder.CloseComponent();
483+
};
484+
485+
// Act
486+
var rootComponentId = renderer.AssignRootComponentId(rootComponent);
487+
await renderer.RenderRootComponentAsync(rootComponentId);
488+
489+
// Assert
490+
Assert.IsType<InvalidTimeZoneException>(renderer.HandledExceptions[0]);
491+
Assert.NotNull(testComponentErrorBuildRenderTree);
492+
Assert.Equal(0, testComponentErrorBuildRenderTree.StateHasChangedCalled);
493+
}
494+
406495
[Fact]
407496
public async Task DoesNotRenderAfterOnParametersSetAsyncTaskIsCanceled()
408497
{
@@ -637,14 +726,38 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
637726

638727
private class TestComponentErrorBuildRenderTree : ComponentBase
639728
{
729+
[Parameter] public bool FaultedTaskOnInitializedAsync { get; set; } = false;
730+
[Parameter] public bool FaultedTaskOnParametersSetAsync { get; set; } = false;
731+
732+
public int StateHasChangedCalled { get; set; } = 0;
733+
734+
protected new void StateHasChanged()
735+
{
736+
StateHasChangedCalled++;
737+
base.StateHasChanged();
738+
}
739+
640740
protected override void BuildRenderTree(RenderTreeBuilder builder)
641741
{
642742
throw new InvalidOperationException("Error in BuildRenderTree");
643743
}
644744

645745
protected override Task OnInitializedAsync()
646746
{
647-
return Task.FromException(new InvalidTimeZoneException());
747+
if (FaultedTaskOnInitializedAsync)
748+
{
749+
return Task.FromException(new InvalidTimeZoneException());
750+
}
751+
return Task.CompletedTask;
752+
}
753+
754+
protected override Task OnParametersSetAsync()
755+
{
756+
if (FaultedTaskOnParametersSetAsync)
757+
{
758+
return Task.FromException(new InvalidTimeZoneException());
759+
}
760+
return Task.CompletedTask;
648761
}
649762
}
650763
}

0 commit comments

Comments
 (0)