diff --git a/src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs b/src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs index 5ad06a390cdf..33e52fa0ed57 100644 --- a/src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs +++ b/src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.cs @@ -183,7 +183,8 @@ protected override void AddPendingTask(ComponentState? componentState, Task task base.AddPendingTask(componentState, task); } - private void SignalRendererToFinishRendering() + // For testing purposes only + internal void SignalRendererToFinishRendering() { // sets a deferred stop on the renderer, which will have an effect after the current batch is completed _rendererIsStopped = true; diff --git a/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs b/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs index bfb82e50d284..ac787b76bfe5 100644 --- a/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs +++ b/src/Components/Endpoints/test/EndpointHtmlRendererTest.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Components.Infrastructure; using Microsoft.AspNetCore.Components.Reflection; using Microsoft.AspNetCore.Components.Rendering; +using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.DataProtection; @@ -47,18 +48,23 @@ public EndpointHtmlRendererTest() } [Fact] - public async Task DoesNotRenderChildAfterRendererStopped() + public async Task DoesNotRenderAfterRendererStopped() { - renderer.SignalRendererToFinishRendering(); - var httpContext = GetHttpContext(); var writer = new StringWriter(); - var result = await renderer.PrerenderComponentAsync(httpContext, typeof(SimpleComponent), null, ParameterView.Empty); - await renderer.Dispatcher.InvokeAsync(() => result.WriteTo(writer, HtmlEncoder.Default)); - var content = writer.ToString(); + var component = new StoppingRendererComponent(); + var id = renderer.AssignRootComponentId(component); + var initialRenderOperation = renderer.Dispatcher.InvokeAsync( + () => renderer.RenderRootComponentAsync(id, ParameterView.Empty)); - Assert.DoesNotContain("Hello from SimpleComponent", content); + renderer.SignalRendererToFinishRendering(); + component.TaskCompletionSource.SetResult(false); + await initialRenderOperation; + int initialRenderCount = renderer.RenderCount; + + await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(id, ParameterView.Empty)); + Assert.Equal(initialRenderCount, renderer.RenderCount); } [Fact] @@ -1772,18 +1778,10 @@ private TestEndpointHtmlRenderer GetEndpointHtmlRenderer(IServiceProvider servic private class TestEndpointHtmlRenderer : EndpointHtmlRenderer { private bool _rendererIsStopped = false; - public TestEndpointHtmlRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) : base(serviceProvider, loggerFactory) - { - } + private int _renderCount; - internal int TestAssignRootComponentId(IComponent component) + public TestEndpointHtmlRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) : base(serviceProvider, loggerFactory) { - return base.AssignRootComponentId(component); - } - public void SignalRendererToFinishRendering() - { - // sets a deferred stop on the renderer, which will have an effect after the current batch is completed - _rendererIsStopped = true; } protected override void ProcessPendingRender() @@ -1793,6 +1791,16 @@ protected override void ProcessPendingRender() return; } base.ProcessPendingRender(); + + _renderCount++; + } + + public int RenderCount => _renderCount; + + public new void SignalRendererToFinishRendering() + { + _rendererIsStopped = true; + base.SignalRendererToFinishRendering(); } } diff --git a/src/Components/Endpoints/test/TestComponents/StoppingRendererComponent.razor b/src/Components/Endpoints/test/TestComponents/StoppingRendererComponent.razor new file mode 100644 index 000000000000..521257c5d11b --- /dev/null +++ b/src/Components/Endpoints/test/TestComponents/StoppingRendererComponent.razor @@ -0,0 +1,17 @@ +
State is @_state
+ +@code { + private bool _state = true; + + // expose a TCS so the test can control when OnInitializedAsync completes + public TaskCompletionSource