Skip to content

Commit 47f9c22

Browse files
committed
docs: added docu
1 parent 92fd9c1 commit 47f9c22

File tree

5 files changed

+114
-3
lines changed

5 files changed

+114
-3
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
@if (isLoading)
2+
{
3+
<p>Loading...</p>
4+
}
5+
else
6+
{
7+
@foreach (var item in Items)
8+
{
9+
<ListItem Value="@item" />
10+
}
11+
}
12+
13+
@code {
14+
[Parameter] public List<string> Items { get; set; } = new();
15+
16+
private bool isLoading = true;
17+
18+
protected override async Task OnInitializedAsync()
19+
{
20+
// Simulate async loading
21+
await Task.Delay(100);
22+
isLoading = false;
23+
}
24+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<div class="list-item">@Value</div>
2+
3+
@code {
4+
[Parameter] public string Value { get; set; } = string.Empty;
5+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Bunit;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Xunit;
4+
5+
namespace Bunit.Docs.Samples;
6+
7+
public class WaitForComponentTest : BunitContext
8+
{
9+
[Fact]
10+
public void WaitForComponent_WaitsForSingleComponent()
11+
{
12+
var cut = Render<AsyncComponentLoader>(parameters => parameters
13+
.Add(p => p.Items, ["Item 1"]));
14+
15+
var listItem = cut.WaitForComponent<ListItem>();
16+
17+
Assert.Equal("Item 1", listItem.Find(".list-item").TextContent);
18+
}
19+
20+
[Fact]
21+
public void WaitForComponents_WaitsForMultipleComponents()
22+
{
23+
var items = new List<string> { "Item 1", "Item 2", "Item 3" };
24+
var cut = Render<AsyncComponentLoader>(parameters => parameters
25+
.Add(p => p.Items, items));
26+
27+
var listItems = cut.WaitForComponents<ListItem>();
28+
29+
Assert.Equal(3, listItems.Count);
30+
Assert.Equal("Item 1", listItems.ElementAt(0).Find(".list-item").TextContent);
31+
Assert.Equal("Item 2", listItems.ElementAt(1).Find(".list-item").TextContent);
32+
Assert.Equal("Item 3", listItems.ElementAt(2).Find(".list-item").TextContent);
33+
}
34+
35+
[Fact]
36+
public void WaitForComponents_WaitsForSpecificCount()
37+
{
38+
var items = new List<string> { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
39+
var cut = Render<AsyncComponentLoader>(parameters => parameters
40+
.Add(p => p.Items, items));
41+
42+
var listItems = cut.WaitForComponents<ListItem>(5);
43+
44+
Assert.Equal(5, listItems.Count);
45+
}
46+
}

docs/site/docs/interaction/awaiting-async-state.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ A test can fail if a component performs asynchronous renders. This may be due to
99

1010
You need to handle this specifically in your tests because tests execute in the test framework's synchronization context and the test renderer executes renders in its own synchronization context. If you do not, you will likely experience tests that sometimes pass and sometimes fail.
1111

12-
bUnit comes with two methods that help to deal with this issue: the [`WaitForState()`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForState``1(Bunit.IRenderedComponent{``0},System.Func{System.Boolean},System.Nullable{System.TimeSpan})) method covered on this page, and the [`WaitForAssertion()`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForAssertion``1(Bunit.IRenderedComponent{``0},System.Action,System.Nullable{System.TimeSpan})) method covered on the <xref:async-assertion> page.
12+
bUnit comes with several methods that help to deal with this issue: the [`WaitForState()`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForState``1(Bunit.IRenderedComponent{``0},System.Func{System.Boolean},System.Nullable{System.TimeSpan})) method, the [`WaitForAssertion()`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForAssertion``1(Bunit.IRenderedComponent{``0},System.Action,System.Nullable{System.TimeSpan})) method covered on the <xref:async-assertion> page, and the component-specific waiting methods [`WaitForComponent()`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForComponent``1(Bunit.IRenderedComponent{Microsoft.AspNetCore.Components.IComponent},System.Nullable{System.TimeSpan})) and [`WaitForComponents()`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForComponents``1(Bunit.IRenderedComponent{Microsoft.AspNetCore.Components.IComponent},System.Nullable{System.TimeSpan})) that are covered later on this page.
1313

1414
Let's start by taking a look at the `WaitForState` method in more detail.
1515

@@ -48,6 +48,42 @@ If the timeout is reached, a <xref:Bunit.Extensions.WaitForHelpers.WaitForFailed
4848

4949
> The state predicate did not pass before the timeout period passed.
5050
51-
## Debugging code that uses `WaitForState`, `WaitForAssertion`, or `WaitForElement`
51+
## Waiting for components using `WaitForComponent` and `WaitForComponents`
52+
53+
bUnit provides specialized methods for waiting for child components to appear in the render tree. These methods are useful when testing scenarios where components are rendered asynchronously based on some state change or data loading.
54+
55+
### Waiting for a single component
56+
57+
The [`WaitForComponent<TComponent>(TimeSpan?)`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForComponent``1(Bunit.IRenderedComponent{Microsoft.AspNetCore.Components.IComponent},System.Nullable{System.TimeSpan})) method waits until the specified component type is rendered in the DOM and returns the first instance found.
58+
59+
Consider the following `<AsyncComponentLoader>` component that loads child components asynchronously:
60+
61+
[!code-cshtml[AsyncComponentLoader.razor](../../../samples/components/AsyncComponentLoader.razor)]
62+
63+
To test that the `<ListItem>` components are rendered correctly, the `WaitForComponent<TComponent>()` method can be used:
64+
65+
[!code-csharp[WaitForComponentTest.cs](../../../samples/tests/xunit/WaitForComponentTest.cs?start=12&end=17)]
66+
67+
### Waiting for multiple components
68+
69+
The [`WaitForComponents<TComponent>(TimeSpan?)`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForComponents``1(Bunit.IRenderedComponent{Microsoft.AspNetCore.Components.IComponent},System.Nullable{System.TimeSpan})) method waits until at least one instance of the specified component type is rendered in the DOM and returns all instances found:
70+
71+
[!code-csharp[WaitForComponentTest.cs](../../../samples/tests/xunit/WaitForComponentTest.cs?start=23&end=31)]
72+
73+
### Waiting for a specific number of components
74+
75+
The [`WaitForComponents<TComponent>(int, TimeSpan?)`](xref:Bunit.RenderedComponentWaitForHelperExtensions.WaitForComponents``1(Bunit.IRenderedComponent{Microsoft.AspNetCore.Components.IComponent},System.Int32,System.Nullable{System.TimeSpan})) overload waits until at least the specified number of component instances are rendered:
76+
77+
[!code-csharp[WaitForComponentTest.cs](../../../samples/tests/xunit/WaitForComponentTest.cs?start=38&end=44)]
78+
79+
> [!NOTE]
80+
> This method waits for **at least** the specified number of components, not exactly that number. If more components are rendered than requested, the method will still succeed and return all found instances.
81+
82+
> [!NOTE]
83+
> These component wait methods use the same underlying mechanism as `WaitForState()` and will retry their checks every time the component under test renders.
84+
85+
If the timeout is reached, a <xref:Bunit.Extensions.WaitForHelpers.WaitForFailedException> exception is thrown with an appropriate error message indicating that the expected component(s) were not found within the timeout period.
86+
87+
## Debugging code that uses `WaitForState`, `WaitForAssertion`, `WaitForComponent`, `WaitForComponents`, or `WaitForElement`
5288

5389
When `bUnit` detects that a debugger is attached (`Debugger.IsAttached`), it will automatically disable the timeout functionality of the "wait for" methods.

src/bunit/Extensions/WaitForHelpers/RenderedComponentWaitForhelperExtensions.WaitForComponent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static IReadOnlyCollection<IRenderedComponent<TComponent>> WaitForCompone
3636
where TComponent : IComponent
3737
{
3838
renderedComponent.WaitForState(
39-
() => renderedComponent.FindComponents<TComponent>().Count == matchComponentCount,
39+
() => renderedComponent.FindComponents<TComponent>().Count >= matchComponentCount,
4040
timeout);
4141
return renderedComponent.FindComponents<TComponent>();
4242
}

0 commit comments

Comments
 (0)