Skip to content

Commit 1bb0b01

Browse files
authored
Merge pull request #1625 from bUnit-dev/release/v1.37
Release of new minor version v1.37
2 parents 653f575 + 5a2c0f4 commit 1bb0b01

28 files changed

+667
-37
lines changed

.config/dotnet-tools.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"rollForward": false
1111
},
1212
"docfx": {
13-
"version": "2.77.0",
13+
"version": "2.78.2",
1414
"commands": [
1515
"docfx"
1616
],

.vscode/tasks.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
{
77
"label": "Serve Docs (Without Build)",
88
"type": "shell",
9-
"command": "docfx metadata docs/site/docfx.json && docfx docs/site/docfx.json --serve"
9+
"command": "dotnet docfx metadata docs/site/docfx.json && dotnet docfx docs/site/docfx.json --serve"
1010
},
1111
{
1212
"label": "Serve Docs (With Build for API Documentation)",
1313
"type": "shell",
14-
"command": "dotnet build -c Release && docfx metadata docs/site/docfx.json && docfx docs/site/docfx.json --serve"
14+
"command": "dotnet build -c Release && dotnet docfx metadata docs/site/docfx.json && docfx docs/site/docfx.json --serve"
1515
},
1616
{
1717
"label": "Run all tests (Release Mode)",

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ All notable changes to **bUnit** will be documented in this file. The project ad
66

77
## [Unreleased]
88

9+
### Added
10+
- Added support for `RendererInfo` and `AssignedRenderMode` (`.net9.0`).
11+
912
## [1.36.0] - 2024-11-12
1013

1114
### Added

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<ImplicitUsings>enable</ImplicitUsings>
1717
<NoWarn>CA1014,NU5104,NETSDK1138,SYSLIB0051</NoWarn>
1818
<CheckEolTargetFramework>false</CheckEolTargetFramework>
19+
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
1920

2021
<!-- Used by code coverage -->
2122
<DebugType>full</DebugType>

Directory.Packages.props

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<GlobalPackageReference Include="AsyncFixer" Version="1.6.0" PrivateAssets="All" IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"/>
99
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167" PrivateAssets="All" IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"/>
1010
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
11-
<PackageVersion Include="Meziantou.Polyfill" Version="1.0.40" />
11+
<PackageVersion Include="Meziantou.Polyfill" Version="1.0.42" />
1212
</ItemGroup>
1313

1414
<ItemGroup Label="Shared">
@@ -28,7 +28,7 @@
2828

2929
<ItemGroup Label="System.Text.Json Vulnerability">
3030
<!-- Due to a CVE in System.Text.Json we explicitly reference the latest version of System.Text.Json -->
31-
<PackageVersion Include="System.Text.Json" Version="8.0.5"/>
31+
<PackageVersion Include="System.Text.Json" Version="9.0.0"/>
3232
</ItemGroup>
3333

3434
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
@@ -58,16 +58,16 @@
5858
</ItemGroup>
5959

6060
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
61-
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0"/>
61+
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.1"/>
6262
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.4"/>
63-
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="6.0.33"/>
64-
65-
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.33"/>
66-
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="6.0.33"/>
67-
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="6.0.2"/>
68-
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="6.0.33"/>
69-
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.33"/>
70-
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.33"/>
63+
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="6.0.36"/>
64+
65+
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.36"/>
66+
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="6.0.36"/>
67+
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="6.0.3"/>
68+
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="6.0.36"/>
69+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.36"/>
70+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.36"/>
7171
</ItemGroup>
7272

7373
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
@@ -86,14 +86,14 @@
8686
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
8787
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1"/>
8888
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2"/>
89-
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="8.0.10"/>
89+
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="8.0.11"/>
9090

91-
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.10"/>
92-
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.10"/>
91+
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="8.0.11"/>
92+
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.11"/>
9393
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1"/>
94-
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="8.0.10"/>
95-
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.10"/>
96-
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.10"/>
94+
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="8.0.11"/>
95+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.11"/>
96+
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.11"/>
9797
</ItemGroup>
9898

9999
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
@@ -103,7 +103,7 @@
103103

104104
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.0"/>
105105
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.0"/>
106-
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0-rc.2.24473.5"/>
106+
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0"/>
107107
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.0"/>
108108
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0"/>
109109
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.0"/>
@@ -122,7 +122,7 @@
122122
<PackageVersion Include="Serilog.Extensions.Logging" Version="8.0.0" />
123123
<PackageVersion Include="Shouldly" Version="4.2.1"/>
124124
<PackageVersion Include="Verify.SourceGenerators" Version="2.5.0"/>
125-
<PackageVersion Include="Verify.Xunit" Version="28.1.0"/>
125+
<PackageVersion Include="Verify.Xunit" Version="28.4.0"/>
126126
<PackageVersion Include="Xunit.Combinatorial" Version="1.6.24"/>
127127
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
128128
<PackageVersion Include="coverlet.msbuild" Version="6.0.2" />
@@ -140,10 +140,10 @@
140140

141141
<ItemGroup Label="Source Code Generators">
142142
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1"/>
143-
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0"/>
144-
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.11.0"/>
145-
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.11.0"/>
146-
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0"/>
143+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0"/>
144+
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.12.0"/>
145+
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.12.0"/>
146+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0"/>
147147
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing.XUnit" Version="1.1.2" />
148148
</ItemGroup>
149149
</Project>

docs/site/docs/interaction/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ This section covers the various ways to interact with a component under test, e.
1111
- **<xref:trigger-renders>:** This covers how to manually trigger a render cycle for a component under test.
1212
- **<xref:awaiting-async-state>:** This covers how to await one or more asynchronous changes to the state of a component under test before continuing the test.
1313
- **<xref:dispose-components>:** This covers how to dispose components and their children.
14+
- **<xref:render-modes>:** This covers the different render modes and their interaction with bUnit.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
uid: render-modes
3+
title: Render modes and RendererInfo
4+
---
5+
6+
# Support for render modes and `RendererInfo`
7+
This article explains how to emulate different render modes and `RendererInfo` in bUnit tests.
8+
9+
Render modes in Blazor Web Apps determine the hosting model and interactivity of components. A render mode can be applied to a component using the `@rendermode` directive. The [`RendererInfo`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.rendererinfo?view=aspnetcore-9.0) allows the application to determine the interactivity and location of the component. For more details, see the [Blazor render modes](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-9.0) documentation.
10+
11+
## Setting the render mode for a component under test
12+
Setting the render mode can be done via the <xref:Bunit.ComponentParameterCollectionBuilder`1.SetAssignedRenderMode(Microsoft.AspNetCore.Components.IComponentRenderMode)> method when writing in a C# file. In a razor file use the `@rendermode` directive. Both take an [`IComponentRenderMode`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.icomponentrendermode?view=aspnetcore-9.0) object as a parameter. Normally this is one of the following types:
13+
* [`InteractiveAutoRenderMode`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.web.interactiveautorendermode?view=aspnetcore-9.0)
14+
* [`InteractiveServerRendeMode`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.web.interactiveserverrendermode?view=aspnetcore-9.0)
15+
* [`InteractiveWebAssemblyRenderMode`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.web.interactivewebassemblyrendermode?view=aspnetcore-9.0)
16+
17+
For ease of use the [`RenderMode`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.web.rendermode?view=aspnetcore-9.0) class defines all three of them.
18+
19+
For example `MovieComponent.razor`:
20+
```razor
21+
@if (AssignedRenderMode is null)
22+
{
23+
// The render mode is Static Server
24+
<form action="/movies">
25+
<input type="text" name="titleFilter" />
26+
<input type="submit" value="Search" />
27+
</form>
28+
}
29+
else
30+
{
31+
// The render mode is Interactive Server, WebAssembly, or Auto
32+
<input @bind="titleFilter" />
33+
<button @onclick="FilterMovies">Search</button>
34+
}
35+
```
36+
37+
The following example shows how to test the above component to check both render modes:
38+
39+
# [C# test code](#tab/csharp)
40+
41+
```csharp
42+
[Fact]
43+
public void InteractiveServer()
44+
{
45+
// Act
46+
var cut = RenderComponent<MovieComponent>(ps => ps
47+
.SetAssignedRenderMode(RenderMode.InteractiveServer));
48+
49+
// Assert
50+
cut.MarkupMatches("""
51+
<input diff:ignoreAttributes />
52+
<button>Search</button>
53+
""");
54+
}
55+
56+
[Fact]
57+
public void StaticRendering()
58+
{
59+
// Act
60+
var cut = RenderComponent<MovieComponent>();
61+
// This is the same behavior as:
62+
// var cut = RenderComponent<MovieComponent>(ps => ps
63+
// .SetAssignedRenderMode(null));
64+
65+
// Assert
66+
cut.MarkupMatches("""
67+
<form action="/movies">
68+
<input type="text" name="titleFilter" />
69+
<input type="submit" value="Search" />
70+
</form>
71+
""");
72+
}
73+
```
74+
75+
# [Razor test code](#tab/razor)
76+
77+
```razor
78+
@inherits TestContext
79+
@code {
80+
[Fact]
81+
public void InteractiveServer()
82+
{
83+
// Act
84+
var cut = Render(@<MovieComponent @rendermode="RenderMode.InteractiveServer" />);
85+
86+
// Assert
87+
cut.MarkupMatches(@<text>
88+
<input diff:ignoreAttributes />
89+
<button>Search</button>
90+
</text>);
91+
}
92+
93+
[Fact]
94+
public void StaticRendering()
95+
{
96+
// Act
97+
var cut = Render(@<MovieComponent />);
98+
99+
// Assert
100+
cut.MarkupMatches(@<form action="/movies">
101+
<input type="text" name="titleFilter" />
102+
<input type="submit" value="Search" />
103+
</form>);
104+
}
105+
}
106+
```
107+
108+
***
109+
110+
## Setting the `RendererInfo` during testing
111+
To control the `ComponentBase.RendererInfo` property during testing, use the <xref:Bunit.TestContextBase.SetRendererInfo(Microsoft.AspNetCore.Components.RendererInfo)> method on the `TestContext` class. The `SetRendererInfo` method takes an nullable `RendererInfo` object as a parameter. Passing `null` will set the `ComponentBase.RendererInfo` to `null`.
112+
113+
A component (`AssistentComponent.razor`) might check if interactivity is given to enable a button:
114+
115+
```razor
116+
@if (RendererInfo.IsInteractive)
117+
{
118+
<p>Hey I am your assistant</p>
119+
}
120+
else
121+
{
122+
<p>Loading...</p>
123+
}
124+
```
125+
126+
In the test, you can set the `RendererInfo` to enable or disable the button:
127+
128+
```csharp
129+
[Fact]
130+
public void SimulatingPreRenderingOnBlazorServer()
131+
{
132+
// Arrange
133+
SetRendererInfo(new RendererInfo(rendererName: "Static", isInteractive: false));
134+
135+
// Act
136+
var cut = RenderComponent<AssistentComponent>();
137+
138+
// Assert
139+
cut.MarkupMatches("<p>Loading...</p>");
140+
}
141+
142+
[Fact]
143+
public void SimulatingInteractiveServerRendering()
144+
{
145+
// Arrange
146+
SetRendererInfo(new RendererInfo(rendererMode: "Server", isInteractive: true));
147+
148+
// Act
149+
var cut = RenderComponent<AssistentComponent>();
150+
151+
// Assert
152+
cut.MarkupMatches("<p>Hey I am your assistant</p>");
153+
}
154+
```
155+
156+
> [!NOTE]
157+
> If a component under test uses the `ComponentBase.RendererInfo` property and the `SetRendererInfo` on `TestContext` hasn't been passed in a `RendererInfo` object, the renderer will throw an exception.

docs/site/docs/toc.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
## [Trigger renders](xref:trigger-renders)
1515
## [Awaiting an async state change](xref:awaiting-async-state)
1616
## [Disposing components](xref:dispose-components)
17+
## [Render modes and RendererInfo](xref:render-modes)
1718

1819
# [Verifying output](xref:verification)
1920
## [Verify markup](xref:verify-markup)

src/bunit.core/ComponentParameterCollection.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ public class ComponentParameterCollection : ICollection<ComponentParameter>, IRe
1919
/// <inheritdoc />
2020
public bool IsReadOnly { get; }
2121

22+
#if NET9_0_OR_GREATER
23+
/// <summary>
24+
/// Gets or sets the <see cref="IComponentRenderMode"/> that will be specified in
25+
/// the render tree for component the parameters are being passed to.
26+
/// </summary>
27+
public IComponentRenderMode? RenderMode { get; set; }
28+
#endif
29+
2230
/// <summary>
2331
/// Adds a <paramref name="item"/> to the collection.
2432
/// </summary>
@@ -104,6 +112,9 @@ void AddComponent(RenderTreeBuilder builder)
104112
{
105113
builder.OpenComponent<TComponent>(0);
106114
AddAttributes(builder);
115+
#if NET9_0_OR_GREATER
116+
builder.AddComponentRenderMode(RenderMode);
117+
#endif
107118
builder.CloseComponent();
108119
}
109120

0 commit comments

Comments
 (0)