Skip to content

Commit f423134

Browse files
committed
Added wrapper of TestContext to make it easier to inherit from the test context in other test frameworks than xUnit
1 parent 18f44e3 commit f423134

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using Bunit.Rendering;
3+
using Microsoft.AspNetCore.Components;
4+
using Microsoft.JSInterop;
5+
6+
namespace Bunit
7+
{
8+
/// <summary>
9+
/// Represents a class that wraps a <see cref="Bunit.TestContext"/>. Useful for
10+
/// simplifying writing tests in NUnit and MSTest, which cannot
11+
/// inherit directly from <see cref="Bunit.TestContext"/>.
12+
/// </summary>
13+
public abstract class TestContextWrapper
14+
{
15+
/// <summary>
16+
/// Gets an instance of the wrapped <see cref="Bunit.TestContext"/>, if any.
17+
/// </summary>
18+
protected virtual TestContext? TestContext { get; set; }
19+
20+
/// <summary>
21+
/// Gets the renderer used by the test context.
22+
/// </summary>
23+
public ITestRenderer Renderer => TestContext?.Renderer ?? throw new InvalidOperationException("The TestContext has not been initialized.");
24+
25+
/// <summary>
26+
/// Gets the service collection and service provider that is used when a
27+
/// component is rendered by the test context.
28+
/// </summary>
29+
public TestServiceProvider Services => TestContext?.Services ?? throw new InvalidOperationException("The TestContext has not been initialized.");
30+
31+
/// <summary>
32+
/// Gets the service collection and service provider that is used when a
33+
/// component is rendered by the test context.
34+
/// </summary>
35+
public RootRenderTree RenderTree => TestContext?.RenderTree ?? throw new InvalidOperationException("The TestContext has not been initialized.");
36+
37+
/// <summary>
38+
/// Gets bUnits JSInterop, that allows setting up handlers for <see cref="IJSRuntime.InvokeAsync{TValue}(string, object[])"/> invocations
39+
/// that components under tests will issue during testing. It also makes it possible to verify that the invocations has happened as expected.
40+
/// </summary>
41+
public BunitJSInterop JSInterop => TestContext?.JSInterop ?? throw new InvalidOperationException("The TestContext has not been initialized.");
42+
43+
/// <summary>
44+
/// Instantiates and performs a first render of a component of type <typeparamref name="TComponent"/>.
45+
/// </summary>
46+
/// <typeparam name="TComponent">Type of the component to render.</typeparam>
47+
/// <param name="parameters">Parameters to pass to the component when it is rendered.</param>
48+
/// <returns>The rendered <typeparamref name="TComponent"/>.</returns>
49+
public virtual IRenderedComponent<TComponent> RenderComponent<TComponent>(params ComponentParameter[] parameters)
50+
where TComponent : IComponent
51+
=> TestContext?.RenderComponent<TComponent>(parameters) ?? throw new InvalidOperationException("The TestContext has not been initialized.");
52+
53+
/// <summary>
54+
/// Instantiates and performs a first render of a component of type <typeparamref name="TComponent"/>.
55+
/// </summary>
56+
/// <typeparam name="TComponent">Type of the component to render.</typeparam>
57+
/// <param name="parameterBuilder">The ComponentParameterBuilder action to add type safe parameters to pass to the component when it is rendered.</param>
58+
/// <returns>The rendered <typeparamref name="TComponent"/>.</returns>
59+
public virtual IRenderedComponent<TComponent> RenderComponent<TComponent>(Action<ComponentParameterCollectionBuilder<TComponent>> parameterBuilder)
60+
where TComponent : IComponent
61+
=> TestContext?.RenderComponent<TComponent>(parameterBuilder) ?? throw new InvalidOperationException("The TestContext has not been initialized.");
62+
63+
/// <summary>
64+
/// Renders the <paramref name="renderFragment"/> and returns the first <typeparamref name="TComponent"/> in the resulting render tree.
65+
/// </summary>
66+
/// <remarks>
67+
/// Calling this method is equivalent to calling <c>Render(renderFragment).FindComponent&lt;TComponent&gt;()</c>.
68+
/// </remarks>
69+
/// <typeparam name="TComponent">The type of component to find in the render tree.</typeparam>
70+
/// <param name="renderFragment">The render fragment to render.</param>
71+
/// <returns>The <see cref="IRenderedComponent{TComponent}"/>.</returns>
72+
public virtual IRenderedComponent<TComponent> Render<TComponent>(RenderFragment renderFragment)
73+
where TComponent : IComponent
74+
=> TestContext?.Render<TComponent>(renderFragment) ?? throw new InvalidOperationException("The TestContext has not been initialized.");
75+
76+
/// <summary>
77+
/// Renders the <paramref name="renderFragment"/> and returns it as a <see cref="IRenderedFragment"/>.
78+
/// </summary>
79+
/// <param name="renderFragment">The render fragment to render.</param>
80+
/// <returns>The <see cref="IRenderedFragment"/>.</returns>
81+
public virtual IRenderedFragment Render(RenderFragment renderFragment)
82+
=> TestContext?.Render(renderFragment) ?? throw new InvalidOperationException("The TestContext has not been initialized.");
83+
84+
/// <summary>
85+
/// Dummy method required to allow Blazor's compiler to generate
86+
/// C# from .razor files.
87+
/// </summary>
88+
protected virtual void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
89+
}
90+
}

0 commit comments

Comments
 (0)