From eebcb8628f302b007c1ced9eedb72269b95f78d4 Mon Sep 17 00:00:00 2001 From: Steven Giesel Date: Wed, 23 Aug 2023 14:41:54 +0200 Subject: [PATCH] feat: Easier handling of triggering stub events --- CHANGELOG.md | 1 + .../RenderedComponentStubExtensions.cs | 36 +++++++++++++++++++ .../Extensions/RenderedFragmentExtensions.cs | 2 ++ .../ComponentDoubleBase{TComponent}.cs | 5 +++ .../Components/Stub{TComponent}.cs | 21 +++++++++++ .../DisposeComponents/DisplayInput.razor | 5 +++ .../TestDoubles/Components/StubTest.cs | 15 ++++++++ 7 files changed, 85 insertions(+) create mode 100644 src/bunit.web/Extensions/RenderedComponentStubExtensions.cs create mode 100644 tests/bunit.testassets/SampleComponents/DisposeComponents/DisplayInput.razor diff --git a/CHANGELOG.md b/CHANGELOG.md index 46b0649c2..045afad41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to **bUnit** will be documented in this file. The project ad - `net8.0` support - Increased timeout of `WaitForAssertion` to infinite when a debugger is attached. By [@linkdotnet](https://github.com/linkdotnet). +- Easier overloads for Stub's to invoke `EventCallback`s ### Fixed diff --git a/src/bunit.web/Extensions/RenderedComponentStubExtensions.cs b/src/bunit.web/Extensions/RenderedComponentStubExtensions.cs new file mode 100644 index 000000000..b49a81959 --- /dev/null +++ b/src/bunit.web/Extensions/RenderedComponentStubExtensions.cs @@ -0,0 +1,36 @@ +#if NET5_0_OR_GREATER +using System.Linq.Expressions; +using Bunit.TestDoubles; + +namespace Bunit; + +/// +/// Extension methods for using component doubles. +/// +public static class RenderedComponentStubExtensions +{ + /// + /// Invokes the event callback from the stub. + /// + public static Task InvokeEventCallback(this IRenderedComponent> component, + Expression> selector) where TComponent : IComponent + { + if (component is null) + throw new ArgumentNullException(nameof(component)); + + return component.Instance.InvokeEventCallback(selector); + } + + /// + /// Invokes the event callback from the stub. + /// + public static Task InvokeEventCallback(this IRenderedComponent> component, + Expression>> selector, TU value) where TComponent : IComponent + { + if (component is null) + throw new ArgumentNullException(nameof(component)); + + return component.Instance.InvokeEventCallback(selector, value); + } +} +#endif diff --git a/src/bunit.web/Extensions/RenderedFragmentExtensions.cs b/src/bunit.web/Extensions/RenderedFragmentExtensions.cs index da7f5addf..40ccca2e4 100644 --- a/src/bunit.web/Extensions/RenderedFragmentExtensions.cs +++ b/src/bunit.web/Extensions/RenderedFragmentExtensions.cs @@ -1,5 +1,7 @@ +using System.Linq.Expressions; using AngleSharp.Dom; using Bunit.Rendering; +using Bunit.TestDoubles; namespace Bunit; diff --git a/src/bunit.web/TestDoubles/Components/ComponentDoubleBase{TComponent}.cs b/src/bunit.web/TestDoubles/Components/ComponentDoubleBase{TComponent}.cs index a97225e68..11da0d2d2 100644 --- a/src/bunit.web/TestDoubles/Components/ComponentDoubleBase{TComponent}.cs +++ b/src/bunit.web/TestDoubles/Components/ComponentDoubleBase{TComponent}.cs @@ -15,6 +15,11 @@ public abstract class ComponentDoubleBase : IComponent /// protected static readonly Type DoubledType = typeof(TComponent); + /// + /// Invokes the given in the context of the associated . + /// + protected Task InvokeAsync(Func workItem) => renderHandle.Dispatcher.InvokeAsync(workItem); + /// /// Gets the parameters that was passed to the /// that this stub replaced in the component tree. diff --git a/src/bunit.web/TestDoubles/Components/Stub{TComponent}.cs b/src/bunit.web/TestDoubles/Components/Stub{TComponent}.cs index 78625eb33..029586dfe 100644 --- a/src/bunit.web/TestDoubles/Components/Stub{TComponent}.cs +++ b/src/bunit.web/TestDoubles/Components/Stub{TComponent}.cs @@ -1,5 +1,6 @@ #if NET5_0_OR_GREATER using System.Diagnostics; +using System.Linq.Expressions; namespace Bunit.TestDoubles; @@ -33,6 +34,26 @@ public Stub(object? replacement) throw new ArgumentException($"The type of replacement is not supported. Replacement type = {replacement.GetType()}", nameof(replacement)); } + /// + /// Triggers an event callback from the stub. + /// + /// Event to trigger. + public Task InvokeEventCallback(Expression> selector) + { + var callback = Parameters.Get(selector); + return InvokeAsync(callback.InvokeAsync); + } + + /// + /// Triggers an event callback from the stub. + /// + /// Event to trigger. + public Task InvokeEventCallback(Expression>> selector, TU? value) + { + var callback = Parameters.Get(selector); + return InvokeAsync(() => callback.InvokeAsync(value)); + } + /// public override string ToString() => $"Stub<{DoubledType.Name}>"; diff --git a/tests/bunit.testassets/SampleComponents/DisposeComponents/DisplayInput.razor b/tests/bunit.testassets/SampleComponents/DisposeComponents/DisplayInput.razor new file mode 100644 index 000000000..ec82f9012 --- /dev/null +++ b/tests/bunit.testassets/SampleComponents/DisposeComponents/DisplayInput.razor @@ -0,0 +1,5 @@ +

User wrote: @value

+ +@code { + private string value; +} \ No newline at end of file diff --git a/tests/bunit.web.tests/TestDoubles/Components/StubTest.cs b/tests/bunit.web.tests/TestDoubles/Components/StubTest.cs index f6492e588..97e3e4d13 100644 --- a/tests/bunit.web.tests/TestDoubles/Components/StubTest.cs +++ b/tests/bunit.web.tests/TestDoubles/Components/StubTest.cs @@ -1,3 +1,6 @@ +using Bunit.TestAssets.SampleComponents.DisposeComponents; +using Microsoft.AspNetCore.Components.Forms; + #if NET5_0_OR_GREATER namespace Bunit.TestDoubles.Components; @@ -26,5 +29,17 @@ public void Test002(string header, string attrValue) ps => ps.ShouldContain(x => x.Key == nameof(Simple1.AttrValue) && attrValue.Equals(x.Value)), ps => ps.Count.ShouldBe(2)); } + + [Fact(DisplayName = "Stub can invoke event callbacks")] + public async Task Test003() + { + ComponentFactories.AddStub(); + var cut = RenderComponent(); + var stubbedInput = cut.FindComponent>(); + + await stubbedInput.InvokeEventCallback(t => t.ValueChanged, "Hello World"); + + cut.Find("p").MarkupMatches("

User wrote: Hello World

"); + } } #endif