Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Globalization;
using Roslyn.Test.Utilities;
using Xunit;

namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests;
Expand Down Expand Up @@ -217,4 +218,46 @@ public class MyComponent : ComponentBase
"The start tag name 'MyComponent' does not match the end tag name 'mycomponent'. Components must have matching start and end tag names (case-sensitive).",
diagnostic.GetMessage(CultureInfo.CurrentCulture));
}

[Fact, WorkItem("https://github.com/dotnet/aspnetcore/issues/23228")]
public void AttributeBinding_ExtraClosingParenthesis_TreatedAsLiteralText()
{
// Arrange/Act
// This reproduces https://github.com/dotnet/aspnetcore/issues/23228
// An extra closing parenthesis in an attribute binding is currently treated as literal text
// rather than producing a diagnostic error
var generated = CompileToCSharp(@"
@page ""/""

@foreach (var item in new[] { Architecture.Windows, Architecture.MacOSX, Architecture.Linux })
{
<label class=""col-auto"">
<input name=""arch"" type=""radio""
value=""@item""
checked=""@IsActive(item))""
@onchange=""@( _ => ChangeArchitecture(item))"" />
@item.ToString()
</label>
}
<h1>@current</h1>
@code {
enum Architecture
{
None,
Windows,
MacOSX,
Linux
}
Architecture current = Architecture.None;
bool IsActive(Architecture arch) => current == arch;
void ChangeArchitecture(Architecture arch) => current = arch;
}");

// Assert
// The compiler currently treats the extra ')' as literal text and generates:
// __builder.AddAttribute(6, "checked", (IsActive(item)) + ")");
// This is valid C# but produces incorrect Blazor behavior (UI out of sync)
// No diagnostic is currently reported for this issue
Assert.Empty(generated.RazorDiagnostics);
}
}