Skip to content

Commit 75d01f4

Browse files
authored
Merge pull request #1001 from bUnit-dev/release/v1.18
Release of new minor version v1.18
2 parents 997a71a + 63c1f53 commit 75d01f4

File tree

17 files changed

+554
-370
lines changed

17 files changed

+554
-370
lines changed

.editorconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,4 @@ dotnet_diagnostic.S125.severity = none # S125: Sections of code should not be co
504504
dotnet_diagnostic.S3459.severity = none # S3459: Unassigned members should be removed
505505
dotnet_diagnostic.S3871.severity = none # S3871: Exception types should be "public"
506506
dotnet_diagnostic.S1186.severity = none # S1186: Methods should not be empty
507+
dotnet_diagnostic.S1133.severity = none # S1133: Deprecated code should be removed

CHANGELOG.md

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

77
## [Unreleased]
88

9+
### Fixed
10+
11+
- Some characters where not properly escaped. Reported by [@pwhe23](https://github.com/pwhe23). Fixed by [@linkdotnet](https://github.com/linkdotnet).
12+
- Clicking a submit button or submit input element inside a form, submits the form, if the submit button or submit input element does not have the `@onclick:preventDefault` attribute set. Reported by [@linkdotnet](https://github.com/linkdotnet). Fixed by [@egil](https://github.com/egil).
13+
914
## [1.17.2] - 2023-02-22
1015

1116
- Submit buttons and input fields now no longer cause a form submit when they have the `@onclick:preventDefault` attribute. By [@JelleHissink](https://github.com/JelleHissink).

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
<!-- Shared code analyzers used for all projects in the solution -->
5151
<ItemGroup Label="Code Analyzers">
5252
<PackageReference Include="AsyncFixer" Version="1.6.0" PrivateAssets="All" />
53-
<PackageReference Include="SonarAnalyzer.CSharp" Version="8.52.0.60960" PrivateAssets="All" />
53+
<PackageReference Include="SonarAnalyzer.CSharp" Version="8.53.0.62665" PrivateAssets="All" />
5454
</ItemGroup>
5555

5656
<ItemGroup Label="Implicit usings"

src/.editorconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,5 @@
3636
##########################################
3737
# Custom - Code Analyzers Rules
3838
##########################################
39+
40+
dotnet_diagnostic.S1133.severity = none # S1133: Deprecated code should be removed

src/bunit.web/ComponentFactories/StubComponentFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public bool CanCreate(Type componentType)
2222
public IComponent Create(Type componentType)
2323
{
2424
var typeToCreate = StubType.MakeGenericType(componentType);
25-
return (IComponent)Activator.CreateInstance(typeToCreate, new object?[] { replacementContent })!;
25+
return (IComponent)Activator.CreateInstance(typeToCreate, replacementContent)!;
2626
}
2727
}
2828
#endif

src/bunit.web/EventDispatchExtensions/TriggerEventDispatchExtensions.cs

Lines changed: 58 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,14 @@ public static void TriggerEvent(this IElement element, string eventName, EventAr
6060
public static Task TriggerEventAsync(this IElement element, string eventName, EventArgs eventArgs)
6161
{
6262
if (element is null)
63+
{
6364
throw new ArgumentNullException(nameof(element));
65+
}
66+
6467
if (eventName is null)
68+
{
6569
throw new ArgumentNullException(nameof(eventName));
70+
}
6671

6772
var renderer = element.GetTestContext()?.Renderer
6873
?? throw new InvalidOperationException($"Blazor events can only be raised on elements rendered with the Blazor test renderer '{nameof(ITestRenderer)}'.");
@@ -80,49 +85,41 @@ public static Task TriggerEventAsync(this IElement element, string eventName, Ev
8085
}
8186

8287
[SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "HTML events are standardize to lower case and safe in this context.")]
83-
private static async Task TriggerEventsAsync(ITestRenderer renderer, IElement element, string eventName, EventArgs eventArgs)
88+
private static Task TriggerEventsAsync(ITestRenderer renderer, IElement element, string eventName, EventArgs eventArgs)
8489
{
8590
var isNonBubblingEvent = NonBubblingEvents.Contains(eventName.ToLowerInvariant());
8691
var unwrappedElement = element.Unwrap();
87-
if (isNonBubblingEvent)
88-
await TriggerNonBubblingEventAsync(renderer, unwrappedElement, eventName, eventArgs);
89-
else
90-
await TriggerBubblingEventAsync(renderer, unwrappedElement, eventName, eventArgs);
9192

92-
switch (unwrappedElement)
93-
{
94-
case IHtmlInputElement { Type: "submit", Form: not null } input when eventName is "onclick":
95-
await TriggerFormSubmitAsync(renderer, input, eventArgs, input.Form);
96-
break;
97-
case IHtmlButtonElement { Type: "submit", Form: not null } button when eventName is "onclick":
98-
await TriggerFormSubmitAsync(renderer, button, eventArgs, button.Form);
99-
break;
100-
}
93+
return isNonBubblingEvent
94+
? TriggerNonBubblingEventAsync(renderer, unwrappedElement, eventName, eventArgs)
95+
: TriggerBubblingEventAsync(renderer, unwrappedElement, eventName, eventArgs);
10196
}
10297

103-
private static Task TriggerFormSubmitAsync(ITestRenderer renderer, IElement element, EventArgs eventArgs, IHtmlFormElement form)
98+
private static Task TriggerNonBubblingEventAsync(ITestRenderer renderer, IElement element, string eventName, EventArgs eventArgs)
10499
{
105-
const string eventName = "onclick";
106-
107100
var eventAttrName = Htmlizer.ToBlazorAttribute(eventName);
108-
var preventDefaultAttrName = $"{eventAttrName}:preventdefault";
109-
if (element.HasAttribute(preventDefaultAttrName))
110-
return Task.CompletedTask;
111101

112-
var events = GetDispatchEventTasks(renderer, form, "onsubmit", eventArgs);
102+
if (string.Equals(eventName, "onsubmit", StringComparison.Ordinal) && element is not IHtmlFormElement)
103+
{
104+
throw new InvalidOperationException("Only forms can have a onsubmit event");
105+
}
113106

114-
if (events.Count == 0)
115-
throw new MissingEventHandlerException(element, eventName);
107+
if (element.TryGetEventId(eventAttrName, out var id))
108+
{
109+
return renderer.DispatchEventAsync(id, new EventFieldInfo { FieldValue = eventName }, eventArgs);
110+
}
116111

117-
return Task.WhenAll(events);
112+
throw new MissingEventHandlerException(element, eventName);
118113
}
119114

120115
private static Task TriggerBubblingEventAsync(ITestRenderer renderer, IElement element, string eventName, EventArgs eventArgs)
121116
{
122117
var eventTasks = GetDispatchEventTasks(renderer, element, eventName, eventArgs);
123118

124119
if (eventTasks.Count == 0)
120+
{
125121
throw new MissingEventHandlerException(element, eventName);
122+
}
126123

127124
return Task.WhenAll(eventTasks);
128125
}
@@ -139,10 +136,17 @@ private static List<Task> GetDispatchEventTasks(
139136

140137
foreach (var candidate in element.GetParentsAndSelf())
141138
{
142-
if (candidate.TryGetEventId(eventAttrName, out var id))
139+
if (candidate.TryGetEventId(eventAttrName, out var eventId))
143140
{
144141
var info = new EventFieldInfo { FieldValue = eventName };
145-
eventTasks.Add(renderer.DispatchEventAsync(id, info, eventArgs, ignoreUnknownEventHandlers: eventTasks.Count > 0));
142+
eventTasks.Add(renderer.DispatchEventAsync(eventId, info, eventArgs, ignoreUnknownEventHandlers: eventTasks.Count > 0));
143+
}
144+
145+
// Special case for elements inside form elements
146+
if (TryGetParentFormElementSpecialCase(candidate, eventName, out var formEventId))
147+
{
148+
var info = new EventFieldInfo { FieldValue = "onsubmit" };
149+
eventTasks.Add(renderer.DispatchEventAsync(formEventId, info, eventArgs, ignoreUnknownEventHandlers: true));
146150
}
147151

148152
if (candidate.HasAttribute(eventStopPropagationAttrName) || candidate.EventIsDisabled(eventName))
@@ -154,34 +158,46 @@ private static List<Task> GetDispatchEventTasks(
154158
return eventTasks;
155159
}
156160

157-
private static Task TriggerNonBubblingEventAsync(ITestRenderer renderer, IElement element, string eventName, EventArgs eventArgs)
161+
private static bool TryGetParentFormElementSpecialCase(
162+
IElement element,
163+
string eventName,
164+
out ulong eventId)
158165
{
159-
var eventAttrName = Htmlizer.ToBlazorAttribute(eventName);
166+
eventId = default;
160167

161-
if (string.Equals(eventName, "onsubmit", StringComparison.Ordinal) && element is not IHtmlFormElement)
162-
throw new InvalidOperationException("Only forms can have a onsubmit event");
168+
if (!eventName.Equals("onclick", StringComparison.OrdinalIgnoreCase))
169+
{
170+
return false;
171+
}
163172

164-
if (element.TryGetEventId(eventAttrName, out var id))
165-
return renderer.DispatchEventAsync(id, new EventFieldInfo { FieldValue = eventName }, eventArgs);
173+
var eventAttrName = Htmlizer.ToBlazorAttribute(eventName);
174+
var preventDefaultAttrName = $"{eventAttrName}:preventdefault";
175+
if (element.HasAttribute(preventDefaultAttrName))
176+
{
177+
return false;
178+
}
166179

167-
throw new MissingEventHandlerException(element, eventName);
180+
var form = element switch
181+
{
182+
IHtmlInputElement { Type: "submit", Form: not null } input => input.Form,
183+
IHtmlButtonElement { Type: "submit", Form: not null } button => button.Form,
184+
_ => null
185+
};
186+
187+
return form is not null
188+
&& form.TryGetEventId(Htmlizer.ToBlazorAttribute("onsubmit"), out eventId);
168189
}
169190

170191
private static bool EventIsDisabled(this IElement element, string eventName)
171192
{
172193
// We want to replicate the normal DOM event behavior that, for 'interactive' elements
173194
// with a 'disabled' attribute, certain mouse events are suppressed
174195

175-
switch (element)
196+
return element switch
176197
{
177-
case IHtmlButtonElement:
178-
case IHtmlInputElement:
179-
case IHtmlTextAreaElement:
180-
case IHtmlSelectElement:
181-
return DisabledEventNames.Contains(eventName) && element.IsDisabled();
182-
default:
183-
return false;
184-
}
198+
IHtmlButtonElement or IHtmlInputElement or IHtmlTextAreaElement or IHtmlSelectElement => DisabledEventNames.Contains(eventName) && element.IsDisabled(),
199+
_ => false,
200+
};
185201
}
186202

187203
private static bool TryGetEventId(this IElement element, string blazorEventName, out ulong id)

0 commit comments

Comments
 (0)