Add tests to validate @tagHelperPrefix inheritance.

- Updated some naming bits that were still using the ViewStart name.
- Updated MvcRazorParserTests to test more cases of the parser, especially with @tagHelperPrefix.

#2110
This commit is contained in:
N. Taylor Mullen 2015-03-16 17:27:52 -07:00
parent f49d52b5fc
commit 2a28e6f4ce
15 changed files with 245 additions and 63 deletions

View File

@ -53,38 +53,62 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
Assert.Equal(expectedContent, responseContent); Assert.Equal(expectedContent, responseContent);
} }
public static IEnumerable<object[]> TagHelpersAreInheritedFromViewStartPagesData public static TheoryData TagHelpersAreInheritedFromGlobalImportPagesData
{ {
get get
{ {
var expected1 = // action, expected
@"<root>root-content</root> return new TheoryData<string, string>
{
{
<nested>nested-content</nested>"; "NestedGlobalImportTagHelper",
yield return new[] { "NestedViewStartTagHelper", expected1 }; string.Format(
"<root>root-content</root>{0}{0}{0}<nested>nested-content</nested>",
var expected2 = Environment.NewLine)
@"layout:<root>root-content</root> },
{
"ViewWithLayoutAndNestedTagHelper",
<nested>nested-content</nested>"; string.Format(
"layout:<root>root-content</root>{0}{0}{0}<nested>nested-content</nested>",
yield return new[] { "ViewWithLayoutAndNestedTagHelper", expected2 }; Environment.NewLine)
},
var expected3 = {
@"layout:<root>root-content</root> "ViewWithInheritedRemoveTagHelper",
string.Format(
"layout:<root>root-content</root>{0}{0}{0}page:<root/>{0}<nested>nested-content</nested>",
page:<root/> Environment.NewLine)
<nested>nested-content</nested>"; },
yield return new[] { "ViewWithInheritedRemoveTagHelper", expected3 }; {
"ViewWithInheritedTagHelperPrefix",
string.Format(
"layout:<root>root-content</root>{0}{0}{0}page:<root>root-content</root>",
Environment.NewLine)
},
{
"ViewWithOverriddenTagHelperPrefix",
string.Format(
"layout:<root>root-content</root>{0}{0}{0}{0}page:<root>root-content</root>",
Environment.NewLine)
},
{
"ViewWithNestedInheritedTagHelperPrefix",
string.Format(
"layout:<root>root-content</root>{0}{0}{0}page:<root>root-content</root>",
Environment.NewLine)
},
{
"ViewWithNestedOverriddenTagHelperPrefix",
string.Format(
"layout:<root>root-content</root>{0}{0}{0}{0}page:<root>root-content</root>",
Environment.NewLine)
},
};
} }
} }
[Theory] [Theory]
[MemberData(nameof(TagHelpersAreInheritedFromViewStartPagesData))] [MemberData(nameof(TagHelpersAreInheritedFromGlobalImportPagesData))]
public async Task TagHelpersAreInheritedFromViewStartPages(string action, string expected) public async Task TagHelpersAreInheritedFromGlobalImportPages(string action, string expected)
{ {
// Arrange // Arrange
var server = TestHelper.CreateServer(_app, SiteName); var server = TestHelper.CreateServer(_app, SiteName);
@ -158,7 +182,7 @@ page:<root/>
{ "Age", "1000" }, { "Age", "1000" },
{ "EmployeeId", "0" }, { "EmployeeId", "0" },
{ "Email", "a@b.com" }, { "Email", "a@b.com" },
{ "Salary", "z" }, { "Salary", "z" },
}; };
var postContent = new FormUrlEncodedContent(validPostValues); var postContent = new FormUrlEncodedContent(validPostValues);

View File

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Razor.Generator.Compiler; using Microsoft.AspNet.Razor.Generator.Compiler;
@ -15,30 +16,132 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
public class MvcRazorCodeParserTest public class MvcRazorCodeParserTest
{ {
[Fact] public static TheoryData GlobalImportData
public void GetTagHelperDescriptors_ReturnsDescriptorsFromViewStart() {
get
{
// codeTrees, expectedDirectiveDescriptors
return new TheoryData<CodeTree[], TagHelperDirectiveDescriptor[]>
{
{
new[] { CreateCodeTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP" }) },
new[] { CreateDirectiveDescriptor("THP", TagHelperDirectiveType.TagHelperPrefix) }
},
{
new[] { CreateCodeTree(new AddTagHelperChunk { LookupText = "ATH" }) },
new[] { CreateDirectiveDescriptor("ATH", TagHelperDirectiveType.AddTagHelper) }
},
{
new[]
{
CreateCodeTree(
new AddTagHelperChunk { LookupText = "ATH1" },
new AddTagHelperChunk { LookupText = "ATH2" })
},
new[]
{
CreateDirectiveDescriptor("ATH1", TagHelperDirectiveType.AddTagHelper),
CreateDirectiveDescriptor("ATH2", TagHelperDirectiveType.AddTagHelper)
}
},
{
new[] { CreateCodeTree(new RemoveTagHelperChunk { LookupText = "RTH" }) },
new[] { CreateDirectiveDescriptor("RTH", TagHelperDirectiveType.RemoveTagHelper) }
},
{
new[]
{
CreateCodeTree(
new RemoveTagHelperChunk { LookupText = "RTH1" },
new RemoveTagHelperChunk { LookupText = "RTH2" })
},
new[]
{
CreateDirectiveDescriptor("RTH1", TagHelperDirectiveType.RemoveTagHelper),
CreateDirectiveDescriptor("RTH2", TagHelperDirectiveType.RemoveTagHelper)
}
},
{
new[]
{
CreateCodeTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP1" }),
CreateCodeTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP2" }),
},
new[] { CreateDirectiveDescriptor("THP1", TagHelperDirectiveType.TagHelperPrefix) }
},
{
new[]
{
CreateCodeTree(
new TagHelperPrefixDirectiveChunk { Prefix = "THP" },
new RemoveTagHelperChunk { LookupText = "RTH" },
new AddTagHelperChunk { LookupText = "ATH" })
},
new[]
{
CreateDirectiveDescriptor("RTH", TagHelperDirectiveType.RemoveTagHelper),
CreateDirectiveDescriptor("ATH", TagHelperDirectiveType.AddTagHelper),
CreateDirectiveDescriptor("THP", TagHelperDirectiveType.TagHelperPrefix),
}
},
{
new[]
{
CreateCodeTree(
new LiteralChunk { Text = "Hello world" },
new AddTagHelperChunk { LookupText = "ATH" }),
CreateCodeTree(new RemoveTagHelperChunk { LookupText = "RTH" })
},
new[]
{
CreateDirectiveDescriptor("RTH", TagHelperDirectiveType.RemoveTagHelper),
CreateDirectiveDescriptor("ATH", TagHelperDirectiveType.AddTagHelper),
}
},
{
new[]
{
CreateCodeTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP" }),
CreateCodeTree(
new LiteralChunk { Text = "Hello world" },
new AddTagHelperChunk { LookupText = "ATH" }),
CreateCodeTree(new RemoveTagHelperChunk { LookupText = "RTH" })
},
new[]
{
CreateDirectiveDescriptor("RTH", TagHelperDirectiveType.RemoveTagHelper),
CreateDirectiveDescriptor("ATH", TagHelperDirectiveType.AddTagHelper),
CreateDirectiveDescriptor("THP", TagHelperDirectiveType.TagHelperPrefix),
}
},
{
new[]
{
CreateCodeTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP1" }),
CreateCodeTree(new AddTagHelperChunk { LookupText = "ATH" }),
CreateCodeTree(new RemoveTagHelperChunk { LookupText = "RTH" }),
CreateCodeTree(new TagHelperPrefixDirectiveChunk { Prefix = "THP2" }),
},
new[]
{
CreateDirectiveDescriptor("RTH", TagHelperDirectiveType.RemoveTagHelper),
CreateDirectiveDescriptor("ATH", TagHelperDirectiveType.AddTagHelper),
CreateDirectiveDescriptor("THP1", TagHelperDirectiveType.TagHelperPrefix),
}
},
};
}
}
[Theory]
[MemberData(nameof(GlobalImportData))]
public void GetTagHelperDescriptors_ReturnsExpectedDirectiveDescriptors(
CodeTree[] codeTrees,
TagHelperDirectiveDescriptor[] expectedDirectiveDescriptors)
{ {
// Arrange // Arrange
var builder = new BlockBuilder { Type = BlockType.Comment }; var builder = new BlockBuilder { Type = BlockType.Comment };
var block = new Block(builder); var block = new Block(builder);
var codeTrees = new[]
{
new CodeTree
{
Chunks = new Chunk[]
{
new LiteralChunk { Text = "Hello world" },
new AddTagHelperChunk { LookupText = "Add Tag Helper" },
}
},
new CodeTree
{
Chunks = new[]
{
new RemoveTagHelperChunk { LookupText = "Remove Tag Helper" },
}
}
};
IList<TagHelperDirectiveDescriptor> descriptors = null; IList<TagHelperDirectiveDescriptor> descriptors = null;
var resolver = new Mock<ITagHelperDescriptorResolver>(); var resolver = new Mock<ITagHelperDescriptorResolver>();
@ -50,25 +153,43 @@ namespace Microsoft.AspNet.Mvc.Razor
.Returns(Enumerable.Empty<TagHelperDescriptor>()) .Returns(Enumerable.Empty<TagHelperDescriptor>())
.Verifiable(); .Verifiable();
var baseParser = new RazorParser(new CSharpCodeParser(), var baseParser = new RazorParser(
new HtmlMarkupParser(), new CSharpCodeParser(),
resolver.Object); new HtmlMarkupParser(),
var parser = new TestableMvcRazorParser(baseParser, codeTrees, new Chunk[0]); tagHelperDescriptorResolver: resolver.Object);
var sink = new ParserErrorSink(); var parser = new TestableMvcRazorParser(baseParser, codeTrees, defaultInheritedChunks: new Chunk[0]);
// Act // Act
var result = parser.GetTagHelperDescriptorsPublic(block, sink).ToArray(); parser.GetTagHelperDescriptorsPublic(block, errorSink: new ParserErrorSink()).ToArray();
// Assert // Assert
Assert.NotNull(descriptors); Assert.NotNull(descriptors);
Assert.Equal(2, descriptors.Count); Assert.Equal(expectedDirectiveDescriptors.Length, descriptors.Count);
Assert.Equal("Remove Tag Helper", descriptors[0].DirectiveText); for (var i = 0; i < expectedDirectiveDescriptors.Length; i++)
Assert.Equal(SourceLocation.Undefined, descriptors[0].Location); {
var expected = expectedDirectiveDescriptors[i];
var actual = descriptors[i];
Assert.Equal("Add Tag Helper", descriptors[1].DirectiveText); Assert.Equal(expected.DirectiveText, actual.DirectiveText, StringComparer.Ordinal);
Assert.Equal(TagHelperDirectiveType.AddTagHelper, descriptors[1].DirectiveType); Assert.Equal(expected.Location, actual.Location);
Assert.Equal(SourceLocation.Undefined, descriptors[1].Location); Assert.Equal(expected.DirectiveType, actual.DirectiveType);
}
}
private static CodeTree CreateCodeTree(params Chunk[] chunks)
{
return new CodeTree
{
Chunks = chunks
};
}
private static TagHelperDirectiveDescriptor CreateDirectiveDescriptor(
string directiveText,
TagHelperDirectiveType directiveType)
{
return new TagHelperDirectiveDescriptor(directiveText, SourceLocation.Undefined, directiveType);
} }
private class TestableMvcRazorParser : MvcRazorParser private class TestableMvcRazorParser : MvcRazorParser

View File

@ -30,7 +30,7 @@ namespace TagHelpersWebSite.Controllers
return View(); return View();
} }
public ViewResult NestedViewStartTagHelper() public ViewResult NestedGlobalImportTagHelper()
{ {
return View(); return View();
} }
@ -44,5 +44,29 @@ namespace TagHelpersWebSite.Controllers
{ {
return View("/Views/RemoveInheritedTagHelpers/ViewWithInheritedRemoveTagHelper.cshtml"); return View("/Views/RemoveInheritedTagHelpers/ViewWithInheritedRemoveTagHelper.cshtml");
} }
public ViewResult ViewWithInheritedTagHelperPrefix()
{
return View("/Views/InheritedTagHelperPrefix/InheritedTagHelperPrefix.cshtml");
}
public ViewResult ViewWithOverriddenTagHelperPrefix()
{
return View("/Views/InheritedTagHelperPrefix/OverriddenTagHelperPrefix.cshtml");
}
public ViewResult ViewWithNestedInheritedTagHelperPrefix()
{
return View(
"/Views/InheritedTagHelperPrefix/NestedInheritedTagHelperPrefix/" +
"NestedInheritedTagHelperPrefix.cshtml");
}
public ViewResult ViewWithNestedOverriddenTagHelperPrefix()
{
return View(
"/Views/InheritedTagHelperPrefix/NestedInheritedTagHelperPrefix/" +
"NestedOverriddenTagHelperPrefix.cshtml");
}
} }
} }

View File

@ -7,7 +7,7 @@ using Microsoft.AspNet.Razor.TagHelpers;
namespace TagHelpersWebSite.TagHelpers namespace TagHelpersWebSite.TagHelpers
{ {
[HtmlElementName("nested")] [HtmlElementName("nested")]
public class NestedViewStartTagHelper : TagHelper public class NestedGlobalImportTagHelper : TagHelper
{ {
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {

View File

@ -1 +1 @@
@addTagHelper "TagHelpersWebSite.TagHelpers.NestedViewStartTagHelper, TagHelpersWebSite" @addTagHelper "TagHelpersWebSite.TagHelpers.NestedGlobalImportTagHelper, TagHelpersWebSite"

View File

@ -0,0 +1 @@
page:<inherited:root></inherited:root>

View File

@ -0,0 +1,3 @@
@tagHelperPrefix "nested-overridden"
page:<nested-overriddenroot></nested-overriddenroot>

View File

@ -0,0 +1,3 @@
@tagHelperPrefix "overridden"
page:<overriddenroot></overriddenroot>

View File

@ -0,0 +1 @@
@tagHelperPrefix "inherited:"

View File

@ -0,0 +1,3 @@
@{
Layout = "~/Views/Shared/_LayoutWithRootTagHelper.cshtml";
}

View File

@ -1,2 +1,2 @@
@removeTagHelper "TagHelpersWebSite.TagHelpers.RootViewStartTagHelper, TagHelpersWebSite" @removeTagHelper "TagHelpersWebSite.TagHelpers.RootViewStartTagHelper, TagHelpersWebSite"
@addTagHelper "TagHelpersWebSite.TagHelpers.NestedViewStartTagHelper, TagHelpersWebSite" @addTagHelper "TagHelpersWebSite.TagHelpers.NestedGlobalImportTagHelper, TagHelpersWebSite"

View File

@ -1,5 +1,5 @@
@{ @{
Layout = "~/Views/Shared/_LayoutWithRootTagHelper.cshtml"; Layout = "~/Views/Shared/_LayoutWithRootTagHelper.cshtml";
} }
@addTagHelper "TagHelpersWebSite.TagHelpers.NestedViewStartTagHelper, TagHelpersWebSite" @addTagHelper "TagHelpersWebSite.TagHelpers.NestedGlobalImportTagHelper, TagHelpersWebSite"
<nested>some-content</nested> <nested>some-content</nested>