// 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 Xunit; namespace Microsoft.AspNetCore.Blazor.Build.Test { public class RuntimeCodeGenerationTest : RazorBaselineIntegrationTestBase { internal override bool UseTwoPhaseCompilation => true; [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 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 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); } [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 @using Microsoft.AspNetCore.Blazor @functions { private int counter; private void Increment(UIEventArgs e) { counter++; } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [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_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); } [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(@" @using Microsoft.AspNetCore.Blazor { })"" />"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithEventArgsLambdaDelegate() { // Arrange // Act var generated = CompileToCSharp(@" @using Microsoft.AspNetCore.Blazor { })"" />"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithNoArgMethodGroup() { // Arrange // Act var generated = CompileToCSharp(@" @using Microsoft.AspNetCore.Blazor @functions { void OnClick() { } }"); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } [Fact] public void EventHandler_OnElement_WithEventArgsMethodGroup() { // Arrange // Act var generated = CompileToCSharp(@" @using Microsoft.AspNetCore.Blazor @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(@" @using Microsoft.AspNetCore.Blazor @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 @using Microsoft.AspNetCore.Blazor @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 @using Microsoft.AspNetCore.Blazor @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 @using Microsoft.AspNetCore.Blazor 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 @using Microsoft.AspNetCore.Blazor await Task.Delay(10)"" /> "); // 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] 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); } [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 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_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); } [Fact] public void Element_WithRef() { // Arrange/Act var generated = CompileToCSharp(@" Hello @functions { private Microsoft.AspNetCore.Blazor.ElementRef 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; } "); // 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; } "); // Assert AssertDocumentNodeMatchesBaseline(generated.CodeDocument); AssertCSharpDocumentMatchesBaseline(generated.CodeDocument); CompileToAssembly(generated); } } }