Skip to content

Commit 91b4ac8

Browse files
authored
Fixed Internal Attributes #111 (#112)
* Fixed Internal Attributes #111 Signed-off-by: samtrion <me@samtrion.net> * Fixed spacing * Fixed spacing, second try * I'm so sorry, please squash * Update src/bunit.web/Rendering/Internal/Htmlizer.cs Co-Authored-By: Egil Hansen <egil@assimilated.dk> * Added theory for handling internal attributes Signed-off-by: samtrion <me@samtrion.net> * Added explanation Signed-off-by: samtrion <me@samtrion.net> * Added test, which confirms correctly prefixed attributes Signed-off-by: samtrion <me@samtrion.net>
1 parent c58fabd commit 91b4ac8

2 files changed

Lines changed: 109 additions & 0 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
namespace Bunit.Rendering.Internal
2+
{
3+
using Microsoft.AspNetCore.Components;
4+
using Microsoft.AspNetCore.Components.Rendering;
5+
using Microsoft.AspNetCore.Components.Web;
6+
using Xunit;
7+
8+
public class HtmlizerTests : ComponentTestFixture
9+
{
10+
public static TheoryData GetOnClickData()
11+
{
12+
return new TheoryData<bool, bool>
13+
{
14+
{ false, true },
15+
{ true, false },
16+
{ true, true }
17+
};
18+
}
19+
20+
[Theory(DisplayName =
21+
"The component is rendered without internal Blazor attributes, " +
22+
"regardless of the PreventDefault and StopPropagation settings.")]
23+
[MemberData(nameof(GetOnClickData))]
24+
public void Test001(bool stopPropagation, bool preventDefault)
25+
{
26+
//Arrange
27+
var component = RenderComponent<Htmlizer01Component>(
28+
EventCallback<MouseEventArgs>(nameof(Htmlizer01Component.OnClick), OnClickCallback),
29+
Parameter(nameof(Htmlizer01Component.OnClickStopPropagation), stopPropagation),
30+
Parameter(nameof(Htmlizer01Component.OnClickPreventDefault), preventDefault));
31+
32+
//Act
33+
34+
//Assert
35+
component.MarkupMatches("<button type=\"button\">Click me!</button>");
36+
void OnClickCallback(MouseEventArgs e)
37+
{
38+
// NOTE: This line is only for the completeness of the EventCallback
39+
Assert.NotNull(e);
40+
}
41+
}
42+
43+
[Theory(DisplayName = "The component contains correctly prefixed internal attributes.")]
44+
[MemberData(nameof(GetOnClickData))]
45+
public void Test002(bool stopPropagation, bool preventDefault)
46+
{
47+
//Arrange
48+
var component = RenderComponent<Htmlizer01Component>(
49+
EventCallback<MouseEventArgs>(nameof(Htmlizer01Component.OnClick), OnClickCallback),
50+
Parameter(nameof(Htmlizer01Component.OnClickStopPropagation), stopPropagation),
51+
Parameter(nameof(Htmlizer01Component.OnClickPreventDefault), preventDefault));
52+
53+
//Act
54+
var button = component.Find("button");
55+
56+
//Assert
57+
Assert.Equal(stopPropagation, button.HasAttribute("blazor:__internal_stopPropagation_onclick"));
58+
Assert.Equal(preventDefault, button.HasAttribute("blazor:__internal_preventDefault_onclick"));
59+
60+
void OnClickCallback(MouseEventArgs e)
61+
{
62+
// NOTE: This line is only for the completeness of the EventCallback
63+
Assert.NotNull(e);
64+
}
65+
}
66+
67+
private class Htmlizer01Component : ComponentBase
68+
{
69+
[Parameter]
70+
public EventCallback<MouseEventArgs> OnClick { get; set; }
71+
72+
[Parameter]
73+
public bool OnClickPreventDefault { get; set; }
74+
75+
[Parameter]
76+
public bool OnClickStopPropagation { get; set; }
77+
78+
/// <inheritdoc />
79+
protected override void BuildRenderTree(RenderTreeBuilder builder)
80+
{
81+
base.BuildRenderTree(builder);
82+
83+
builder.OpenElement(0, "button");
84+
builder.AddAttribute(1, "type", "button");
85+
86+
if (OnClick.HasDelegate)
87+
{
88+
builder.AddAttribute(2, "onclick", Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, OnClick));
89+
builder.AddEventStopPropagationAttribute(3, "onclick", OnClickStopPropagation);
90+
builder.AddEventPreventDefaultAttribute(4, "onclick", OnClickPreventDefault);
91+
}
92+
93+
builder.AddContent(5, "Click me!");
94+
95+
builder.CloseElement();
96+
}
97+
}
98+
}
99+
}

src/bunit.web/Rendering/Internal/Htmlizer.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ internal class Htmlizer
2020
"area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"
2121
};
2222

23+
private const string BLAZOR_INTERNAL_ATTR_PREFIX = "__internal_";
24+
2325
public const string BLAZOR_ATTR_PREFIX = "blazor:";
2426
public const string ELEMENT_REFERENCE_ATTR_NAME = BLAZOR_ATTR_PREFIX + "elementreference";
2527

@@ -220,6 +222,14 @@ private static int RenderAttributes(
220222

221223
switch (frame.AttributeValue)
222224
{
225+
case bool flag when flag && frame.AttributeName.StartsWith(BLAZOR_INTERNAL_ATTR_PREFIX, StringComparison.Ordinal):
226+
// NOTE: This was added to make it more obvious
227+
// that this is a generated/special blazor attribute
228+
// for internal usage
229+
result.Add(" ");
230+
result.Add(BLAZOR_ATTR_PREFIX);
231+
result.Add(frame.AttributeName);
232+
break;
223233
case bool flag when flag:
224234
result.Add(" ");
225235
result.Add(frame.AttributeName);

0 commit comments

Comments
 (0)