Skip to content

Commit

Permalink
fix: await task when calling SetDirectParametersAsync
Browse files Browse the repository at this point in the history
fix: await task when calling SetDirectParametersAsync
  • Loading branch information
egil committed Sep 5, 2023
1 parent a23fa20 commit e5f6566
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 37 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ All notable changes to **bUnit** will be documented in this file. The project ad

## [Unreleased]

### Fixed

- If the renderer was not idle when calling `SetParametersAndRender`, the method could return before the parameters were set and the component under test had finished rendering. This was a regression that happened in v1.21.9. Reported by [@Skintkingle](https://github.com/Skintkingle]) in <https://github.com/bUnit-dev/bUnit/issues/1188>. Fixed by [@egil](https://github.com/egil).

### Added

- `net8.0` support
Expand Down
10 changes: 9 additions & 1 deletion src/bunit.core/Extensions/RenderedComponentRenderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@ public static void SetParametersAndRender<TComponent>(this IRenderedComponentBas
throw new ArgumentNullException(nameof(renderedComponent));

var renderer = renderedComponent.Services.GetRequiredService<TestRenderer>();
renderer.SetDirectParameters(renderedComponent, parameters);

try
{
renderer.SetDirectParametersAsync(renderedComponent, parameters).GetAwaiter().GetResult();
}
catch (AggregateException e) when (e.InnerExceptions.Count == 1)
{
ExceptionDispatchInfo.Capture(e.InnerExceptions[0]).Throw();
}
}

/// <summary>
Expand Down
62 changes: 28 additions & 34 deletions src/bunit.core/Rendering/TestRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public void DisposeComponents()
AssertNoUnhandledExceptions();
}
}

#if NET8_0_OR_GREATER
/// <inheritdoc/>
protected override IComponent ResolveComponentForRenderMode(Type componentType, int? parentComponentId,
Expand All @@ -207,52 +207,46 @@ public void DisposeComponents()
#endif

/// <inheritdoc/>
internal void SetDirectParameters(IRenderedFragmentBase renderedComponent, ParameterView parameters)
internal Task SetDirectParametersAsync(IRenderedFragmentBase renderedComponent, ParameterView parameters)
{
if (disposed)
throw new ObjectDisposedException(nameof(TestRenderer));

// Calling SetDirectParameters updates the render tree
// if the event contains associated data.
lock (renderTreeUpdateLock)
var result = Dispatcher.InvokeAsync(() =>
{
if (disposed)
throw new ObjectDisposedException(nameof(TestRenderer));

var result = Dispatcher.InvokeAsync(() =>
try
{
try
{
IsBatchInProgress = true;

IsBatchInProgress = true;

#if NET8_0_OR_GREATER
var setDirectParametersMethod = typeof(ComponentState).GetMethod("SetDirectParameters", BindingFlags.NonPublic | BindingFlags.Instance)!;
var componentState = GetComponentState(renderedComponent.ComponentId);
var setDirectParametersMethod = typeof(ComponentState).GetMethod("SetDirectParameters", BindingFlags.NonPublic | BindingFlags.Instance)!;
var componentState = GetComponentState(renderedComponent.ComponentId);
#else
var componentState = GetRequiredComponentStateMethod.Invoke(this, new object[] { renderedComponent.ComponentId })!;
var setDirectParametersMethod = componentState.GetType().GetMethod("SetDirectParameters", BindingFlags.Public | BindingFlags.Instance)!;
var componentState = GetRequiredComponentStateMethod.Invoke(this, new object[] { renderedComponent.ComponentId })!;
var setDirectParametersMethod = componentState.GetType().GetMethod("SetDirectParameters", BindingFlags.Public | BindingFlags.Instance)!;
#endif
setDirectParametersMethod.Invoke(componentState, new object[] { parameters });
}
catch (TargetInvocationException ex) when (ex.InnerException is not null)
{
throw ex.InnerException;
}
finally
{
IsBatchInProgress = false;
}

ProcessPendingRender();
});

if (result.IsFaulted && result.Exception is not null)
setDirectParametersMethod.Invoke(componentState, new object[] { parameters });
}
catch (TargetInvocationException ex) when (ex.InnerException is not null)
{
HandleException(result.Exception);
throw ex.InnerException;
}
finally
{
IsBatchInProgress = false;
}

AssertNoUnhandledExceptions();
ProcessPendingRender();
});

if (result.IsFaulted && result.Exception is not null)
{
HandleException(result.Exception);
}

AssertNoUnhandledExceptions();

return result;
}

/// <inheritdoc/>
Expand Down
4 changes: 2 additions & 2 deletions tests/bunit.core.tests/Rendering/TestRendererTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ public void Test208()
cut.Instance.AfterRenderCount.ShouldBe(2);
cut.Instance.AfterRenderAsyncCount.ShouldBe(2);
}

#if NET8_0_OR_GREATER
[Fact(DisplayName = "Can render components that have a RenderMode attribute")]
public void Test209()
Expand Down Expand Up @@ -632,7 +632,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
throw new InvalidOperationException();
}
}

#if NET8_0_OR_GREATER
[RenderModeServer]
private sealed class RenderModeServerComponent : ComponentBase
Expand Down

0 comments on commit e5f6566

Please sign in to comment.