// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Linq; using Xunit; namespace Microsoft.AspNetCore.Blazor.Build.Test { public abstract class CodeGenerationTestBase : RazorBaselineIntegrationTestBase { internal override bool UseTwoPhaseCompilation => true; public CodeGenerationTestBase() : base(generateBaselines: false) { } #region Basics [Fact] public void ChildComponent_Simple() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithParameters() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class SomeType { } public class MyComponent : BlazorComponent { [Parameter] int IntProperty { get; set; } [Parameter] bool BoolProperty { get; set; } [Parameter] string StringProperty { get; set; } [Parameter] SomeType ObjectProperty { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ComponentWithTypeParameters() { // Arrange // Act var generated = CompileToCSharp(@" @using Microsoft.AspNetCore.Blazor; @typeparam TItem1 @typeparam TItem2

Item1

@foreach (var item2 in Items2) {

@ChildContent(item2);

} @functions { [Parameter] TItem1 Item1 { get; set; } [Parameter] List Items2 { get; set; } [Parameter] RenderFragment ChildContent { get; set; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithExplicitStringParameter() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] string StringProperty { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithNonPropertyAttributes() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ComponentParameter_TypeMismatch_ReportsDiagnostic() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class CoolnessMeter : BlazorComponent { [Parameter] private int Coolness { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); var assembly = CompileToAssembly(generated, throwOnFailure: false); // This has some errors Assert.Collection( assembly.Diagnostics.OrderBy(d => d.Id), d => Assert.Equal("CS1503", d.Id)); } #endregion #region Bind [Fact] public void BindToComponent_SpecifiesValue_WithMatchingProperties() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] int Value { get; set; } [Parameter] Action ValueChanged { get; set; } } }")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public int ParentValue { get; set; } = 42; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BindToComponent_TypeChecked_WithMatchingProperties() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] int Value { get; set; } [Parameter] Action ValueChanged { get; set; } } }")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public string ParentValue { get; set; } = ""42""; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); var assembly = CompileToAssembly(generated, throwOnFailure: false); // This has some errors Assert.Collection( assembly.Diagnostics.OrderBy(d => d.Id), d => Assert.Equal("CS0029", d.Id), d => Assert.Equal("CS1503", d.Id)); } [Fact] public void BindToComponent_SpecifiesValue_WithoutMatchingProperties() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent, IComponent { void IComponent.SetParameters(ParameterCollection parameters) { } } }")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public int ParentValue { get; set; } = 42; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BindToComponent_SpecifiesValueAndChangeEvent_WithMatchingProperties() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] int Value { get; set; } [Parameter] Action OnChanged { get; set; } } }")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public int ParentValue { get; set; } = 42; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BindToComponent_SpecifiesValueAndChangeEvent_WithoutMatchingProperties() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent, IComponent { void IComponent.SetParameters(ParameterCollection parameters) { } } }")); var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public int ParentValue { get; set; } = 42; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BindToElement_WritesAttributes() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { [BindElement(""div"", null, ""myvalue"", ""myevent"")] public static class BindAttributes { } }")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly
@functions { public string ParentValue { get; set; } = ""hi""; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BindToElementWithSuffix_WritesAttributes() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { [BindElement(""div"", ""value"", ""myvalue"", ""myevent"")] public static class BindAttributes { } }")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly
@functions { public string ParentValue { get; set; } = ""hi""; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BuiltIn_BindToInputWithoutType_WritesAttributes() { // Arrange // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public int ParentValue { get; set; } = 42; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BuiltIn_BindToInputText_WithFormat_WritesAttributes() { // Arrange // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public DateTime CurrentDate { get; set; } = new DateTime(2018, 1, 1); }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BuiltIn_BindToInputText_WithFormatFromProperty_WritesAttributes() { // Arrange // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public DateTime CurrentDate { get; set; } = new DateTime(2018, 1, 1); public string Format { get; set; } = ""MM/dd/yyyy""; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BuiltIn_BindToInputText_WritesAttributes() { // Arrange // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public int ParentValue { get; set; } = 42; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BuiltIn_BindToInputCheckbox_WritesAttributes() { // Arrange // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public bool Enabled { get; set; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BindToElementFallback_WritesAttributes() { // Arrange // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public int ParentValue { get; set; } = 42; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BindToElementFallback_WithFormat_WritesAttributes() { // Arrange // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public DateTime CurrentDate { get; set; } = new DateTime(2018, 1, 1); }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Child Content [Fact] public void ChildComponent_WithChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] string MyAttr { get; set; } [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly Some textNested text"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithGenericChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] string MyAttr { get; set; } [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly Some text@context.ToLowerInvariant()"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithGenericChildContent_SetsParameterName() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] string MyAttr { get; set; } [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly Some text@item.ToLowerInvariant() "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithGenericChildContent_SetsParameterNameOnComponent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] string MyAttr { get; set; } [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly Some text@item.ToLowerInvariant() "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithElementOnlyChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly hello"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithExplicitChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly hello"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithExplicitGenericChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @context"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void MultipleExplictChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment Header { get; set; } [Parameter] RenderFragment Footer { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly
Hi!
@(""bye!"")
"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BodyAndAttributeChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment Header { get; set; } RenderFragment ChildContent { get; set; } [Parameter] RenderFragment Footer { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @{ RenderFragment header = (context) => @
@context.ToLowerInvariant()
; } Some Content "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void BodyAndExplicitChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment Header { get; set; } [Parameter] RenderFragment ChildContent { get; set; } [Parameter] RenderFragment Footer { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @{ RenderFragment header = (context) => @
@context.ToLowerInvariant()
; } Some Content
Bye!
"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Directives [Fact] public void ChildComponent_WithPageDirective() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @page ""/MyPage"" @page ""/AnotherRoute/{id}"" "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Event Handlers [Fact] public void ChildComponent_WithLambdaEventHandler() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] Action OnClick { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly { Increment(); })""/> @functions { private int counter; private void Increment() { counter++; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } // Regression test for #954 - we need to allow arbitrary event handler // attributes with weak typing. [Fact] public void ChildComponent_WithWeaklyTypeEventHandler() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class DynamicElement : BlazorComponent { } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { private Action OnClick { get; set; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_WithExplicitEventHandler() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] Action OnClick { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { private int counter; private void Increment(UIEventArgs e) { counter++; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithString() { // Arrange // Act var generated = CompileToCSharp(@" "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithNoArgsLambdaDelegate() { // Arrange // Act var generated = CompileToCSharp(@" { })"" />"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithEventArgsLambdaDelegate() { // Arrange // Act var generated = CompileToCSharp(@" { })"" />"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithNoArgMethodGroup() { // Arrange // Act var generated = CompileToCSharp(@" @functions { void OnClick() { } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithEventArgsMethodGroup() { // Arrange // Act var generated = CompileToCSharp(@" @functions { void OnClick(UIMouseEventArgs e) { } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_ArbitraryEventName_WithEventArgsMethodGroup() { // Arrange // Act var generated = CompileToCSharp(@" @functions { void OnClick(UIEventArgs e) { } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void AsyncEventHandler_OnElement_Action_MethodGroup() { // Arrange // Act var generated = CompileToCSharp(@" @using System.Threading.Tasks @functions { Task OnClick() { return Task.CompletedTask; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void AsyncEventHandler_OnElement_ActionEventArgs_MethodGroup() { // Arrange // Act var generated = CompileToCSharp(@" @using System.Threading.Tasks @functions { Task OnClick(UIMouseEventArgs e) { return Task.CompletedTask; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void AsyncEventHandler_OnElement_Action_Lambda() { // Arrange // Act var generated = CompileToCSharp(@" @using System.Threading.Tasks await Task.Delay(10)"" /> "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void AsyncEventHandler_OnElement_ActionEventArgs_Lambda() { // Arrange // Act var generated = CompileToCSharp(@" @using System.Threading.Tasks await Task.Delay(10)"" /> "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithLambdaDelegate() { // Arrange // Act var generated = CompileToCSharp(@" { })"" />"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithDelegate() { // Arrange // Act var generated = CompileToCSharp(@" @functions { void OnClick(UIMouseEventArgs e) { } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Generics [Fact] public void ChildComponent_Generic() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_Generic_TypeInference() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_Generic_TypeInference_Multiple() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericWeaklyTypedAttribute() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericWeaklyTypedAttribute_TypeInference() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericBind() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } [Parameter] Action ItemChanged { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { string Value; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericBind_TypeInference() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } [Parameter] Action ItemChanged { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { string Value; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericBindWeaklyTyped() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { string Value; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericBindWeaklyTyped_TypeInference() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Value { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { string Value; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly
@context.ToLower()
"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_GenericChildContent_TypeInference() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } [Parameter] RenderFragment ChildContent { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly
@context.ToLower()
"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_MultipleGenerics() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem1 Item { get; set; } [Parameter] RenderFragment ChildContent { get; set; } [Parameter] RenderFragment AnotherChildContent { get; set; } public class Context { public TItem2 Item { get; set; } } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly
@context.ToLower()
@System.Math.Max(0, item.Item);
"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ChildComponent_MultipleGenerics_TypeInference() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System.Collections.Generic; using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem1 Item { get; set; } [Parameter] List Items { get; set; } [Parameter] RenderFragment ChildContent { get; set; } [Parameter] RenderFragment AnotherChildContent { get; set; } public class Context { public TItem2 Item { get; set; } } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly ())>
@context.ToLower()
@System.Math.Max(0, item.Item);
"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void GenericComponent_WithComponentRef() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { private MyComponent _my; public void Foo() { System.GC.KeepAlive(_my); } } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void GenericComponent_WithComponentRef_TypeInference() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] TItem Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { private MyComponent _my; public void Foo() { System.GC.KeepAlive(_my); } } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Ref [Fact] public void Element_WithRef() { // Arrange/Act var generated = CompileToCSharp(@" Hello @functions { private Microsoft.AspNetCore.Blazor.ElementRef myElem; public void Foo() { System.GC.KeepAlive(myElem); } } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void Component_WithRef() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { } } ")); // Arrange/Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { private Test.MyComponent myInstance; public void Foo() { System.GC.KeepAlive(myInstance); } } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void Component_WithRef_WithChildContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { } } ")); // Arrange/Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly Some further content @functions { private Test.MyComponent myInstance; public void Foo() { System.GC.KeepAlive(myInstance); } } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Templates [Fact] public void RazorTemplate_InCodeBlock() { // Arrange // Act var generated = CompileToCSharp(@" @{ RenderFragment p = (person) => @
@person.Name
; } @functions { class Person { public string Name { get; set; } } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void RazorTemplate_InExplicitExpression() { // Arrange // Act var generated = CompileToCSharp(@" @(RenderPerson((person) => @
@person.Name
)) @functions { class Person { public string Name { get; set; } } object RenderPerson(RenderFragment p) => null; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void RazorTemplate_NonGeneric_InImplicitExpression() { // Arrange // Act var generated = CompileToCSharp(@" @RenderPerson(@
HI
) @functions { object RenderPerson(RenderFragment p) => null; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void RazorTemplate_Generic_InImplicitExpression() { // Arrange // Act var generated = CompileToCSharp(@" @RenderPerson((person) => @
@person.Name
) @functions { class Person { public string Name { get; set; } } object RenderPerson(RenderFragment p) => null; }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void RazorTemplate_ContainsComponent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] string Name { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper ""*, TestAssembly"" @{ RenderFragment p = (person) => @
; } @functions { class Person { public string Name { get; set; } } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } // Targeted at the logic that assigns 'builder' names [Fact] public void RazorTemplate_FollowedByComponent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] string Name { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper ""*, TestAssembly"" @{ RenderFragment p = (person) => @
; } @(""hello, world!"") @functions { class Person { public string Name { get; set; } } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void RazorTemplate_NonGeneric_AsComponentParameter() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment Template { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper ""*, TestAssembly"" @{ RenderFragment template = @
Joey
; } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void RazorTemplate_Generic_AsComponentParameter() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment PersonTemplate { get; set; } } public class Person { public string Name { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper ""*, TestAssembly"" @{ RenderFragment template = (person) => @
@person.Name
; } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void RazorTemplate_AsComponentParameter_MixedContent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class MyComponent : BlazorComponent { [Parameter] RenderFragment Template { get; set; } } public class Context { public int Index { get; set; } public string Item { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper ""*, TestAssembly"" @{ RenderFragment template = (context) => @
  • #@context.Index - @context.Item.ToLower()
  • ; } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Whitespace [Fact] public void LeadingWhiteSpace_WithDirective() { // Arrange/Act var generated = CompileToCSharp(@" @using System

    Hello

    "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void LeadingWhiteSpace_WithCSharpExpression() { // Arrange/Act var generated = CompileToCSharp(@" @(""My value"")

    Hello

    "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void LeadingWhiteSpace_WithComponent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class SomeOtherComponent : BlazorComponent { } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly

    Hello

    "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void TrailingWhiteSpace_WithDirective() { // Arrange/Act var generated = CompileToCSharp(@"

    Hello

    @page ""/my/url"" "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void TrailingWhiteSpace_WithCSharpExpression() { // Arrange/Act var generated = CompileToCSharp(@"

    Hello

    @(""My value"") "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void TrailingWhiteSpace_WithComponent() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class SomeOtherComponent : BlazorComponent { } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly

    Hello

    "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion #region Misc [Fact] // We don't process - we just skip them public void Component_WithDocType() { // Arrange // Act var generated = CompileToCSharp(@"
    "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void ScriptTag_WithErrorSuppressed() { // Arrange/Act var generated = CompileToCSharp(@"
    "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] // https://github.com/aspnet/Blazor/issues/597 public void Regression_597() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class Counter : BlazorComponent { public int Count { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { string y = null; } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void Regression_609() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using System; using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class User : BlazorComponent { public string Name { get; set; } public Action NameChanged { get; set; } public bool IsActive { get; set; } public Action IsActiveChanged { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @functions { public string UserName { get; set; } public bool UserIsActive { get; set; } } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] // https://github.com/aspnet/Blazor/issues/772 public void Regression_772() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class SurveyPrompt : BlazorComponent { [Parameter] private string Title { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @page ""/""

    Hello, world!

    Welcome to your new app. d.Id), d => Assert.Equal("RZ1034", d.Id), d => Assert.Equal("RZ1035", d.Id)); } [Fact] // https://github.com/aspnet/Blazor/issues/773 public void Regression_773() { // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Blazor.Components; namespace Test { public class SurveyPrompt : BlazorComponent { [Parameter] private string Title { get; set; } } } ")); // Act var generated = CompileToCSharp(@" @addTagHelper *, TestAssembly @page ""/""

    Hello, world!

    Welcome to your new app. Test!
    "" /> "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void Regression_784() { // Arrange // Act var generated = CompileToCSharp(@"

    @functions { public string ParentBgColor { get; set; } = ""#FFFFFF""; public void OnComponentHover(UIMouseEventArgs e) { } } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } #endregion } }