Skip to content

Commit f620a81

Browse files
committed
refactor: Remove IRefreshableCollection and behavior
1 parent 9e34fd6 commit f620a81

File tree

9 files changed

+56
-178
lines changed

9 files changed

+56
-178
lines changed

MIGRATION.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,26 @@ The `TestServiceProvider` class has been renamed to `BunitTestServiceProvider`.
8282

8383
## `DisposeComponents` is now asynchronous and called `DisposeComponentsAsync`
8484
`DisposeComponentsAsync` allows to await `DisposeAsync` of components under test. If you used `DisposeComponents`, you should replace it with `DisposeComponentsAsync`.
85+
86+
## `IRefreshableElementCollection` was removed
87+
88+
The `IRefreshableElementCollection` interface has been removed. With this the `FindAll` method does not accept a `bool enableRefresh` parameter anymore. Code like this:
89+
90+
```csharp
91+
var items = cut.FindAll("li", enableRefresh: true);
92+
93+
cut.Find("button").Click(); // Some action that causes items to change
94+
95+
Assert.Equal(3, items.Count);
96+
```
97+
98+
Should be changed to this:
99+
100+
```csharp
101+
var items = cut.FindAll("li");
102+
103+
cut.Find("button").Click(); // Some action that causes items to change
104+
105+
items = cut.FindAll("li"); // Re-query the items
106+
Assert.Equal(3, items.Count);
107+
```

docs/site/docs/verification/verify-markup.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ bUnit supports multiple different ways of searching and querying the rendered HT
3737

3838
- `FindByLabelText(string labelText)` that takes a text string used to label an input element and returns an `IElement` as output, or throws an exception if none are found (this is included in the experimental library [bunit.web.query](https://www.nuget.org/packages/bunit.web.query)). Use this method when possible compared to the generic `Find` and `FindAll` methods.
3939
- [`Find(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.Find``1(Bunit.IRenderedComponent{``0},System.String)) takes a "CSS selector" as input and returns an `IElement` as output, or throws an exception if none are found.
40-
- [`FindAll(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.FindAll``1(Bunit.IRenderedComponent{``0},System.String,System.Boolean)) takes a "CSS selector" as input and returns a list of `IElement` elements.
40+
- [`FindAll(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.FindAll``1(Bunit.IRenderedComponent{``0},System.String)) takes a "CSS selector" as input and returns a list of `IElement` elements.
4141

42-
Let's see some examples of using the [`Find(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.Find``1(Bunit.IRenderedComponent{``0},System.String)) and [`FindAll(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.FindAll``1(Bunit.IRenderedComponent{``0},System.String,System.Boolean)) methods to query the `<FancyTable>` component listed below.
42+
Let's see some examples of using the [`Find(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.Find``1(Bunit.IRenderedComponent{``0},System.String)) and [`FindAll(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.FindAll``1(Bunit.IRenderedComponent{``0},System.String)) methods to query the `<FancyTable>` component listed below.
4343

4444
[!code-razor[FancyTable.razor](../../../samples/components/FancyTable.razor)]
4545

@@ -59,10 +59,6 @@ However, that does not apply to elements that are found by traversing the DOM tr
5959

6060
As a result of this, it is always recommended to use the [`Find(string cssSelector)`](xref:Bunit.RenderedComponentExtensions.Find``1(Bunit.IRenderedComponent{``0},System.String)) method when searching for a single element. Alternatively, always reissue the query whenever you need the element.
6161

62-
#### Auto-refreshable FindAll() queries
63-
64-
The [`FindAll(string cssSelector, bool enableAutoRefresh = false)`](xref:Bunit.RenderedComponentExtensions.FindAll``1(Bunit.IRenderedComponent{``0},System.String,System.Boolean)) method has an optional parameter, `enableAutoRefresh`, which when set to `true` will return a collection of `IElement`. This automatically refreshes itself when the component the elements came from is re-rendered.
65-
6662
## Semantic comparison of markup
6763

6864
Working with raw markup only works well with very simple output, but even then you have to sanitize it to get stable tests. A much better approach is to use the semantic HTML comparer that comes with bUnit.

src/bunit/Extensions/IRefreshableElementCollection.cs

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/bunit/Extensions/Internal/RefreshableElementCollection.cs

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/bunit/Extensions/RenderedComponentExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ public static IElement Find<TComponent>(this IRenderedComponent<TComponent> rend
3636
/// </summary>
3737
/// <param name="renderedComponent">The rendered fragment to search.</param>
3838
/// <param name="cssSelector">The group of selectors to use.</param>
39-
/// <param name="enableAutoRefresh">If true, the returned <see cref="IRefreshableElementCollection{IElement}"/> will automatically refresh its <see cref="IElement"/>s whenever the <paramref name="renderedComponent"/> changes.</param>
40-
/// <returns>An <see cref="IRefreshableElementCollection{IElement}"/>, that can be refreshed to execute the search again.</returns>
41-
public static IRefreshableElementCollection<IElement> FindAll<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, bool enableAutoRefresh = false)
39+
/// <returns>An <see cref="IReadOnlyList{IElement}"/>, that can be refreshed to execute the search again.</returns>
40+
public static IReadOnlyList<IElement> FindAll<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector)
4241
where TComponent : IComponent
4342
{
4443
ArgumentNullException.ThrowIfNull(renderedComponent);
45-
return new RefreshableElementCollection((IRenderedComponent<IComponent>)renderedComponent, cssSelector) { EnableAutoRefresh = enableAutoRefresh };
44+
45+
return renderedComponent.Nodes.QuerySelectorAll(cssSelector).ToArray();
4646
}
4747

4848
/// <summary>

src/bunit/Extensions/WaitForHelpers/RenderedComponentWaitForHelperExtensions.WaitForElement.cs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ public static IElement WaitForElement<TComponent>(this IRenderedComponent<TCompo
4040
/// <param name="renderedComponent">The render fragment or component find the matching element in.</param>
4141
/// <param name="cssSelector">The CSS selector to use to search for elements.</param>
4242
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
43-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
44-
public static IRefreshableElementCollection<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector)
43+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
44+
public static IReadOnlyList<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector)
4545
where TComponent : IComponent => WaitForElementsCore(renderedComponent, cssSelector, matchElementCount: null, timeout: null);
4646

4747
/// <summary>
@@ -52,8 +52,8 @@ public static IRefreshableElementCollection<IElement> WaitForElements<TComponent
5252
/// <param name="cssSelector">The CSS selector to use to search for elements.</param>
5353
/// <param name="matchElementCount">The exact number of elements to that the <paramref name="cssSelector"/> should match.</param>
5454
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
55-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
56-
public static IRefreshableElementCollection<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount)
55+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
56+
public static IReadOnlyList<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount)
5757
where TComponent : IComponent => WaitForElementsCore(renderedComponent, cssSelector, matchElementCount: matchElementCount, timeout: null);
5858

5959
/// <summary>
@@ -64,8 +64,8 @@ public static IRefreshableElementCollection<IElement> WaitForElements<TComponent
6464
/// <param name="cssSelector">The CSS selector to use to search for elements.</param>
6565
/// <param name="timeout">The maximum time to wait for elements to appear.</param>
6666
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
67-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
68-
public static IRefreshableElementCollection<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, TimeSpan timeout)
67+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
68+
public static IReadOnlyList<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, TimeSpan timeout)
6969
where TComponent : IComponent
7070
=> WaitForElementsCore(renderedComponent, cssSelector, matchElementCount: null, timeout: timeout);
7171

@@ -78,8 +78,8 @@ public static IRefreshableElementCollection<IElement> WaitForElements<TComponent
7878
/// <param name="matchElementCount">The exact number of elements to that the <paramref name="cssSelector"/> should match.</param>
7979
/// <param name="timeout">The maximum time to wait for elements to appear.</param>
8080
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
81-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
82-
public static IRefreshableElementCollection<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount, TimeSpan timeout)
81+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
82+
public static IReadOnlyList<IElement> WaitForElements<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount, TimeSpan timeout)
8383
where TComponent : IComponent
8484
=> WaitForElementsCore(renderedComponent, cssSelector, matchElementCount: matchElementCount, timeout: timeout);
8585

@@ -115,8 +115,8 @@ internal static Task<IElement> WaitForElementAsync<TComponent>(this IRenderedCom
115115
/// <param name="cssSelector">The CSS selector to use to search for elements.</param>
116116
/// <param name="matchElementCount">The exact number of elements to that the <paramref name="cssSelector"/> should match.</param>
117117
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
118-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
119-
internal static Task<IRefreshableElementCollection<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount)
118+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
119+
internal static Task<IReadOnlyList<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount)
120120
where TComponent : IComponent
121121
=> WaitForElementsCoreAsync(renderedComponent, cssSelector, matchElementCount: matchElementCount, timeout: null);
122122

@@ -128,8 +128,8 @@ internal static Task<IRefreshableElementCollection<IElement>> WaitForElementsAsy
128128
/// <param name="cssSelector">The CSS selector to use to search for elements.</param>
129129
/// <param name="timeout">The maximum time to wait for elements to appear.</param>
130130
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
131-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
132-
internal static Task<IRefreshableElementCollection<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, TimeSpan timeout)
131+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
132+
internal static Task<IReadOnlyList<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, TimeSpan timeout)
133133
where TComponent : IComponent
134134
=> WaitForElementsCoreAsync(renderedComponent, cssSelector, matchElementCount: null, timeout: timeout);
135135

@@ -142,8 +142,8 @@ internal static Task<IRefreshableElementCollection<IElement>> WaitForElementsAsy
142142
/// <param name="matchElementCount">The exact number of elements to that the <paramref name="cssSelector"/> should match.</param>
143143
/// <param name="timeout">The maximum time to wait for elements to appear.</param>
144144
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
145-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
146-
internal static Task<IRefreshableElementCollection<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount, TimeSpan timeout)
145+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
146+
internal static Task<IReadOnlyList<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector, int matchElementCount, TimeSpan timeout)
147147
where TComponent : IComponent
148148
=> WaitForElementsCoreAsync(renderedComponent, cssSelector, matchElementCount: matchElementCount, timeout: timeout);
149149

@@ -154,8 +154,8 @@ internal static Task<IRefreshableElementCollection<IElement>> WaitForElementsAsy
154154
/// <param name="renderedComponent">The render fragment or component find the matching element in.</param>
155155
/// <param name="cssSelector">The CSS selector to use to search for elements.</param>
156156
/// <exception cref="WaitForFailedException">Thrown if no elements is found matching the <paramref name="cssSelector"/> within the default timeout.</exception>
157-
/// <returns>The <see cref="IRefreshableElementCollection{IElement}"/>.</returns>
158-
internal static Task<IRefreshableElementCollection<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector)
157+
/// <returns>The <see cref="IReadOnlyList{IElement}"/>.</returns>
158+
internal static Task<IReadOnlyList<IElement>> WaitForElementsAsync<TComponent>(this IRenderedComponent<TComponent> renderedComponent, string cssSelector)
159159
where TComponent : IComponent
160160
=> WaitForElementsCoreAsync<TComponent>(renderedComponent, cssSelector, matchElementCount: null, timeout: null);
161161

@@ -185,7 +185,7 @@ private static async Task<IElement> WaitForElementCoreAsync<TComponent>(this IRe
185185
return await waiter.WaitTask;
186186
}
187187

188-
private static IRefreshableElementCollection<IElement> WaitForElementsCore<TComponent>(
188+
private static IReadOnlyList<IElement> WaitForElementsCore<TComponent>(
189189
this IRenderedComponent<TComponent> renderedComponent,
190190
string cssSelector,
191191
int? matchElementCount,
@@ -207,7 +207,7 @@ private static IRefreshableElementCollection<IElement> WaitForElementsCore<TComp
207207
}
208208
}
209209

210-
private static async Task<IRefreshableElementCollection<IElement>> WaitForElementsCoreAsync<TComponent>(
210+
private static async Task<IReadOnlyList<IElement>> WaitForElementsCoreAsync<TComponent>(
211211
this IRenderedComponent<TComponent> renderedComponent,
212212
string cssSelector,
213213
int? matchElementCount,

src/bunit/Extensions/WaitForHelpers/WaitForElementsHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Bunit.Extensions.WaitForHelpers;
77
/// <summary>
88
/// Represents an async wait helper, that will wait for a specified time for element(s) to become available in the DOM.
99
/// </summary>
10-
internal class WaitForElementsHelper<TComponent> : WaitForHelper<IRefreshableElementCollection<IElement>, TComponent>
10+
internal class WaitForElementsHelper<TComponent> : WaitForHelper<IReadOnlyList<IElement>, TComponent>
1111
where TComponent : IComponent
1212
{
1313
internal const string TimeoutBeforeFoundMessage = "The CSS selector did not result in any matching element(s) before the timeout period passed.";

0 commit comments

Comments
 (0)