Skip to content

Commit

Permalink
move to element factory to prevent re-renders causing issues
Browse files Browse the repository at this point in the history
  • Loading branch information
scottsauber committed Nov 13, 2023
1 parent 5bbb5f2 commit 8617b7b
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 26 deletions.
35 changes: 35 additions & 0 deletions src/bunit.web.query/ByLabelTextElementFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using AngleSharp.Dom;

namespace Bunit;

using AngleSharpWrappers;


internal sealed class ByLabelTextElementFactory<TElement> : IElementFactory<TElement>
where TElement : class, IElement
{
private readonly IRenderedFragment testTarget;
private readonly string labelText;
private TElement? element;

public ByLabelTextElementFactory(IRenderedFragment testTarget, TElement initialElement, string labelText)
{
this.testTarget = testTarget;
element = initialElement;
this.labelText = labelText;
testTarget.OnMarkupUpdated += FragmentsMarkupUpdated;
}

private void FragmentsMarkupUpdated(object? sender, EventArgs args) => element = null;

TElement IElementFactory<TElement>.GetElement()
{
if (element is null)
{
var queryResult = testTarget.FindByLabelTextInternal(labelText);
element = queryResult as TElement;
}

return element ?? throw new ElementRemovedFromDomException(labelText);
}
}
156 changes: 156 additions & 0 deletions src/bunit.web.query/ElementWrapperFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using AngleSharp.Dom;
using AngleSharp.Html.Dom;
using AngleSharp.Svg.Dom;
using AngleSharpWrappers;

namespace Bunit;

internal static class ElementWrapperFactory
{
public static IElement CreateByLabelText(IElement element, IRenderedFragment renderedFragment, string labelText)
{
return element switch
{
IHtmlAnchorElement htmlAnchorElement => new HtmlAnchorElementWrapper(
new ByLabelTextElementFactory<IHtmlAnchorElement>(renderedFragment, htmlAnchorElement, labelText)),
IHtmlAreaElement htmlAreaElement => new HtmlAreaElementWrapper(
new ByLabelTextElementFactory<IHtmlAreaElement>(renderedFragment, htmlAreaElement, labelText)),
IHtmlAudioElement htmlAudioElement => new HtmlAudioElementWrapper(
new ByLabelTextElementFactory<IHtmlAudioElement>(renderedFragment, htmlAudioElement, labelText)),
IHtmlBaseElement htmlBaseElement => new HtmlBaseElementWrapper(
new ByLabelTextElementFactory<IHtmlBaseElement>(renderedFragment, htmlBaseElement, labelText)),
IHtmlBodyElement htmlBodyElement => new HtmlBodyElementWrapper(
new ByLabelTextElementFactory<IHtmlBodyElement>(renderedFragment, htmlBodyElement, labelText)),
IHtmlBreakRowElement htmlBreakRowElement => new HtmlBreakRowElementWrapper(
new ByLabelTextElementFactory<IHtmlBreakRowElement>(renderedFragment, htmlBreakRowElement, labelText)),
IHtmlButtonElement htmlButtonElement => new HtmlButtonElementWrapper(
new ByLabelTextElementFactory<IHtmlButtonElement>(renderedFragment, htmlButtonElement, labelText)),
IHtmlCanvasElement htmlCanvasElement => new HtmlCanvasElementWrapper(
new ByLabelTextElementFactory<IHtmlCanvasElement>(renderedFragment, htmlCanvasElement, labelText)),
IHtmlCommandElement htmlCommandElement => new HtmlCommandElementWrapper(
new ByLabelTextElementFactory<IHtmlCommandElement>(renderedFragment, htmlCommandElement, labelText)),
IHtmlDataElement htmlDataElement => new HtmlDataElementWrapper(
new ByLabelTextElementFactory<IHtmlDataElement>(renderedFragment, htmlDataElement, labelText)),
IHtmlDataListElement htmlDataListElement => new HtmlDataListElementWrapper(
new ByLabelTextElementFactory<IHtmlDataListElement>(renderedFragment, htmlDataListElement, labelText)),
IHtmlDetailsElement htmlDetailsElement => new HtmlDetailsElementWrapper(
new ByLabelTextElementFactory<IHtmlDetailsElement>(renderedFragment, htmlDetailsElement, labelText)),
IHtmlDialogElement htmlDialogElement => new HtmlDialogElementWrapper(
new ByLabelTextElementFactory<IHtmlDialogElement>(renderedFragment, htmlDialogElement, labelText)),
IHtmlDivElement htmlDivElement => new HtmlDivElementWrapper(
new ByLabelTextElementFactory<IHtmlDivElement>(renderedFragment, htmlDivElement, labelText)),
IHtmlEmbedElement htmlEmbedElement => new HtmlEmbedElementWrapper(
new ByLabelTextElementFactory<IHtmlEmbedElement>(renderedFragment, htmlEmbedElement, labelText)),
IHtmlFieldSetElement htmlFieldSetElement => new HtmlFieldSetElementWrapper(
new ByLabelTextElementFactory<IHtmlFieldSetElement>(renderedFragment, htmlFieldSetElement, labelText)),
IHtmlFormElement htmlFormElement => new HtmlFormElementWrapper(
new ByLabelTextElementFactory<IHtmlFormElement>(renderedFragment, htmlFormElement, labelText)),
IHtmlHeadElement htmlHeadElement => new HtmlHeadElementWrapper(
new ByLabelTextElementFactory<IHtmlHeadElement>(renderedFragment, htmlHeadElement, labelText)),
IHtmlHeadingElement htmlHeadingElement => new HtmlHeadingElementWrapper(
new ByLabelTextElementFactory<IHtmlHeadingElement>(renderedFragment, htmlHeadingElement, labelText)),
IHtmlHrElement htmlHrElement => new HtmlHrElementWrapper(
new ByLabelTextElementFactory<IHtmlHrElement>(renderedFragment, htmlHrElement, labelText)),
IHtmlHtmlElement htmlHtmlElement => new HtmlHtmlElementWrapper(
new ByLabelTextElementFactory<IHtmlHtmlElement>(renderedFragment, htmlHtmlElement, labelText)),
IHtmlImageElement htmlImageElement => new HtmlImageElementWrapper(
new ByLabelTextElementFactory<IHtmlImageElement>(renderedFragment, htmlImageElement, labelText)),
IHtmlInlineFrameElement htmlInlineFrameElement => new HtmlInlineFrameElementWrapper(
new ByLabelTextElementFactory<IHtmlInlineFrameElement>(renderedFragment, htmlInlineFrameElement, labelText)),
IHtmlInputElement htmlInputElement => new HtmlInputElementWrapper(
new ByLabelTextElementFactory<IHtmlInputElement>(renderedFragment, htmlInputElement, labelText)),
IHtmlKeygenElement htmlKeygenElement => new HtmlKeygenElementWrapper(
new ByLabelTextElementFactory<IHtmlKeygenElement>(renderedFragment, htmlKeygenElement, labelText)),
IHtmlLabelElement htmlLabelElement => new HtmlLabelElementWrapper(
new ByLabelTextElementFactory<IHtmlLabelElement>(renderedFragment, htmlLabelElement, labelText)),
IHtmlLegendElement htmlLegendElement => new HtmlLegendElementWrapper(
new ByLabelTextElementFactory<IHtmlLegendElement>(renderedFragment, htmlLegendElement, labelText)),
IHtmlLinkElement htmlLinkElement => new HtmlLinkElementWrapper(
new ByLabelTextElementFactory<IHtmlLinkElement>(renderedFragment, htmlLinkElement, labelText)),
IHtmlListItemElement htmlListItemElement => new HtmlListItemElementWrapper(
new ByLabelTextElementFactory<IHtmlListItemElement>(renderedFragment, htmlListItemElement, labelText)),
IHtmlMapElement htmlMapElement => new HtmlMapElementWrapper(
new ByLabelTextElementFactory<IHtmlMapElement>(renderedFragment, htmlMapElement, labelText)),
IHtmlMarqueeElement htmlMarqueeElement => new HtmlMarqueeElementWrapper(
new ByLabelTextElementFactory<IHtmlMarqueeElement>(renderedFragment, htmlMarqueeElement, labelText)),
IHtmlMenuElement htmlMenuElement => new HtmlMenuElementWrapper(
new ByLabelTextElementFactory<IHtmlMenuElement>(renderedFragment, htmlMenuElement, labelText)),
IHtmlMenuItemElement htmlMenuItemElement => new HtmlMenuItemElementWrapper(
new ByLabelTextElementFactory<IHtmlMenuItemElement>(renderedFragment, htmlMenuItemElement, labelText)),
IHtmlMetaElement htmlMetaElement => new HtmlMetaElementWrapper(
new ByLabelTextElementFactory<IHtmlMetaElement>(renderedFragment, htmlMetaElement, labelText)),
IHtmlMeterElement htmlMeterElement => new HtmlMeterElementWrapper(
new ByLabelTextElementFactory<IHtmlMeterElement>(renderedFragment, htmlMeterElement, labelText)),
IHtmlModElement htmlModElement => new HtmlModElementWrapper(
new ByLabelTextElementFactory<IHtmlModElement>(renderedFragment, htmlModElement, labelText)),
IHtmlObjectElement htmlObjectElement => new HtmlObjectElementWrapper(
new ByLabelTextElementFactory<IHtmlObjectElement>(renderedFragment, htmlObjectElement, labelText)),
IHtmlOrderedListElement htmlOrderedListElement => new HtmlOrderedListElementWrapper(
new ByLabelTextElementFactory<IHtmlOrderedListElement>(renderedFragment, htmlOrderedListElement, labelText)),
IHtmlParagraphElement htmlParagraphElement => new HtmlParagraphElementWrapper(
new ByLabelTextElementFactory<IHtmlParagraphElement>(renderedFragment, htmlParagraphElement, labelText)),
IHtmlParamElement htmlParamElement => new HtmlParamElementWrapper(
new ByLabelTextElementFactory<IHtmlParamElement>(renderedFragment, htmlParamElement, labelText)),
IHtmlPreElement htmlPreElement => new HtmlPreElementWrapper(
new ByLabelTextElementFactory<IHtmlPreElement>(renderedFragment, htmlPreElement, labelText)),
IHtmlProgressElement htmlProgressElement => new HtmlProgressElementWrapper(
new ByLabelTextElementFactory<IHtmlProgressElement>(renderedFragment, htmlProgressElement, labelText)),
IHtmlQuoteElement htmlQuoteElement => new HtmlQuoteElementWrapper(
new ByLabelTextElementFactory<IHtmlQuoteElement>(renderedFragment, htmlQuoteElement, labelText)),
IHtmlScriptElement htmlScriptElement => new HtmlScriptElementWrapper(
new ByLabelTextElementFactory<IHtmlScriptElement>(renderedFragment, htmlScriptElement, labelText)),
IHtmlSelectElement htmlSelectElement => new HtmlSelectElementWrapper(
new ByLabelTextElementFactory<IHtmlSelectElement>(renderedFragment, htmlSelectElement, labelText)),
IHtmlSourceElement htmlSourceElement => new HtmlSourceElementWrapper(
new ByLabelTextElementFactory<IHtmlSourceElement>(renderedFragment, htmlSourceElement, labelText)),
IHtmlSpanElement htmlSpanElement => new HtmlSpanElementWrapper(
new ByLabelTextElementFactory<IHtmlSpanElement>(renderedFragment, htmlSpanElement, labelText)),
IHtmlStyleElement htmlStyleElement => new HtmlStyleElementWrapper(
new ByLabelTextElementFactory<IHtmlStyleElement>(renderedFragment, htmlStyleElement, labelText)),
IHtmlTableCaptionElement htmlTableCaptionElement => new HtmlTableCaptionElementWrapper(
new ByLabelTextElementFactory<IHtmlTableCaptionElement>(renderedFragment, htmlTableCaptionElement, labelText)),
IHtmlTableCellElement htmlTableCellElement => new HtmlTableCellElementWrapper(
new ByLabelTextElementFactory<IHtmlTableCellElement>(renderedFragment, htmlTableCellElement, labelText)),
IHtmlTableElement htmlTableElement => new HtmlTableElementWrapper(
new ByLabelTextElementFactory<IHtmlTableElement>(renderedFragment, htmlTableElement, labelText)),
IHtmlTableRowElement htmlTableRowElement => new HtmlTableRowElementWrapper(
new ByLabelTextElementFactory<IHtmlTableRowElement>(renderedFragment, htmlTableRowElement, labelText)),
IHtmlTableSectionElement htmlTableSectionElement => new HtmlTableSectionElementWrapper(
new ByLabelTextElementFactory<IHtmlTableSectionElement>(renderedFragment, htmlTableSectionElement, labelText)),
IHtmlTemplateElement htmlTemplateElement => new HtmlTemplateElementWrapper(
new ByLabelTextElementFactory<IHtmlTemplateElement>(renderedFragment, htmlTemplateElement, labelText)),
IHtmlTextAreaElement htmlTextAreaElement => new HtmlTextAreaElementWrapper(
new ByLabelTextElementFactory<IHtmlTextAreaElement>(renderedFragment, htmlTextAreaElement, labelText)),
IHtmlTimeElement htmlTimeElement => new HtmlTimeElementWrapper(
new ByLabelTextElementFactory<IHtmlTimeElement>(renderedFragment, htmlTimeElement, labelText)),
IHtmlTitleElement htmlTitleElement => new HtmlTitleElementWrapper(
new ByLabelTextElementFactory<IHtmlTitleElement>(renderedFragment, htmlTitleElement, labelText)),
IHtmlTrackElement htmlTrackElement => new HtmlTrackElementWrapper(
new ByLabelTextElementFactory<IHtmlTrackElement>(renderedFragment, htmlTrackElement, labelText)),
IHtmlUnknownElement htmlUnknownElement => new HtmlUnknownElementWrapper(
new ByLabelTextElementFactory<IHtmlUnknownElement>(renderedFragment, htmlUnknownElement, labelText)),
IHtmlVideoElement htmlVideoElement => new HtmlVideoElementWrapper(
new ByLabelTextElementFactory<IHtmlVideoElement>(renderedFragment, htmlVideoElement, labelText)),
IHtmlMediaElement htmlMediaElement => new HtmlMediaElementWrapper(
new ByLabelTextElementFactory<IHtmlMediaElement>(renderedFragment, htmlMediaElement, labelText)),
IPseudoElement pseudoElement => new PseudoElementWrapper(
new ByLabelTextElementFactory<IPseudoElement>(renderedFragment, pseudoElement, labelText)),
ISvgCircleElement svgCircleElement => new SvgCircleElementWrapper(
new ByLabelTextElementFactory<ISvgCircleElement>(renderedFragment, svgCircleElement, labelText)),
ISvgDescriptionElement svgDescriptionElement => new SvgDescriptionElementWrapper(
new ByLabelTextElementFactory<ISvgDescriptionElement>(renderedFragment, svgDescriptionElement, labelText)),
ISvgForeignObjectElement svgForeignObjectElement => new SvgForeignObjectElementWrapper(
new ByLabelTextElementFactory<ISvgForeignObjectElement>(renderedFragment, svgForeignObjectElement, labelText)),
ISvgSvgElement svgSvgElement => new SvgSvgElementWrapper(
new ByLabelTextElementFactory<ISvgSvgElement>(renderedFragment, svgSvgElement, labelText)),
ISvgTitleElement svgTitleElement => new SvgTitleElementWrapper(
new ByLabelTextElementFactory<ISvgTitleElement>(renderedFragment, svgTitleElement, labelText)),
ISvgElement svgElement => new SvgElementWrapper(
new ByLabelTextElementFactory<ISvgElement>(renderedFragment, svgElement, labelText)),
IHtmlElement htmlElement => new HtmlElementWrapper(
new ByLabelTextElementFactory<IHtmlElement>(renderedFragment, htmlElement, labelText)),
_ => new ElementWrapper(
new ByLabelTextElementFactory<IElement>(renderedFragment, element, labelText)),
};
}
}
15 changes: 13 additions & 2 deletions src/bunit.web.query/Labels/LabelQueryExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AngleSharp.Dom;
using Bunit.Labels.Strategies;

namespace Bunit;

Expand All @@ -19,6 +20,16 @@ public static class LabelQueryExtensions
/// <param name="renderedFragment">The rendered fragment to search.</param>
/// <param name="labelText">The text of the label to search (i.e. the InnerText of the Label, such as "First Name" for a `<label>First Name</label>`)</param>
public static IElement FindByLabelText(this IRenderedFragment renderedFragment, string labelText)
{
return FindByLabelTextInternal(renderedFragment, labelText) ?? throw new ElementNotFoundException(labelText);
}

/// <summary>
/// Returns the first element (i.e. an input, select, textarea, etc. element) associated with the given label text.
/// </summary>
/// <param name="renderedFragment">The rendered fragment to search.</param>
/// <param name="labelText">The text of the label to search (i.e. the InnerText of the Label, such as "First Name" for a `<label>First Name</label>`)</param>
internal static IElement? FindByLabelTextInternal(this IRenderedFragment renderedFragment, string labelText)
{
try
{
Expand All @@ -32,9 +43,9 @@ public static IElement FindByLabelText(this IRenderedFragment renderedFragment,
}
catch (DomException exception) when (exception.Message == "The string did not match the expected pattern.")
{
throw new ElementNotFoundException(labelText);
return null;
}

throw new ElementNotFoundException(labelText);
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using AngleSharp.Dom;

namespace Bunit;
namespace Bunit.Labels.Strategies;

internal interface ILabelTextQueryStrategy
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using AngleSharp.Dom;

namespace Bunit;
namespace Bunit.Labels.Strategies;

internal class LabelTextUsingAriaLabelStrategy : ILabelTextQueryStrategy

Check failure on line 5 in src/bunit.web.query/Labels/Strategies/LabelTextUsingAriaLabelStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

Type 'LabelTextUsingAriaLabelStrategy' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
public IElement? FindElement(IRenderedFragment renderedFragment, string labelText)
{
var results = renderedFragment.FindAll($"[aria-label='{labelText}']");
var element = renderedFragment.Nodes.QuerySelector($"[aria-label='{labelText}']");

return results.Count == 0
? null
: results[0];
if (element is null)
return null;

return ElementWrapperFactory.CreateByLabelText(element, renderedFragment, labelText);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
using AngleSharp.Dom;

namespace Bunit;
namespace Bunit.Labels.Strategies;

internal class LabelTextUsingAriaLabelledByStrategy : ILabelTextQueryStrategy

Check failure on line 5 in src/bunit.web.query/Labels/Strategies/LabelTextUsingAriaLabelledByStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

Type 'LabelTextUsingAriaLabelledByStrategy' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
public IElement? FindElement(IRenderedFragment renderedFragment, string labelText)
{
var elementsWithAriaLabelledBy = renderedFragment.FindAll("[aria-labelledby]");
var elementsWithAriaLabelledBy = renderedFragment.Nodes.QuerySelectorAll("[aria-labelledby]");

foreach (var element in elementsWithAriaLabelledBy)
{
var labelElements = renderedFragment.FindAll($"#{element.GetAttribute("aria-labelledby")}");
if (labelElements.Count > 0 && labelElements[0].GetInnerText() == labelText)
return element;
var labelElement = renderedFragment.Nodes.QuerySelector($"#{element.GetAttribute("aria-labelledby")}");
if (labelElement.GetInnerText() == labelText)
return ElementWrapperFactory.CreateByLabelText(element, renderedFragment, labelText);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
using AngleSharp.Dom;

namespace Bunit;
namespace Bunit.Labels.Strategies;

internal class LabelTextUsingForAttributeStrategy : ILabelTextQueryStrategy

Check failure on line 5 in src/bunit.web.query/Labels/Strategies/LabelTextUsingForAttributeStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

Type 'LabelTextUsingForAttributeStrategy' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 5 in src/bunit.web.query/Labels/Strategies/LabelTextUsingForAttributeStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

Type 'LabelTextUsingForAttributeStrategy' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
public IElement? FindElement(IRenderedFragment renderedFragment, string labelText)
{
var labels = renderedFragment.FindAll("label");
var labels = renderedFragment.Nodes.QuerySelectorAll("label");
var matchingLabel = labels.SingleOrDefault(l => l.TextContent == labelText);

return matchingLabel == null
? null
: renderedFragment.Find($"#{matchingLabel.GetAttribute("for")}");
if (matchingLabel is null)
return null;

var matchingElement = renderedFragment.Nodes.QuerySelector($"#{matchingLabel.GetAttribute("for")}");

if (matchingElement is null)
return null;

return ElementWrapperFactory.CreateByLabelText(matchingElement, renderedFragment, labelText);
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
using AngleSharp.Dom;

namespace Bunit;
namespace Bunit.Labels.Strategies;

internal class LabelTextUsingWrappedElementStrategy : ILabelTextQueryStrategy

Check failure on line 5 in src/bunit.web.query/Labels/Strategies/LabelTextUsingWrappedElementStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

Type 'LabelTextUsingWrappedElementStrategy' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)

Check failure on line 5 in src/bunit.web.query/Labels/Strategies/LabelTextUsingWrappedElementStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

Type 'LabelTextUsingWrappedElementStrategy' can be sealed because it has no subtypes in its containing assembly and is not externally visible (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852)
{
public IElement? FindElement(IRenderedFragment renderedFragment, string labelText)
{
var labels = renderedFragment.FindAll("label");
var labels = renderedFragment.Nodes.QuerySelectorAll("label");
var matchingLabel = labels.SingleOrDefault(l => l.InnerHtml.StartsWith(labelText));

Check failure on line 10 in src/bunit.web.query/Labels/Strategies/LabelTextUsingWrappedElementStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'Bunit.Labels.Strategies.LabelTextUsingWrappedElementStrategy.FindElement(Bunit.IRenderedFragment, string)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

Check failure on line 10 in src/bunit.web.query/Labels/Strategies/LabelTextUsingWrappedElementStrategy.cs

View workflow job for this annotation

GitHub Actions / 👌 Verify bUnit (windows-latest)

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'Bunit.Labels.Strategies.LabelTextUsingWrappedElementStrategy.FindElement(Bunit.IRenderedFragment, string)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

return matchingLabel?
var matchingElement = matchingLabel?
.Children
.SingleOrDefault(n => n.IsHtmlElementThatCanHaveALabel());

if (matchingElement is null)
return null;

return ElementWrapperFactory.CreateByLabelText(matchingElement, renderedFragment, labelText);
}
}
1 change: 1 addition & 0 deletions src/bunit.web.query/bunit.web.query.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AngleSharpWrappers\AngleSharpWrappers.csproj" />
<ProjectReference Include="..\bunit.web\bunit.web.csproj" />
</ItemGroup>

Expand Down
16 changes: 14 additions & 2 deletions tests/bunit.testassets/BlazorE2E/LabelQueryComponent.razor
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,20 @@
@((MarkupString) $"""<{htmlElement} aria-labelledby="{htmlElement}-with-aria-labelledby"></{htmlElement}>""")
}

@* Testing we get back the re-rendered element *@
<input id="re-rendered-element" @bind="@_count" aria-label="Re-rendered Element" />

@* Testing we get back the re-rendered element for an aria-label *@
<label for="re-rendered-input-with-label">Re-rendered input with label</label>
<input @bind="@_count" id="re-rendered-input-with-label" />

<label>Re-rendered input with wrapped label
<input @bind="@_count" />
</label>

<input @bind="@_count" aria-label="Re-rendered input With Aria Label" />

<h2 id="re-rendered-input-with-aria-labelledby">Re-rendered input with Aria Labelledby</h2>
<input aria-labelledby="re-rendered-input-with-aria-labelledby" @bind="@_count" />

<button id="increment-button" @onclick="IncrementCount">Click</button>

@code {
Expand Down

0 comments on commit 8617b7b

Please sign in to comment.