diff --git a/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs b/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs index 4d7c2fe5e..a52b1e002 100644 --- a/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs +++ b/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs @@ -3,6 +3,7 @@ using Bunit.Diffing; using Bunit.Extensions; using Bunit.Rendering; +using Microsoft.Extensions.Logging; namespace Bunit; @@ -299,8 +300,13 @@ public static void MarkupMatches(this IRenderedFragment actual, RenderFragment e if (expected is null) throw new ArgumentNullException(nameof(expected)); - var testContext = actual.Services.GetRequiredService(); - var renderedFragment = (IRenderedFragment)testContext.RenderInsideRenderTree(expected); + // TODO: This will be obsolete with: https://github.com/bUnit-dev/bUnit/issues/1018 + // As the renderer would be transient we don't have to new up an instance + using var renderer = new TestRenderer( + actual.Services.GetRequiredService(), + actual.Services.GetRequiredService(), + actual.Services.GetRequiredService()); + var renderedFragment = (IRenderedFragment)renderer.RenderFragment(expected); MarkupMatches(actual, renderedFragment, userMessage); } diff --git a/tests/bunit.testassets/SampleComponents/InvokeAsyncInsideContinueWith.razor b/tests/bunit.testassets/SampleComponents/InvokeAsyncInsideContinueWith.razor new file mode 100644 index 000000000..9be4161b2 --- /dev/null +++ b/tests/bunit.testassets/SampleComponents/InvokeAsyncInsideContinueWith.razor @@ -0,0 +1,50 @@ +@if (Task != null) +{ + @if (Task.IsCompleted) + { + done + } + else + { + waiting + } +} +@code { + [Parameter] public Task? Task { get; set; } + + private Task? registeredTask; + private Task? delegatedTask; + + protected override void OnParametersSet() + { + var task = Task; + if (task != registeredTask) + { + registeredTask = task; + delegatedTask = task == null ? null : DelegateTo(task); + RenderWhenDone(); + } + + base.OnParametersSet(); + } + + private async void RenderWhenDone() + { + var task = delegatedTask; + if (task != null) + { + _ = await Task.WhenAny(task).ConfigureAwait(false); + + if (task == delegatedTask) + { + _ = InvokeAsync(StateHasChanged); + } + } + } + + private static async Task DelegateTo(Task task) + { + await task;//.ConfigureAwait(false); + return null; + } +} diff --git a/tests/bunit.web.tests/Asserting/MarkupMatchesTests.razor b/tests/bunit.web.tests/Asserting/MarkupMatchesTests.razor index 3596c1a60..5c22485fc 100644 --- a/tests/bunit.web.tests/Asserting/MarkupMatchesTests.razor +++ b/tests/bunit.web.tests/Asserting/MarkupMatchesTests.razor @@ -2,6 +2,7 @@ @inherits TestContext @code { + [Fact] public void MarkupMatchesShouldNotBeBlockedByRenderer() { @@ -15,4 +16,20 @@ cut.WaitForAssertion(() => cut.MarkupMatches(@done)); } + + [SuppressMessage("Usage", "xUnit1026:Theory method does not use parameter")] + [Theory] + [Repeat(2)] + public void MarkupMatchesShouldNotBeBlockedByRendererComplex(int repeatCount) + { + var tcs = new TaskCompletionSource(); + + var cut = Render(@ ); + + cut.MarkupMatches(@waiting); + + tcs.SetResult(true); + + cut.WaitForAssertion(() => cut.MarkupMatches(@done)); + } }