diff --git a/test/Microsoft.AspNet.Razor.Test/Generator/CSharpRazorCodeGeneratorTest.cs b/test/Microsoft.AspNet.Razor.Test/Generator/CSharpRazorCodeGeneratorTest.cs index c80cd9ea71..67924d4e23 100644 --- a/test/Microsoft.AspNet.Razor.Test/Generator/CSharpRazorCodeGeneratorTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Generator/CSharpRazorCodeGeneratorTest.cs @@ -387,7 +387,14 @@ namespace Microsoft.AspNet.Razor.Test.Generator [Fact] public void CSharpCodeGeneratorRendersHelpersBlockCorrectlyWhenInstanceHelperRequested() { - RunTest("Helpers", baselineName: "Helpers.Instance", hostConfig: h => h.StaticHelpers = false); + RunTest("Helpers", + baselineName: "Helpers.Instance", + hostConfig: host => + { + host.StaticHelpers = false; + + return host; + }); } [Fact] @@ -396,6 +403,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator RunTest("Instrumented", hostConfig: host => { host.InstrumentedSourceFilePath = string.Format("~/{0}.cshtml", host.DefaultClassName); + + return host; }); } diff --git a/test/Microsoft.AspNet.Razor.Test/Generator/CSharpTagHelperRenderingTest.cs b/test/Microsoft.AspNet.Razor.Test/Generator/CSharpTagHelperRenderingTest.cs index 239584e795..c0a9efe8ed 100644 --- a/test/Microsoft.AspNet.Razor.Test/Generator/CSharpTagHelperRenderingTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Generator/CSharpTagHelperRenderingTest.cs @@ -1,17 +1,14 @@ // Copyright (c) Microsoft Open Technologies, Inc. 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 System.Reflection; -using Microsoft.AspNet.Razor.Parser; -using Microsoft.AspNet.Razor.Parser.TagHelpers.Internal; using Microsoft.AspNet.Razor.TagHelpers; using Moq; using Xunit; namespace Microsoft.AspNet.Razor.Test.Generator { - public class CSharpTagHelperRenderingTest : CSharpRazorCodeGeneratorTest + public class CSharpTagHelperRenderingTest : TagHelperTestBase { [Theory] [InlineData("TagHelpersInSection")] @@ -36,7 +33,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator }); // Act & Assert - RunTagHelperTest(testType, tagHelperDescriptorProvider); + RunTagHelperTest(testType, tagHelperDescriptorProvider: tagHelperDescriptorProvider); } [Theory] @@ -80,7 +77,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator }); // Act & Assert - RunTagHelperTest(testType, tagHelperDescriptorProvider); + RunTagHelperTest(testType, tagHelperDescriptorProvider: tagHelperDescriptorProvider); } [Fact] @@ -98,45 +95,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator }); // Act & Assert - RunTagHelperTest("ContentBehaviorTagHelpers", tagHelperDescriptorProvider); - } - - private void RunTagHelperTest(string testName, TagHelperDescriptorProvider tagHelperDescriptorProvider) - { - RunTest( - name: testName, - templateEngineConfig: (engine) => - { - return new TagHelperTemplateEngine(engine, tagHelperDescriptorProvider); - }); - } - - private class TagHelperTemplateEngine : RazorTemplateEngine - { - private TagHelperDescriptorProvider _tagHelperDescriptorProvider; - - public TagHelperTemplateEngine(RazorTemplateEngine engine, TagHelperDescriptorProvider tagHelperDescriptorProvider) - : base(engine.Host) - { - _tagHelperDescriptorProvider = tagHelperDescriptorProvider; - } - - protected internal override RazorParser CreateParser() - { - var parser = base.CreateParser(); - var tagHelperParseTreeRewriter = new TagHelperParseTreeRewriter(_tagHelperDescriptorProvider); - - for (var i = 0; i < parser.Optimizers.Count; i++) - { - if (parser.Optimizers[i] is TagHelperParseTreeRewriter) - { - parser.Optimizers[i] = tagHelperParseTreeRewriter; - break; - } - } - - return parser; - } + RunTagHelperTest("ContentBehaviorTagHelpers", tagHelperDescriptorProvider: tagHelperDescriptorProvider); } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Razor.Test/Generator/RazorCodeGeneratorTest.cs b/test/Microsoft.AspNet.Razor.Test/Generator/RazorCodeGeneratorTest.cs index 9bbad9c8fc..788d1334aa 100644 --- a/test/Microsoft.AspNet.Razor.Test/Generator/RazorCodeGeneratorTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Generator/RazorCodeGeneratorTest.cs @@ -37,7 +37,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator IList expectedDesignTimePragmas = null, TestSpan[] spans = null, TabTest tabTest = TabTest.Both, - Action hostConfig = null, + Func hostConfig = null, Func templateEngineConfig = null, Action onResults = null) { @@ -93,7 +93,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator IList expectedDesignTimePragmas, TestSpan[] spans, bool withTabs, - Action hostConfig, + Func hostConfig, Func templateEngineConfig, Action onResults = null) { @@ -130,7 +130,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator }; if (hostConfig != null) { - hostConfig(host); + host = hostConfig(host); } host.IsIndentingWithTabs = withTabs; diff --git a/test/Microsoft.AspNet.Razor.Test/Generator/TagHelperAttributeValueCodeRendererTest.cs b/test/Microsoft.AspNet.Razor.Test/Generator/TagHelperAttributeValueCodeRendererTest.cs new file mode 100644 index 0000000000..404cd0de10 --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Test/Generator/TagHelperAttributeValueCodeRendererTest.cs @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Reflection; +using Microsoft.AspNet.Razor.Generator; +using Microsoft.AspNet.Razor.Generator.Compiler; +using Microsoft.AspNet.Razor.Generator.Compiler.CSharp; +using Microsoft.AspNet.Razor.TagHelpers; +using Moq; +using Xunit; + +namespace Microsoft.AspNet.Razor.Test.Generator +{ + public class TagHelperAttributeValueCodeRendererTest : TagHelperTestBase + { + [Fact] + public void TagHelpers_CanReplaceAttributeCodeGeneratorLogic() + { + // Arrange + var inputTypePropertyInfo = new Mock(); + inputTypePropertyInfo.Setup(propertyInfo => propertyInfo.PropertyType).Returns(typeof(string)); + inputTypePropertyInfo.Setup(propertyInfo => propertyInfo.Name).Returns("Type"); + var checkedPropertyInfo = new Mock(); + checkedPropertyInfo.Setup(propertyInfo => propertyInfo.PropertyType).Returns(typeof(bool)); + checkedPropertyInfo.Setup(propertyInfo => propertyInfo.Name).Returns("Checked"); + var tagHelperDescriptorProvider = new TagHelperDescriptorProvider( + new TagHelperDescriptor[] + { + new TagHelperDescriptor("p", "PTagHelper", ContentBehavior.None), + new TagHelperDescriptor("input", + "InputTagHelper", + ContentBehavior.None, + new TagHelperAttributeDescriptor[] { + new TagHelperAttributeDescriptor("type", inputTypePropertyInfo.Object) + }), + new TagHelperDescriptor("input", + "InputTagHelper2", + ContentBehavior.None, + new TagHelperAttributeDescriptor[] { + new TagHelperAttributeDescriptor("type", inputTypePropertyInfo.Object), + new TagHelperAttributeDescriptor("checked", checkedPropertyInfo.Object) + }), + }); + + // Act & Assert + RunTagHelperTest(testName: "BasicTagHelpers", + baseLineName: "BasicTagHelpers.CustomAttributeCodeGenerator", + tagHelperDescriptorProvider: tagHelperDescriptorProvider, + hostConfig: (host) => + { + return new CodeBuilderReplacingHost(host); + }); + } + + private class CodeBuilderReplacingHost : RazorEngineHost + { + public CodeBuilderReplacingHost(RazorEngineHost originalHost) + : base(new CSharpRazorCodeLanguage()) + { + GeneratedClassContext = originalHost.GeneratedClassContext; + } + + public override CodeBuilder DecorateCodeBuilder(CodeBuilder incomingBuilder, CodeBuilderContext context) + { + return new AttributeCodeGeneratorReplacingCodeBuilder(context); + } + } + + private class AttributeCodeGeneratorReplacingCodeBuilder : CSharpCodeBuilder + { + public AttributeCodeGeneratorReplacingCodeBuilder(CodeBuilderContext context) + : base(context) + { + } + + protected override CSharpCodeVisitor CreateCSharpCodeVisitor([NotNull] CSharpCodeWriter writer, + [NotNull] CodeBuilderContext context) + { + var bodyVisitor = base.CreateCSharpCodeVisitor(writer, context); + + bodyVisitor.TagHelperRenderer.AttributeValueCodeRenderer = new CustomTagHelperAttributeCodeRenderer(); + + return bodyVisitor; + } + } + + private class CustomTagHelperAttributeCodeRenderer : TagHelperAttributeValueCodeRenderer + { + public override void RenderAttributeValue([NotNull] TagHelperAttributeDescriptor attributeInfo, + [NotNull] CSharpCodeWriter writer, + [NotNull] CodeBuilderContext context, + [NotNull] Action renderAttributeValue) + { + writer.Write("**From custom attribute code renderer**: "); + + base.RenderAttributeValue(attributeInfo, writer, context, renderAttributeValue); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Razor.Test/Generator/TagHelperTestBase.cs b/test/Microsoft.AspNet.Razor.Test/Generator/TagHelperTestBase.cs new file mode 100644 index 0000000000..5ca58a9c06 --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Test/Generator/TagHelperTestBase.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; +using Microsoft.AspNet.Razor.Parser; +using Microsoft.AspNet.Razor.Parser.TagHelpers.Internal; +using Microsoft.AspNet.Razor.TagHelpers; + +namespace Microsoft.AspNet.Razor.Test.Generator +{ + public class TagHelperTestBase : CSharpRazorCodeGeneratorTest + { + protected void RunTagHelperTest(string testName, + string baseLineName = null, + TagHelperDescriptorProvider tagHelperDescriptorProvider = null, + Func hostConfig = null) + { + RunTest(name: testName, + baselineName: baseLineName, + templateEngineConfig: (engine) => + { + return new TagHelperTemplateEngine(engine, tagHelperDescriptorProvider); + }, + hostConfig: hostConfig); + } + + private class TagHelperTemplateEngine : RazorTemplateEngine + { + private TagHelperDescriptorProvider _tagHelperDescriptorProvider; + + public TagHelperTemplateEngine(RazorTemplateEngine engine, TagHelperDescriptorProvider tagHelperDescriptorProvider) + : base(engine.Host) + { + _tagHelperDescriptorProvider = tagHelperDescriptorProvider; + } + + protected internal override RazorParser CreateParser() + { + var parser = base.CreateParser(); + var tagHelperParseTreeRewriter = new TagHelperParseTreeRewriter(_tagHelperDescriptorProvider); + + for (var i = 0; i < parser.Optimizers.Count; i++) + { + if (parser.Optimizers[i] is TagHelperParseTreeRewriter) + { + parser.Optimizers[i] = tagHelperParseTreeRewriter; + break; + } + } + + return parser; + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/CS/Output/BasicTagHelpers.CustomAttributeCodeGenerator.cs b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/CS/Output/BasicTagHelpers.CustomAttributeCodeGenerator.cs new file mode 100644 index 0000000000..62df1e570a --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Test/TestFiles/CodeGenerator/CS/Output/BasicTagHelpers.CustomAttributeCodeGenerator.cs @@ -0,0 +1,87 @@ +#pragma checksum "BasicTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "8d60e58d54168749dc71a0d6d3a95887b2adb5e7" +namespace TestOutput +{ + using Microsoft.AspNet.Razor.Runtime.TagHelpers; + using System.Threading.Tasks; + + public class BasicTagHelpers + { + #line hidden + private System.IO.TextWriter __tagHelperStringValueBuffer = null; + private TagHelperExecutionContext __tagHelperExecutionContext = null; + private TagHelperRunner __tagHelperRunner = new TagHelperRunner(); + private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager(); + private PTagHelper __PTagHelper = null; + private InputTagHelper __InputTagHelper = null; + private InputTagHelper2 __InputTagHelper2 = null; + #line hidden + public BasicTagHelpers() + { + } + + #pragma warning disable 1998 + public override async Task ExecuteAsync() + { + Instrumentation.BeginContext(0, 47, true); + WriteLiteral("
\r\n "); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("p"); + __PTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__PTagHelper); + __tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World"); + __tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result; + WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag()); + Instrumentation.BeginContext(70, 10, true); + WriteLiteral("\r\n "); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("p"); + __PTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__PTagHelper); + __tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result; + WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag()); + WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag()); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(87, 10, true); + WriteLiteral("\r\n "); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input"); + __InputTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper); + __InputTagHelper.Type = **From custom attribute code renderer**: "text"; + __tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type); + __InputTagHelper2 = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper2); + __InputTagHelper2.Type = __InputTagHelper.Type; + __tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result; + WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag()); + WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag()); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(118, 10, true); + WriteLiteral("\r\n "); + Instrumentation.EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input"); + __InputTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper); + __InputTagHelper.Type = **From custom attribute code renderer**: "checkbox"; + __tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type); + __InputTagHelper2 = CreateTagHelper(); + __tagHelperExecutionContext.Add(__InputTagHelper2); + __InputTagHelper2.Type = __InputTagHelper.Type; + __InputTagHelper2.Checked = **From custom attribute code renderer**: true; + __tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked); + __tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result; + WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag()); + WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag()); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(167, 6, true); + WriteLiteral("\r\n "); + Instrumentation.EndContext(); + WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag()); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + Instrumentation.BeginContext(177, 8, true); + WriteLiteral("\r\n
"); + Instrumentation.EndContext(); + } + #pragma warning restore 1998 + } +}