Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit

Permalink
Add test for TagHelperAttributeCodeGenerator extensibility.
Browse files Browse the repository at this point in the history
- Tested that we can successfully plugin our own TagHelperAttributeCodeGenerator.
- Moved some existing TagHelper test logic into its own base type to enhance code reusability.

#119
  • Loading branch information
NTaylorMullen committed Oct 2, 2014
1 parent 4c75bd8 commit 6843937
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,14 @@ public void CSharpCodeGeneratorDoesNotRenderLinePragmasIfGenerateLinePragmasIsSe
[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]
Expand Down
Original file line number Diff line number Diff line change
@@ -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")]
Expand Down Expand Up @@ -43,7 +40,7 @@ public void TagHelpers_WithinHelpersAndSections_GeneratesExpectedOutput(string t
[InlineData("SingleTagHelper")]
[InlineData("BasicTagHelpers")]
[InlineData("ComplexTagHelpers")]
public void TagHelpers_GenerateExpectedOutput(string testType)
public void TagHelpers_ChangeGeneratedOutput(string testType)
{
// Arrange
var pFooPropertyInfo = new Mock<PropertyInfo>();
Expand Down Expand Up @@ -84,7 +81,7 @@ public void TagHelpers_GenerateExpectedOutput(string testType)
}

[Fact]
public void TagHelpers_WithContentBehaviors_GenerateExpectedOutput()
public void TagHelpers_ContentBehavior()
{
// Arrange
var tagHelperDescriptorProvider = new TagHelperDescriptorProvider(
Expand All @@ -100,43 +97,5 @@ public void TagHelpers_WithContentBehaviors_GenerateExpectedOutput()
// 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;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected void RunTest(string name,
IList<LineMapping> expectedDesignTimePragmas = null,
TestSpan[] spans = null,
TabTest tabTest = TabTest.Both,
Action<RazorEngineHost> hostConfig = null,
Func<RazorEngineHost, RazorEngineHost> hostConfig = null,
Func<RazorTemplateEngine, RazorTemplateEngine> templateEngineConfig = null,
Action<GeneratorResults> onResults = null)
{
Expand Down Expand Up @@ -93,7 +93,7 @@ private void RunTestInternal(string name,
IList<LineMapping> expectedDesignTimePragmas,
TestSpan[] spans,
bool withTabs,
Action<RazorEngineHost> hostConfig,
Func<RazorEngineHost, RazorEngineHost> hostConfig,
Func<RazorTemplateEngine, RazorTemplateEngine> templateEngineConfig,
Action<GeneratorResults> onResults = null)
{
Expand Down Expand Up @@ -130,7 +130,7 @@ private void RunTestInternal(string name,
};
if (hostConfig != null)
{
hostConfig(host);
host = hostConfig(host);
}

host.IsIndentingWithTabs = withTabs;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// 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 TagHelperAttributeCodeGeneratorTests : TagHelperTestBase
{
[Fact]
public void TagHelpers_CanReplaceAttributeCodeGeneratorLogic()
{
var inputTypePropertyInfo = new Mock<PropertyInfo>();
inputTypePropertyInfo.Setup(ipi => ipi.PropertyType).Returns(typeof(string));
inputTypePropertyInfo.Setup(ipi => ipi.Name).Returns("Type");
var checkedPropertyInfo = new Mock<PropertyInfo>();
checkedPropertyInfo.Setup(ipi => ipi.PropertyType).Returns(typeof(bool));
checkedPropertyInfo.Setup(ipi => ipi.Name).Returns("Checked");
// Arrange
var tagHelperProvider = 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: tagHelperProvider,
hostConfig: (host) =>
{
return new CodeBuilderReplacingHost();
});
}

private class CodeBuilderReplacingHost : RazorEngineHost
{
public CodeBuilderReplacingHost()
: base(new CSharpRazorCodeLanguage())
{
}

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 DecorateCSharpCodeVisitor([NotNull] CSharpCodeWriter writer,
[NotNull] CodeBuilderContext context,
[NotNull] CSharpCodeVisitor incomingVisitor)
{
incomingVisitor.TagHelperRenderer =
new CSharpTagHelperCodeRenderer(incomingVisitor,
new CustomTagHelperAttributeCodeGenerator(),
writer,
context);

return base.DecorateCSharpCodeVisitor(writer, context, incomingVisitor);
}
}

private class CustomTagHelperAttributeCodeGenerator : TagHelperAttributeValueCodeRenderer
{
public override void RenderAttributeValue([NotNull]TagHelperAttributeDescriptor attributeInfo,
[NotNull]CSharpCodeWriter writer,
[NotNull]CodeGeneratorContext context,
[NotNull]Action<CSharpCodeWriter> renderAttributeValue)
{
writer.Write("**From custom attribute code generator**: ");

base.RenderAttributeValue(attributeInfo, writer, context, renderAttributeValue);
}
}
}
}
56 changes: 56 additions & 0 deletions test/Microsoft.AspNet.Razor.Test/Generator/TagHelperTestBase.cs
Original file line number Diff line number Diff line change
@@ -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, TagHelperDescriptorProvider tagHelperDescriptorProvider)
{
RunTagHelperTest(testName, testName, tagHelperDescriptorProvider, (host) => host);
}

protected void RunTagHelperTest(string testName,
string baseLineName,
TagHelperDescriptorProvider tagHelperDescriptorProvider,
Func<RazorEngineHost, RazorEngineHost> hostConfig)
{
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 optimizers = parser.Optimizers.Where(opmzr => !(opmzr is TagHelperParseTreeRewriter));

parser.Optimizers = optimizers.Concat(new[] {
new TagHelperParseTreeRewriter(_tagHelperDescriptorProvider)
}).ToList();

return parser;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
namespace TestOutput
{
using System.Threading.Tasks;

public class BasicTagHelpers
{
private TagHelperManager __tagHelperManager { get; set; }
#line hidden
public BasicTagHelpers()
{
}

#pragma warning disable 1998
public override async Task ExecuteAsync()
{
var __tagHelperAttributeValue = string.Empty;
PTagHelper __p_PTagHelper;
InputTagHelper __input_InputTagHelper;
InputTagHelper2 __input_InputTagHelper2;
WriteLiteral("<div class=\"randomNonTagHelperAttribute\">\r\n ");
__p_PTagHelper = __tagHelperManager.InstantiateTagHelper<PTagHelper>();
__tagHelperManager.AddHtmlAttribute("class", "Hello World");
__tagHelperManager.StartTagHelpersScope("p");
await __tagHelperManager.ExecuteTagHelpersAsync();
WriteLiteral(__tagHelperManager.GenerateTagStart());
WriteLiteral("\r\n ");
__p_PTagHelper = __tagHelperManager.InstantiateTagHelper<PTagHelper>();
__tagHelperManager.StartTagHelpersScope("p");
await __tagHelperManager.ExecuteTagHelpersAsync();
WriteLiteral(__tagHelperManager.GenerateTagStart());
WriteLiteral(__tagHelperManager.GenerateTagEnd());
__tagHelperManager.EndTagHelpersScope();
WriteLiteral("\r\n ");
__input_InputTagHelper = __tagHelperManager.InstantiateTagHelper<InputTagHelper>();
__input_InputTagHelper.Type = **From custom attribute code generator**: "text";
__tagHelperManager.AddTagHelperAttribute("type", __input_InputTagHelper.Type);
__input_InputTagHelper2 = __tagHelperManager.InstantiateTagHelper<InputTagHelper2>();
__input_InputTagHelper2.Type = __input_InputTagHelper.Type;
__tagHelperManager.StartTagHelpersScope("input");
await __tagHelperManager.ExecuteTagHelpersAsync();
WriteLiteral(__tagHelperManager.GenerateTagStart());
WriteLiteral(__tagHelperManager.GenerateTagEnd());
__tagHelperManager.EndTagHelpersScope();
WriteLiteral("\r\n ");
__input_InputTagHelper = __tagHelperManager.InstantiateTagHelper<InputTagHelper>();
__input_InputTagHelper.Type = **From custom attribute code generator**: "checkbox";
__tagHelperManager.AddTagHelperAttribute("type", __input_InputTagHelper.Type);
__input_InputTagHelper2 = __tagHelperManager.InstantiateTagHelper<InputTagHelper2>();
__input_InputTagHelper2.Type = __input_InputTagHelper.Type;
__input_InputTagHelper2.Checked = **From custom attribute code generator**: true;
__tagHelperManager.AddTagHelperAttribute("checked", __input_InputTagHelper2.Checked);
__tagHelperManager.StartTagHelpersScope("input");
await __tagHelperManager.ExecuteTagHelpersAsync();
WriteLiteral(__tagHelperManager.GenerateTagStart());
WriteLiteral(__tagHelperManager.GenerateTagEnd());
__tagHelperManager.EndTagHelpersScope();
WriteLiteral("\r\n ");
WriteLiteral(__tagHelperManager.GenerateTagEnd());
__tagHelperManager.EndTagHelpersScope();
WriteLiteral("\r\n</div>");
}
#pragma warning restore 1998
}
}

0 comments on commit 6843937

Please sign in to comment.