Add tests to validate TagHelper escape functionality.

- Added extensive unit tests.
- Added functional test to validate output for runtime and design time.

#187
This commit is contained in:
N. Taylor Mullen 2015-01-22 14:43:13 -08:00
parent 94230a5a14
commit cf3d049272
9 changed files with 1914 additions and 1 deletions

View File

@ -0,0 +1,71 @@
// 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 Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class HtmlElementNameAttributeTest
{
public static TheoryData InvalidTagNameData
{
get
{
var invalidTagNameError =
"Tag helpers cannot target element name '{0}' because it contains a '{1}' character.";
var nullOrWhitespaceTagNameError =
"Tag name cannot be null or whitespace.";
// tagName, expectedExceptionMessage
return new TheoryData<string, string>
{
{ "!", string.Format(invalidTagNameError, "!", "!") },
{ "hello!", string.Format(invalidTagNameError, "hello!", "!") },
{ "!hello", string.Format(invalidTagNameError, "!hello", "!") },
{ "he!lo", string.Format(invalidTagNameError, "he!lo", "!") },
{ "!he!lo!", string.Format(invalidTagNameError, "!he!lo!", "!") },
{ string.Empty, nullOrWhitespaceTagNameError },
{ Environment.NewLine, nullOrWhitespaceTagNameError },
{ "\t", nullOrWhitespaceTagNameError },
{ " \t ", nullOrWhitespaceTagNameError },
{ " ", nullOrWhitespaceTagNameError },
{ Environment.NewLine + " ", nullOrWhitespaceTagNameError },
{ null, nullOrWhitespaceTagNameError },
};
}
}
[Theory]
[MemberData(nameof(InvalidTagNameData))]
public void SingleArgumentConstructor_ThrowsOnInvalidTagNames(
string tagName,
string expectedExceptionMessage)
{
// Arrange
expectedExceptionMessage += Environment.NewLine + "Parameter name: tag";
// Act & Assert
var exception = Assert.Throws<ArgumentException>(
"tag",
() => new HtmlElementNameAttribute(tagName));
Assert.Equal(exception.Message, expectedExceptionMessage);
}
[Theory]
[MemberData(nameof(InvalidTagNameData))]
public void MultipleArgumentConstructor_ThrowsOnInvalidTagNames(
string tagName,
string expectedExceptionMessage)
{
// Arrange
expectedExceptionMessage += Environment.NewLine + "Parameter name: additionalTags";
// Act & Assert
var exception = Assert.Throws<ArgumentException>(
"additionalTags",
() => new HtmlElementNameAttribute("p", "div", "span", tagName));
Assert.Equal(exception.Message, expectedExceptionMessage);
}
}
}

View File

@ -14,6 +14,19 @@ namespace Microsoft.AspNet.Razor.Test.Framework
_factory = factory;
}
public Block EscapedMarkupTagBlock(string prefix, string suffix)
{
return EscapedMarkupTagBlock(prefix, suffix, AcceptedCharacters.Any);
}
public Block EscapedMarkupTagBlock(string prefix, string suffix, AcceptedCharacters acceptedCharacters)
{
return new MarkupTagBlock(
_factory.Markup(prefix),
_factory.BangEscape(),
_factory.Markup(suffix).Accepts(acceptedCharacters));
}
public Block MarkupTagBlock(string content)
{
return MarkupTagBlock(content, AcceptedCharacters.Any);

View File

@ -104,6 +104,14 @@ namespace Microsoft.AspNet.Razor.Test.Framework
return self.Span(SpanKind.Comment, content, type);
}
public static SpanConstructor BangEscape(this SpanFactory self)
{
return self
.Span(SpanKind.MetaCode, "!", markup: true)
.With(SpanCodeGenerator.Null)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor Markup(this SpanFactory self, string content)
{
return self.Span(SpanKind.Markup, content, markup: true).With(new MarkupCodeGenerator());

View File

@ -248,6 +248,39 @@ namespace Microsoft.AspNet.Razor.Test.Generator
contentLength: 0)
}
},
{
"EscapedTagHelpers",
"EscapedTagHelpers.DesignTime",
PAndInputTagHelperDescriptors,
new List<LineMapping>
{
BuildLineMapping(documentAbsoluteIndex: 14,
documentLineIndex: 0,
generatedAbsoluteIndex: 479,
generatedLineIndex: 15,
characterOffsetIndex: 14,
contentLength: 11),
BuildLineMapping(documentAbsoluteIndex: 102,
documentLineIndex: 3,
generatedAbsoluteIndex: 975,
generatedLineIndex: 34,
characterOffsetIndex: 29,
contentLength: 12),
BuildLineMapping(documentAbsoluteIndex: 200,
documentLineIndex: 5,
documentCharacterOffsetIndex: 51,
generatedAbsoluteIndex: 1130,
generatedLineIndex: 40,
generatedCharacterOffsetIndex: 6,
contentLength: 12),
BuildLineMapping(documentAbsoluteIndex: 223,
documentLineIndex: 5,
generatedAbsoluteIndex: 1467,
generatedLineIndex: 48,
characterOffsetIndex: 74,
contentLength: 4)
}
},
};
}
}
@ -280,6 +313,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{ "BasicTagHelpers.RemoveTagHelper", PAndInputTagHelperDescriptors },
{ "ComplexTagHelpers", PAndInputTagHelperDescriptors },
{ "EmptyAttributeTagHelpers", PAndInputTagHelperDescriptors },
{ "EscapedTagHelpers", PAndInputTagHelperDescriptors },
};
}
}

View File

@ -199,7 +199,7 @@ namespace Microsoft.AspNet.Razor.Test.Parser.Html
[Fact]
public void ParseDocumentReturnsOneMarkupSegmentIfNoCodeBlocksEncountered()
{
SingleSpanDocumentTest("Foo Baz<!--Foo-->Bar<!-F> Qux", BlockType.Markup, SpanKind.Markup);
SingleSpanDocumentTest("Foo Baz<!--Foo-->Bar<!--F> Qux", BlockType.Markup, SpanKind.Markup);
}
[Fact]

View File

@ -0,0 +1,56 @@
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class EscapedTagHelpers
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
string __tagHelperDirectiveSyntaxHelper = null;
__tagHelperDirectiveSyntaxHelper =
#line 1 "EscapedTagHelpers.cshtml"
"something"
#line default
#line hidden
;
#pragma warning restore 219
}
#line hidden
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
#line hidden
public EscapedTagHelpers()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
#line 4 "EscapedTagHelpers.cshtml"
__o = DateTime.Now;
#line default
#line hidden
__InputTagHelper = CreateTagHelper<InputTagHelper>();
#line 6 "EscapedTagHelpers.cshtml"
__o = DateTime.Now;
#line default
#line hidden
__InputTagHelper.Type = string.Empty;
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__InputTagHelper2.Type = __InputTagHelper.Type;
#line 6 "EscapedTagHelpers.cshtml"
__InputTagHelper2.Checked = true;
#line default
#line hidden
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,87 @@
#pragma checksum "EscapedTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "f1f93dcc77691cc626112fe0475f5c350e5fa802"
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class EscapedTagHelpers
{
#line hidden
#pragma warning disable 0414
private System.IO.TextWriter __tagHelperStringValueBuffer = null;
#pragma warning restore 0414
private TagHelperExecutionContext __tagHelperExecutionContext = null;
private TagHelperRunner __tagHelperRunner = new TagHelperRunner();
private TagHelperScopeManager __tagHelperScopeManager = new TagHelperScopeManager();
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
#line hidden
public EscapedTagHelpers()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
Instrumentation.BeginContext(27, 72, true);
WriteLiteral("\r\n<div class=\"randomNonTagHelperAttribute\">\r\n <p class=\"Hello World\" ");
Instrumentation.EndContext();
Instrumentation.BeginContext(102, 12, false);
#line 4 "EscapedTagHelpers.cshtml"
Write(DateTime.Now);
#line default
#line hidden
Instrumentation.EndContext();
Instrumentation.BeginContext(114, 69, true);
WriteLiteral(">\r\n <input type=\"text\" />\r\n <em>Not a TagHelper: </em> ");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", "test", async() => {
}
, StartWritingScope, EndWritingScope);
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__tagHelperExecutionContext.Add(__InputTagHelper);
StartWritingScope();
#line 6 "EscapedTagHelpers.cshtml"
Write(DateTime.Now);
#line default
#line hidden
__tagHelperStringValueBuffer = EndWritingScope();
__InputTagHelper.Type = __tagHelperStringValueBuffer.ToString();
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
__InputTagHelper2.Type = __InputTagHelper.Type;
#line 6 "EscapedTagHelpers.cshtml"
__InputTagHelper2.Checked = true;
#line default
#line hidden
__tagHelperExecutionContext.AddTagHelperAttribute("checked", __InputTagHelper2.Checked);
__tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result;
WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag());
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePreContent());
if (__tagHelperExecutionContext.Output.ContentSet)
{
WriteLiteral(__tagHelperExecutionContext.Output.GenerateContent());
}
else if (__tagHelperExecutionContext.ChildContentRetrieved)
{
WriteLiteral(__tagHelperExecutionContext.GetChildContentAsync().Result);
}
else
{
__tagHelperExecutionContext.ExecuteChildContentAsync().Wait();
}
WriteLiteral(__tagHelperExecutionContext.Output.GeneratePostContent());
WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag());
__tagHelperExecutionContext = __tagHelperScopeManager.End();
Instrumentation.BeginContext(231, 18, true);
WriteLiteral("\r\n </p>\r\n</div>");
Instrumentation.EndContext();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,8 @@
@addtaghelper "something"
<!div class="randomNonTagHelperAttribute">
<!p class="Hello World" @DateTime.Now>
<!input type="text" />
<!em>Not a TagHelper: </!em> <input type="@DateTime.Now" checked="true" />
</!p>
</!div>