Add tests to verify tagHelperPrefix directive.

- Added parsing, sub-rewriting, rewriting and code generation tests for runtime/designtime.
- Fixed existing tests to utilize new class structures.

#309
This commit is contained in:
N. Taylor Mullen 2015-02-24 19:59:19 -08:00
parent 4d97a544f1
commit 4bd02badda
10 changed files with 1337 additions and 92 deletions

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Razor.Parser;
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.AspNet.Razor.Text;
using Xunit;
@ -41,6 +42,491 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
}
public static TheoryData ResolveDirectiveDescriptorsInvalidTagHelperPrefixData
{
get
{
var assemblyA = AssemblyName;
var stringType = typeof(string);
var assemblyB = stringType.GetTypeInfo().Assembly.GetName().Name;
var defaultAssemblyLookups = new Dictionary<string, IEnumerable<Type>>
{
{ assemblyA, new[] { Valid_PlainTagHelperType, Valid_InheritedTagHelperType } },
{ assemblyB, new[] { stringType } }
};
var directiveLocation1 = new SourceLocation(1, 2, 3);
var directiveLocation2 = new SourceLocation(4, 5, 6);
var multipleDirectiveError =
"Invalid tag helper directive '{0}'. Cannot have multiple '{0}' directives on a page.";
var invalidTagHelperPrefixValueError =
"Invalid tag helper directive '{0}' value. '{1} is not allowed in prefix '{2}'.";
return new TheoryData<Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
IEnumerable<TagHelperDirectiveDescriptor>, // directiveDescriptors
IEnumerable<TagHelperDescriptor>, // expectedDescriptors
IEnumerable<RazorError>> // expectedErrors
{
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"th:",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"different",
directiveLocation2,
TagHelperDirectiveType.TagHelperPrefix)
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(multipleDirectiveError, SyntaxConstants.CSharp.TagHelperPrefixKeyword),
directiveLocation2)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"th:",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"different",
directiveLocation2,
TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
directiveLocation1,
TagHelperDirectiveType.AddTagHelper),
},
new[] { CreatePrefixedValidPlainDescriptor("th:") },
new[]
{
new RazorError(
string.Format(multipleDirectiveError, SyntaxConstants.CSharp.TagHelperPrefixKeyword),
directiveLocation2)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"th:",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"different",
directiveLocation2,
TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
directiveLocation1,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor(
"*String*, " + assemblyB,
directiveLocation1,
TagHelperDirectiveType.AddTagHelper),
},
new[] { CreatePrefixedValidPlainDescriptor("th:"), CreatePrefixedStringDescriptor("th:") },
new[]
{
new RazorError(
string.Format(multipleDirectiveError, SyntaxConstants.CSharp.TagHelperPrefixKeyword),
directiveLocation2)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"th ",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
' ',
"th "),
directiveLocation1)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"th\t",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
'\t',
"th\t"),
directiveLocation1)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"th" + Environment.NewLine,
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
Environment.NewLine[0],
"th" + Environment.NewLine),
directiveLocation1)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
" th ",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
' ',
" th "),
directiveLocation1)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"@",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
'@',
"@"),
directiveLocation1)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"t@h",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
'@',
"t@h"),
directiveLocation1)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"!",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
'!',
"!"),
directiveLocation1)
}
},
{
defaultAssemblyLookups,
new[]
{
new TagHelperDirectiveDescriptor(
"!th",
directiveLocation1,
TagHelperDirectiveType.TagHelperPrefix),
},
new TagHelperDescriptor[0],
new[]
{
new RazorError(
string.Format(
invalidTagHelperPrefixValueError,
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
'!',
"!th"),
directiveLocation1)
}
},
};
}
}
[Theory]
[MemberData(nameof(ResolveDirectiveDescriptorsInvalidTagHelperPrefixData))]
public void Resolve_CreatesExpectedErrorsForTagHelperPrefixDirectives(
Dictionary<string, IEnumerable<Type>> descriptorAssemblyLookups,
IEnumerable<TagHelperDirectiveDescriptor> directiveDescriptors,
IEnumerable<TagHelperDescriptor> expectedDescriptors,
IEnumerable<RazorError> expectedErrors)
{
// Arrange
var tagHelperDescriptorResolver =
new TestTagHelperDescriptorResolver(
new LookupBasedTagHelperTypeResolver(descriptorAssemblyLookups));
var errorSink = new ParserErrorSink();
var resolutionContext = new TagHelperDescriptorResolutionContext(
directiveDescriptors,
errorSink);
// Act
var descriptors = tagHelperDescriptorResolver.Resolve(resolutionContext);
// Assert
Assert.Equal(expectedErrors, errorSink.Errors);
Assert.Equal(expectedDescriptors.Count(), descriptors.Count());
foreach (var expectedDescriptor in expectedDescriptors)
{
Assert.Contains(expectedDescriptor, descriptors, TagHelperDescriptorComparer.Default);
}
}
public static TheoryData ResolveDirectiveDescriptorsTagHelperPrefixData
{
get
{
var assemblyA = AssemblyName;
var stringType = typeof(string);
var assemblyB = stringType.GetTypeInfo().Assembly.GetName().Name;
var defaultAssemblyLookups = new Dictionary<string, IEnumerable<Type>>
{
{ assemblyA, new[] { Valid_PlainTagHelperType, Valid_InheritedTagHelperType } },
{ assemblyB, new[] { stringType } }
};
return new TheoryData<
Dictionary<string, IEnumerable<Type>>, // descriptorAssemblyLookups
IEnumerable<TagHelperDirectiveDescriptor>, // directiveDescriptors
IEnumerable<TagHelperDescriptor>> // expectedDescriptors
{
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor("", TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
},
new [] { Valid_PlainTagHelperDescriptor }
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor("th:", TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
},
new [] { CreatePrefixedValidPlainDescriptor("th:") }
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor("th:", TagHelperDirectiveType.TagHelperPrefix)
},
new [] { CreatePrefixedValidPlainDescriptor("th:") }
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor("*, " + assemblyA, TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor("th:", TagHelperDirectiveType.TagHelperPrefix)
},
new []
{
CreatePrefixedValidPlainDescriptor("th:"),
CreatePrefixedValidInheritedDescriptor("th:")
}
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor("th-", TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor(
"*Inherited*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper)
},
new []
{
CreatePrefixedValidPlainDescriptor("th-"),
CreatePrefixedValidInheritedDescriptor("th-")
}
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor("", TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor(
"*Inherited*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper)
},
new [] { Valid_PlainTagHelperDescriptor, Valid_InheritedTagHelperDescriptor }
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor(
"*Plain*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor(
"*Inherited*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor("th:", TagHelperDirectiveType.TagHelperPrefix)
},
new []
{
CreatePrefixedValidPlainDescriptor("th:"),
CreatePrefixedValidInheritedDescriptor("th:")
}
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor("th", TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor(
"*, " + assemblyB,
TagHelperDirectiveType.AddTagHelper),
},
new []
{
CreatePrefixedValidPlainDescriptor("th"),
CreatePrefixedValidInheritedDescriptor("th"),
CreatePrefixedStringDescriptor("th")
}
},
{
defaultAssemblyLookups,
new []
{
new TagHelperDirectiveDescriptor(
"*, " + assemblyA,
TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor("th:-", TagHelperDirectiveType.TagHelperPrefix),
new TagHelperDirectiveDescriptor(
"*, " + assemblyB,
TagHelperDirectiveType.AddTagHelper),
},
new []
{
CreatePrefixedValidPlainDescriptor("th:-"),
CreatePrefixedValidInheritedDescriptor("th:-"),
CreatePrefixedStringDescriptor("th:-")
}
},
};
}
}
[Theory]
[MemberData(nameof(ResolveDirectiveDescriptorsTagHelperPrefixData))]
public void Resolve_ReturnsPrefixedDescriptorsBasedOnDirectiveDescriptors(
Dictionary<string, IEnumerable<Type>> descriptorAssemblyLookups,
IEnumerable<TagHelperDirectiveDescriptor> directiveDescriptors,
IEnumerable<TagHelperDescriptor> expectedDescriptors)
{
// Arrange
var tagHelperDescriptorResolver =
new TestTagHelperDescriptorResolver(
new LookupBasedTagHelperTypeResolver(descriptorAssemblyLookups));
var resolutionContext = new TagHelperDescriptorResolutionContext(
directiveDescriptors,
new ParserErrorSink());
// Act
var descriptors = tagHelperDescriptorResolver.Resolve(resolutionContext);
// Assert
Assert.Equal(expectedDescriptors.Count(), descriptors.Count());
foreach (var expectedDescriptor in expectedDescriptors)
{
Assert.Contains(expectedDescriptor, descriptors, TagHelperDescriptorComparer.Default);
}
}
[Theory]
[InlineData("MyType, MyAssembly", "MyAssembly")]
[InlineData("*, MyAssembly2", "MyAssembly2")]
@ -477,7 +963,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
new TestTagHelperDescriptorResolver(
new LookupBasedTagHelperTypeResolver(descriptorAssemblyLookups));
var resolutionContext = new TagHelperDescriptorResolutionContext(
directiveDescriptors,
directiveDescriptors,
new ParserErrorSink());
// Act
@ -832,7 +1318,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
"format is: \"typeName, assemblyName\".",
lookupText);
var resolutionContext = new TagHelperDescriptorResolutionContext(
new [] { new TagHelperDirectiveDescriptor(lookupText, documentLocation, directiveType)},
new[] { new TagHelperDirectiveDescriptor(lookupText, documentLocation, directiveType) },
errorSink);
// Act
@ -872,6 +1358,49 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Assert.Equal(expectedErrorMessage, error.Message);
}
private static TagHelperDescriptor CreateDescriptor(
string prefix,
string tagName,
string typeName,
string assemblyName)
{
return new TagHelperDescriptor(
prefix,
tagName,
typeName,
assemblyName,
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>());
}
private static TagHelperDescriptor CreatePrefixedValidPlainDescriptor(string prefix)
{
return CreateDescriptor(
prefix,
tagName: "valid_plain",
typeName: Valid_PlainTagHelperType.FullName,
assemblyName: AssemblyName);
}
private static TagHelperDescriptor CreatePrefixedValidInheritedDescriptor(string prefix)
{
return CreateDescriptor(
prefix,
tagName: "valid_inherited",
typeName: Valid_InheritedTagHelperType.FullName,
assemblyName: AssemblyName);
}
private static TagHelperDescriptor CreatePrefixedStringDescriptor(string prefix)
{
var stringType = typeof(string);
return CreateDescriptor(
prefix,
tagName: "string",
typeName: stringType.FullName,
assemblyName: stringType.GetTypeInfo().Assembly.GetName().Name);
}
private class TestTagHelperDescriptorResolver : TagHelperDescriptorResolver
{
public TestTagHelperDescriptorResolver(TagHelperTypeResolver typeResolver)
@ -939,8 +1468,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
protected override IEnumerable<TagHelperDescriptor> ResolveDescriptorsInAssembly(
string assemblyName,
SourceLocation documentLocation,
string assemblyName,
SourceLocation documentLocation,
ParserErrorSink errorSink)
{
throw _error;

View File

@ -320,6 +320,11 @@ namespace Microsoft.AspNet.Razor.Test.Framework
new AddOrRemoveTagHelperCodeGenerator(removeTagHelperDescriptors: true, lookupText: lookupText));
}
public SpanConstructor AsTagHelperPrefixDirective(string prefix)
{
return _self.With(new TagHelperPrefixDirectiveCodeGenerator(prefix));
}
public SpanConstructor As(ISpanCodeGenerator codeGenerator)
{
return _self.With(codeGenerator);

View File

@ -14,37 +14,10 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
public class CSharpTagHelperRenderingTest : TagHelperTestBase
{
private static IEnumerable<TagHelperDescriptor> PAndInputTagHelperDescriptors
{
get
{
var pAgePropertyInfo = typeof(TestType).GetProperty("Age");
var inputTypePropertyInfo = typeof(TestType).GetProperty("Type");
var checkedPropertyInfo = typeof(TestType).GetProperty("Checked");
return new[]
{
new TagHelperDescriptor("p",
"PTagHelper",
"SomeAssembly",
new [] {
new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
}),
new TagHelperDescriptor("input",
"InputTagHelper",
"SomeAssembly",
new TagHelperAttributeDescriptor[] {
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
}),
new TagHelperDescriptor("input",
"InputTagHelper2",
"SomeAssembly",
new TagHelperAttributeDescriptor[] {
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
})
};
}
}
private static IEnumerable<TagHelperDescriptor> DefaultPAndInputTagHelperDescriptors
=> BuildPAndInputTagHelperDescriptors(prefix: string.Empty);
private static IEnumerable<TagHelperDescriptor> PrefixedPAndInputTagHelperDescriptors
=> BuildPAndInputTagHelperDescriptors("THS");
public static TheoryData TagHelperDescriptorFlowTestData
{
@ -59,50 +32,64 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
"SingleTagHelper",
"SingleTagHelper",
PAndInputTagHelperDescriptors,
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
false
},
{
"SingleTagHelper",
"SingleTagHelper.DesignTime",
PAndInputTagHelperDescriptors,
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
true
},
{
"BasicTagHelpers",
"BasicTagHelpers",
PAndInputTagHelperDescriptors,
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
false
},
{
"BasicTagHelpers",
"BasicTagHelpers.DesignTime",
PAndInputTagHelperDescriptors,
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
true
},
{
"BasicTagHelpers.RemoveTagHelper",
"BasicTagHelpers.RemoveTagHelper",
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
Enumerable.Empty<TagHelperDescriptor>(),
false
},
{
"BasicTagHelpers.Prefixed",
"BasicTagHelpers.Prefixed",
PrefixedPAndInputTagHelperDescriptors,
PrefixedPAndInputTagHelperDescriptors,
false
},
{
"BasicTagHelpers.Prefixed",
"BasicTagHelpers.Prefixed.DesignTime",
PrefixedPAndInputTagHelperDescriptors,
PrefixedPAndInputTagHelperDescriptors,
true
},
{
"ComplexTagHelpers",
"ComplexTagHelpers",
PAndInputTagHelperDescriptors,
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
false
},
{
"ComplexTagHelpers",
"ComplexTagHelpers.DesignTime",
PAndInputTagHelperDescriptors,
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
true
}
};
@ -141,7 +128,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
"SingleTagHelper",
"SingleTagHelper.DesignTime",
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
new List<LineMapping>
{
BuildLineMapping(documentAbsoluteIndex: 14,
@ -161,7 +148,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
"BasicTagHelpers",
"BasicTagHelpers.DesignTime",
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
new List<LineMapping>
{
BuildLineMapping(documentAbsoluteIndex: 14,
@ -178,10 +165,36 @@ namespace Microsoft.AspNet.Razor.Test.Generator
contentLength: 4)
}
},
{
"BasicTagHelpers.Prefixed",
"BasicTagHelpers.Prefixed.DesignTime",
PrefixedPAndInputTagHelperDescriptors,
new List<LineMapping>
{
BuildLineMapping(documentAbsoluteIndex: 17,
documentLineIndex: 0,
generatedAbsoluteIndex: 496,
generatedLineIndex: 15,
characterOffsetIndex: 17,
contentLength: 5),
BuildLineMapping(documentAbsoluteIndex: 38,
documentLineIndex: 1,
generatedAbsoluteIndex: 655,
generatedLineIndex: 22,
characterOffsetIndex: 14,
contentLength: 17),
BuildLineMapping(documentAbsoluteIndex: 228,
documentLineIndex: 7,
generatedAbsoluteIndex: 1480,
generatedLineIndex: 46,
characterOffsetIndex: 43,
contentLength: 4)
}
},
{
"ComplexTagHelpers",
"ComplexTagHelpers.DesignTime",
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
new List<LineMapping>
{
BuildLineMapping(14, 0, 479, 15, 14, 17),
@ -217,7 +230,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
"EmptyAttributeTagHelpers",
"EmptyAttributeTagHelpers.DesignTime",
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
new List<LineMapping>
{
BuildLineMapping(documentAbsoluteIndex: 14,
@ -251,7 +264,7 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
"EscapedTagHelpers",
"EscapedTagHelpers.DesignTime",
PAndInputTagHelperDescriptors,
DefaultPAndInputTagHelperDescriptors,
new List<LineMapping>
{
BuildLineMapping(documentAbsoluteIndex: 14,
@ -308,12 +321,13 @@ namespace Microsoft.AspNet.Razor.Test.Generator
// Note: The baseline resource name is equivalent to the test resource name.
return new TheoryData<string, IEnumerable<TagHelperDescriptor>>
{
{ "SingleTagHelper", PAndInputTagHelperDescriptors },
{ "BasicTagHelpers", PAndInputTagHelperDescriptors },
{ "BasicTagHelpers.RemoveTagHelper", PAndInputTagHelperDescriptors },
{ "ComplexTagHelpers", PAndInputTagHelperDescriptors },
{ "EmptyAttributeTagHelpers", PAndInputTagHelperDescriptors },
{ "EscapedTagHelpers", PAndInputTagHelperDescriptors },
{ "SingleTagHelper", DefaultPAndInputTagHelperDescriptors },
{ "BasicTagHelpers", DefaultPAndInputTagHelperDescriptors },
{ "BasicTagHelpers.RemoveTagHelper", DefaultPAndInputTagHelperDescriptors },
{ "BasicTagHelpers.Prefixed", PrefixedPAndInputTagHelperDescriptors },
{ "ComplexTagHelpers", DefaultPAndInputTagHelperDescriptors },
{ "EmptyAttributeTagHelpers", DefaultPAndInputTagHelperDescriptors },
{ "EscapedTagHelpers", DefaultPAndInputTagHelperDescriptors },
};
}
}
@ -395,6 +409,41 @@ namespace Microsoft.AspNet.Razor.Test.Generator
RunTagHelperTest(testType, tagHelperDescriptors: tagHelperDescriptors);
}
private static IEnumerable<TagHelperDescriptor> BuildPAndInputTagHelperDescriptors(string prefix)
{
var pAgePropertyInfo = typeof(TestType).GetProperty("Age");
var inputTypePropertyInfo = typeof(TestType).GetProperty("Type");
var checkedPropertyInfo = typeof(TestType).GetProperty("Checked");
return new[]
{
new TagHelperDescriptor(
prefix,
tagName: "p",
typeName: "PTagHelper",
assemblyName: "SomeAssembly",
attributes: new [] {
new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
}),
new TagHelperDescriptor(
prefix,
tagName: "input",
typeName: "InputTagHelper",
assemblyName: "SomeAssembly",
attributes: new TagHelperAttributeDescriptor[] {
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
}),
new TagHelperDescriptor(
prefix,
tagName: "input",
typeName: "InputTagHelper2",
assemblyName: "SomeAssembly",
attributes: new TagHelperAttributeDescriptor[] {
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
})
};
}
private class TestType
{
public int Age { get; set; }

View File

@ -12,6 +12,100 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
{
public class CSharpDirectivesTest : CsHtmlCodeParserTestBase
{
[Fact]
public void TagHelperPrefixDirective_NoValueSucceeds()
{
ParseBlockTest("@tagHelperPrefix \"\"",
new DirectiveBlock(
Factory.CodeTransition(),
Factory
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharacters.None),
Factory.Code("\"\"").AsTagHelperPrefixDirective("")));
}
[Fact]
public void TagHelperPrefixDirective_Succeeds()
{
ParseBlockTest("@tagHelperPrefix \"Foo\"",
new DirectiveBlock(
Factory.CodeTransition(),
Factory
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharacters.None),
Factory.Code("\"Foo\"").AsTagHelperPrefixDirective("Foo")));
}
[Fact]
public void TagHelperPrefixDirective_RequiresValue()
{
ParseBlockTest("@tagHelperPrefix ",
new DirectiveBlock(
Factory.CodeTransition(),
Factory
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharacters.None),
Factory.EmptyCSharp().AsTagHelperPrefixDirective(string.Empty)),
new RazorError(
RazorResources.FormatParseError_DirectiveMustHaveValue(
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17));
}
[Fact]
public void TagHelperPrefixDirective_StartQuoteRequiresDoubleQuotesAroundValue()
{
ParseBlockTest("@tagHelperPrefix \"Foo",
new DirectiveBlock(
Factory.CodeTransition(),
Factory
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharacters.None),
Factory.Code("\"Foo").AsTagHelperPrefixDirective("Foo")),
new RazorError(
RazorResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 17, lineIndex: 0, columnIndex: 17),
new RazorError(
RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes(
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17));
}
[Fact]
public void TagHelperPrefixDirective_EndQuoteRequiresDoubleQuotesAroundValue()
{
ParseBlockTest("@tagHelperPrefix Foo\"",
new DirectiveBlock(
Factory.CodeTransition(),
Factory
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharacters.None),
Factory.Code("Foo\"").AsTagHelperPrefixDirective("Foo")),
new RazorError(
RazorResources.ParseError_Unterminated_String_Literal,
absoluteIndex: 20, lineIndex: 0, columnIndex: 20),
new RazorError(
RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes(
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17));
}
[Fact]
public void TagHelperPrefixDirective_RequiresDoubleQuotesAroundValue()
{
ParseBlockTest("@tagHelperPrefix Foo",
new DirectiveBlock(
Factory.CodeTransition(),
Factory
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharacters.None),
Factory.Code("Foo").AsTagHelperPrefixDirective("Foo")),
new RazorError(
RazorResources.FormatParseError_DirectiveMustBeSurroundedByQuotes(
SyntaxConstants.CSharp.TagHelperPrefixKeyword),
absoluteIndex: 17, lineIndex: 0, columnIndex: 17));
}
[Fact]
public void RemoveTagHelperDirective_Succeeds()
{

View File

@ -10,7 +10,93 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
public class TagHelperDescriptorProviderTest
{
[Fact]
public void TagHelperDescriptorProvider_GetTagHelpersReturnsNothingForUnregisteredTags()
public void GetTagHelpers_ReturnsEmptyDescriptorsWithPrefixAsTagName()
{
// Arrange
var catchAllDescriptor = CreatePrefixedDescriptor("th", "*", "foo1");
var descriptors = new[] { catchAllDescriptor };
var provider = new TagHelperDescriptorProvider(descriptors);
// Act
var resolvedDescriptors = provider.GetTagHelpers("th");
// Assert
Assert.Empty(resolvedDescriptors);
}
[Fact]
public void GetTagHelpers_OnlyUnderstandsSinglePrefix()
{
// Arrange
var divDescriptor = CreatePrefixedDescriptor("th:", "div", "foo1");
var spanDescriptor = CreatePrefixedDescriptor("th2:", "span", "foo2");
var descriptors = new[] { divDescriptor, spanDescriptor };
var provider = new TagHelperDescriptorProvider(descriptors);
// Act
var retrievedDescriptorsDiv = provider.GetTagHelpers("th:div");
var retrievedDescriptorsSpan = provider.GetTagHelpers("th2:span");
// Assert
var descriptor = Assert.Single(retrievedDescriptorsDiv);
Assert.Same(divDescriptor, descriptor);
Assert.Empty(retrievedDescriptorsSpan);
}
[Fact]
public void GetTagHelpers_ReturnsCatchAllDescriptorsForPrefixedTags()
{
// Arrange
var catchAllDescriptor = CreatePrefixedDescriptor("th:", "*", "foo1");
var descriptors = new[] { catchAllDescriptor };
var provider = new TagHelperDescriptorProvider(descriptors);
// Act
var retrievedDescriptorsDiv = provider.GetTagHelpers("th:div");
var retrievedDescriptorsSpan = provider.GetTagHelpers("th:span");
// Assert
var descriptor = Assert.Single(retrievedDescriptorsDiv);
Assert.Same(catchAllDescriptor, descriptor);
descriptor = Assert.Single(retrievedDescriptorsSpan);
Assert.Same(catchAllDescriptor, descriptor);
}
[Fact]
public void GetTagHelpers_ReturnsDescriptorsForPrefixedTags()
{
// Arrange
var divDescriptor = CreatePrefixedDescriptor("th:", "div", "foo1");
var descriptors = new[] { divDescriptor };
var provider = new TagHelperDescriptorProvider(descriptors);
// Act
var retrievedDescriptors = provider.GetTagHelpers("th:div");
// Assert
var descriptor = Assert.Single(retrievedDescriptors);
Assert.Same(divDescriptor, descriptor);
}
[Theory]
[InlineData("*")]
[InlineData("div")]
public void GetTagHelpers_ReturnsNothingForUnprefixedTags(string tagName)
{
// Arrange
var divDescriptor = CreatePrefixedDescriptor("th:", tagName, "foo1");
var descriptors = new[] { divDescriptor };
var provider = new TagHelperDescriptorProvider(descriptors);
// Act
var retrievedDescriptorsDiv = provider.GetTagHelpers("div");
// Assert
Assert.Empty(retrievedDescriptorsDiv);
}
[Fact]
public void GetTagHelpers_ReturnsNothingForUnregisteredTags()
{
// Arrange
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
@ -26,7 +112,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
}
[Fact]
public void TagHelperDescriptorProvider_GetTagHelpersDoesNotReturnNonCatchAllTagsForCatchAll()
public void GetTagHelpers_DoesNotReturnNonCatchAllTagsForCatchAll()
{
// Arrange
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
@ -44,7 +130,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
}
[Fact]
public void TagHelperDescriptorProvider_GetTagHelpersReturnsCatchAllsWithEveryTagName()
public void GetTagHelpers_ReturnsCatchAllsWithEveryTagName()
{
// Arrange
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
@ -70,7 +156,7 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
}
[Fact]
public void TagHelperDescriptorProvider_DuplicateDescriptorsAreNotPartOfTagHelperDescriptorPool()
public void GetTagHelpers_DuplicateDescriptorsAreNotPartOfTagHelperDescriptorPool()
{
// Arrange
var divDescriptor = new TagHelperDescriptor("div", "foo1", "SomeAssembly");
@ -84,5 +170,15 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
var descriptor = Assert.Single(retrievedDescriptors);
Assert.Same(divDescriptor, descriptor);
}
private static TagHelperDescriptor CreatePrefixedDescriptor(string prefix, string tagName, string typeName)
{
return new TagHelperDescriptor(
prefix,
tagName,
typeName,
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>());
}
}
}

View File

@ -16,7 +16,7 @@ using Xunit;
namespace Microsoft.AspNet.Razor.TagHelpers
{
public class AddOrRemoveTagHelperSpanVisitorTest
public class TagHelperDirectiveSpanVisitorTest
{
private static readonly SpanFactory Factory = SpanFactory.CreateCsHtml();
@ -28,16 +28,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
var resolver = new Mock<ITagHelperDescriptorResolver>();
resolver.Setup(mock => mock.Resolve(It.IsAny<TagHelperDescriptorResolutionContext>()))
.Returns(Enumerable.Empty<TagHelperDescriptor>());
var addOrRemoveTagHelperSpanVisitor = new AddOrRemoveTagHelperSpanVisitor(
var tagHelperDirectiveSpanVisitor = new TagHelperDirectiveSpanVisitor(
resolver.Object,
new ParserErrorSink());
var document = new MarkupBlock(
Factory.Code("\"one\"").AsAddTagHelper("one"),
Factory.Code("\"two\"").AsRemoveTagHelper("two"),
Factory.Code("\"three\"").AsRemoveTagHelper("three"));
Factory.Code("\"three\"").AsRemoveTagHelper("three"),
Factory.Code("\"four\"").AsTagHelperPrefixDirective("four"));
// Act
addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
tagHelperDirectiveSpanVisitor.GetDescriptors(document);
// Assert
resolver.Verify(mock => mock.Resolve(It.IsAny<TagHelperDescriptorResolutionContext>()), Times.Once);
@ -49,25 +50,28 @@ namespace Microsoft.AspNet.Razor.TagHelpers
{
// Arrange
var resolver = new TestTagHelperDescriptorResolver();
var addOrRemoveTagHelperSpanVisitor = new AddOrRemoveTagHelperSpanVisitor(resolver, new ParserErrorSink());
var tagHelperDirectiveSpanVisitor = new TagHelperDirectiveSpanVisitor(resolver, new ParserErrorSink());
var document = new MarkupBlock(
Factory.Code("\"one\"").AsAddTagHelper("one"),
Factory.Code("\"two\"").AsRemoveTagHelper("two"),
Factory.Code("\"three\"").AsRemoveTagHelper("three"));
var expectedRegistrations = new TagHelperDirectiveDescriptor[]
Factory.Code("\"three\"").AsRemoveTagHelper("three"),
Factory.Code("\"four\"").AsTagHelperPrefixDirective("four"));
var expectedDescriptors = new TagHelperDirectiveDescriptor[]
{
new TagHelperDirectiveDescriptor("one", TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor("two", TagHelperDirectiveType.RemoveTagHelper),
new TagHelperDirectiveDescriptor("three", TagHelperDirectiveType.RemoveTagHelper),
new TagHelperDirectiveDescriptor("four", TagHelperDirectiveType.TagHelperPrefix),
};
// Act
addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
tagHelperDirectiveSpanVisitor.GetDescriptors(document);
// Assert
Assert.Equal(expectedRegistrations,
resolver.DirectiveDescriptors,
TagHelperDirectiveDescriptorComparer.Default);
Assert.Equal(
expectedDescriptors,
resolver.DirectiveDescriptors,
TagHelperDirectiveDescriptorComparer.Default);
}
[Fact]
@ -80,29 +84,32 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new TagHelperDirectiveDescriptor("one", TagHelperDirectiveType.AddTagHelper),
new TagHelperDirectiveDescriptor("two", TagHelperDirectiveType.RemoveTagHelper),
new TagHelperDirectiveDescriptor("three", TagHelperDirectiveType.RemoveTagHelper),
new TagHelperDirectiveDescriptor("four", TagHelperDirectiveType.TagHelperPrefix),
};
var expectedEndDirectiveDescriptors = new TagHelperDirectiveDescriptor[]
{
new TagHelperDirectiveDescriptor("custom", TagHelperDirectiveType.AddTagHelper)
};
var addOrRemoveTagHelperSpanVisitor = new CustomAddOrRemoveTagHelperSpanVisitor(
var tagHelperDirectiveSpanVisitor = new CustomTagHelperDirectiveSpanVisitor(
resolver,
(descriptors, errorSink) =>
{
Assert.Equal(expectedInitialDirectiveDescriptors,
descriptors,
TagHelperDirectiveDescriptorComparer.Default);
Assert.Equal(
expectedInitialDirectiveDescriptors,
descriptors,
TagHelperDirectiveDescriptorComparer.Default);
return new TagHelperDescriptorResolutionContext(expectedEndDirectiveDescriptors, errorSink);
});
var document = new MarkupBlock(
Factory.Code("\"one\"").AsAddTagHelper("one"),
Factory.Code("\"two\"").AsRemoveTagHelper("two"),
Factory.Code("\"three\"").AsRemoveTagHelper("three"));
Factory.Code("\"three\"").AsRemoveTagHelper("three"),
Factory.Code("\"four\"").AsTagHelperPrefixDirective("four"));
// Act
addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
tagHelperDirectiveSpanVisitor.GetDescriptors(document);
// Assert
Assert.Equal(expectedEndDirectiveDescriptors,
@ -110,12 +117,39 @@ namespace Microsoft.AspNet.Razor.TagHelpers
TagHelperDirectiveDescriptorComparer.Default);
}
[Fact]
public void GetDescriptors_LocatesTagHelperPrefixDirectiveCodeGenerator()
{
// Arrange
var resolver = new TestTagHelperDescriptorResolver();
var tagHelperDirectiveSpanVisitor = new TagHelperDirectiveSpanVisitor(resolver, new ParserErrorSink());
var document = new MarkupBlock(
new DirectiveBlock(
Factory.CodeTransition(),
Factory
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
.Accepts(AcceptedCharacters.None),
Factory.Code("\"something\"").AsTagHelperPrefixDirective("something")));
var expectedDirectiveDescriptor =
new TagHelperDirectiveDescriptor("something", TagHelperDirectiveType.TagHelperPrefix);
// Act
tagHelperDirectiveSpanVisitor.GetDescriptors(document);
// Assert
var directiveDescriptor = Assert.Single(resolver.DirectiveDescriptors);
Assert.Equal(
expectedDirectiveDescriptor,
directiveDescriptor,
TagHelperDirectiveDescriptorComparer.Default);
}
[Fact]
public void GetDescriptors_LocatesAddTagHelperCodeGenerator()
{
// Arrange
var resolver = new TestTagHelperDescriptorResolver();
var addOrRemoveTagHelperSpanVisitor = new AddOrRemoveTagHelperSpanVisitor(resolver, new ParserErrorSink());
var tagHelperDirectiveSpanVisitor = new TagHelperDirectiveSpanVisitor(resolver, new ParserErrorSink());
var document = new MarkupBlock(
new DirectiveBlock(
Factory.CodeTransition(),
@ -127,7 +161,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new TagHelperDirectiveDescriptor("something", TagHelperDirectiveType.AddTagHelper);
// Act
addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
tagHelperDirectiveSpanVisitor.GetDescriptors(document);
// Assert
var directiveDescriptor = Assert.Single(resolver.DirectiveDescriptors);
@ -139,7 +173,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
{
// Arrange
var resolver = new TestTagHelperDescriptorResolver();
var addOrRemoveTagHelperSpanVisitor = new AddOrRemoveTagHelperSpanVisitor(resolver, new ParserErrorSink());
var tagHelperDirectiveSpanVisitor = new TagHelperDirectiveSpanVisitor(resolver, new ParserErrorSink());
var document = new MarkupBlock(
new DirectiveBlock(
Factory.CodeTransition(),
@ -151,7 +185,7 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new TagHelperDirectiveDescriptor("something", TagHelperDirectiveType.RemoveTagHelper);
// Act
addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
tagHelperDirectiveSpanVisitor.GetDescriptors(document);
// Assert
var directiveDescriptor = Assert.Single(resolver.DirectiveDescriptors);
@ -162,14 +196,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
public void GetDescriptors_RemoveTagHelperNotInDocument_DoesNotThrow()
{
// Arrange
var addOrRemoveTagHelperSpanVisitor =
new AddOrRemoveTagHelperSpanVisitor(
var tagHelperDirectiveSpanVisitor =
new TagHelperDirectiveSpanVisitor(
new TestTagHelperDescriptorResolver(),
new ParserErrorSink());
var document = new MarkupBlock(Factory.Markup("Hello World"));
// Act
var descriptors = addOrRemoveTagHelperSpanVisitor.GetDescriptors(document);
var descriptors = tagHelperDirectiveSpanVisitor.GetDescriptors(document);
Assert.Empty(descriptors);
}
@ -203,8 +237,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
public bool Equals(TagHelperDirectiveDescriptor directiveDescriptorX,
TagHelperDirectiveDescriptor directiveDescriptorY)
{
return string.Equals(directiveDescriptorX.LookupText,
directiveDescriptorY.LookupText,
return string.Equals(directiveDescriptorX.DirectiveText,
directiveDescriptorY.DirectiveText,
StringComparison.Ordinal) &&
directiveDescriptorX.DirectiveType == directiveDescriptorY.DirectiveType;
}
@ -213,19 +247,19 @@ namespace Microsoft.AspNet.Razor.TagHelpers
{
return HashCodeCombiner.Start()
.Add(base.GetHashCode())
.Add(directiveDescriptor.LookupText)
.Add(directiveDescriptor.DirectiveText)
.Add(directiveDescriptor.DirectiveType)
.CombinedHash;
}
}
private class CustomAddOrRemoveTagHelperSpanVisitor : AddOrRemoveTagHelperSpanVisitor
private class CustomTagHelperDirectiveSpanVisitor : TagHelperDirectiveSpanVisitor
{
private Func<IEnumerable<TagHelperDirectiveDescriptor>,
ParserErrorSink,
TagHelperDescriptorResolutionContext> _replacer;
public CustomAddOrRemoveTagHelperSpanVisitor(
public CustomTagHelperDirectiveSpanVisitor(
ITagHelperDescriptorResolver descriptorResolver,
Func<IEnumerable<TagHelperDirectiveDescriptor>,
ParserErrorSink,

View File

@ -19,6 +19,282 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
{
public class TagHelperParseTreeRewriterTest : CsHtmlMarkupParserTestBase
{
public static TheoryData PrefixedTagHelperBoundData
{
get
{
var factory = CreateDefaultSpanFactory();
var blockFactory = new BlockFactory(factory);
var availableDescriptorsColon = new TagHelperDescriptor[]
{
new TagHelperDescriptor(
prefix: "th:",
tagName: "myth",
typeName: "mythTagHelper",
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>()),
new TagHelperDescriptor(
prefix: "th:",
tagName: "myth2",
typeName: "mythTagHelper2",
assemblyName: "SomeAssembly",
attributes: new []
{
new TagHelperAttributeDescriptor(
name: "bound",
propertyName: "Bound",
typeName: typeof(bool).FullName),
})
};
var availableDescriptorsText = new TagHelperDescriptor[]
{
new TagHelperDescriptor(
prefix: "PREFIX",
tagName: "myth",
typeName: "mythTagHelper",
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>()),
new TagHelperDescriptor(
prefix: "PREFIX",
tagName: "myth2",
typeName: "mythTagHelper2",
assemblyName: "SomeAssembly",
attributes: new []
{
new TagHelperAttributeDescriptor(
name: "bound",
propertyName: "Bound",
typeName: typeof(bool).FullName),
})
};
var availableDescriptorsCatchAll = new TagHelperDescriptor[]
{
new TagHelperDescriptor(
prefix: "myth",
tagName: "*",
typeName: "mythTagHelper",
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>()),
};
// documentContent, expectedOutput, availableDescriptors
return new TheoryData<string, MarkupBlock, IEnumerable<TagHelperDescriptor>>
{
{
"<myth />",
new MarkupBlock(blockFactory.MarkupTagBlock("<myth />")),
availableDescriptorsCatchAll
},
{
"<myth>words and spaces</myth>",
new MarkupBlock(
blockFactory.MarkupTagBlock("<myth>"),
factory.Markup("words and spaces"),
blockFactory.MarkupTagBlock("</myth>")),
availableDescriptorsCatchAll
},
{
"<th:myth />",
new MarkupBlock(
new MarkupTagHelperBlock("th:myth", selfClosing: true)),
availableDescriptorsColon
},
{
"<PREFIXmyth />",
new MarkupBlock(
new MarkupTagHelperBlock("PREFIXmyth", selfClosing: true)),
availableDescriptorsText
},
{
"<th:myth></th:myth>",
new MarkupBlock(
new MarkupTagHelperBlock("th:myth")),
availableDescriptorsColon
},
{
"<PREFIXmyth></PREFIXmyth>",
new MarkupBlock(
new MarkupTagHelperBlock("PREFIXmyth")),
availableDescriptorsText
},
{
"<th:myth><th:my2th></th:my2th></th:myth>",
new MarkupBlock(
new MarkupTagHelperBlock(
"th:myth",
blockFactory.MarkupTagBlock("<th:my2th>"),
blockFactory.MarkupTagBlock("</th:my2th>"))),
availableDescriptorsColon
},
{
"<PREFIXmyth><PREFIXmy2th></PREFIXmy2th></PREFIXmyth>",
new MarkupBlock(
new MarkupTagHelperBlock(
"PREFIXmyth",
blockFactory.MarkupTagBlock("<PREFIXmy2th>"),
blockFactory.MarkupTagBlock("</PREFIXmy2th>"))),
availableDescriptorsText
},
{
"<!th:myth />",
new MarkupBlock(
blockFactory.EscapedMarkupTagBlock("<", "th:myth />")),
availableDescriptorsColon
},
{
"<!PREFIXmyth />",
new MarkupBlock(
blockFactory.EscapedMarkupTagBlock("<", "PREFIXmyth />")),
availableDescriptorsText
},
{
"<!th:myth></!th:myth>",
new MarkupBlock(
blockFactory.EscapedMarkupTagBlock("<", "th:myth>"),
blockFactory.EscapedMarkupTagBlock("</", "th:myth>")),
availableDescriptorsColon
},
{
"<!PREFIXmyth></!PREFIXmyth>",
new MarkupBlock(
blockFactory.EscapedMarkupTagBlock("<", "PREFIXmyth>"),
blockFactory.EscapedMarkupTagBlock("</", "PREFIXmyth>")),
availableDescriptorsText
},
{
"<th:myth class=\"btn\" />",
new MarkupBlock(
new MarkupTagHelperBlock(
"th:myth",
selfClosing: true,
attributes: new Dictionary<string, SyntaxTreeNode>
{
{ "class", factory.Markup("btn") }
})),
availableDescriptorsColon
},
{
"<PREFIXmyth class=\"btn\" />",
new MarkupBlock(
new MarkupTagHelperBlock(
"PREFIXmyth",
selfClosing: true,
attributes: new Dictionary<string, SyntaxTreeNode>
{
{ "class", factory.Markup("btn") }
})),
availableDescriptorsText
},
{
"<th:myth2 class=\"btn\" />",
new MarkupBlock(
new MarkupTagHelperBlock(
"th:myth2",
selfClosing: true,
attributes: new Dictionary<string, SyntaxTreeNode>
{
{ "class", factory.Markup("btn") }
})),
availableDescriptorsColon
},
{
"<PREFIXmyth2 class=\"btn\" />",
new MarkupBlock(
new MarkupTagHelperBlock(
"PREFIXmyth2",
selfClosing: true,
attributes: new Dictionary<string, SyntaxTreeNode>
{
{ "class", factory.Markup("btn") }
})),
availableDescriptorsText
},
{
"<th:myth class=\"btn\">words and spaces</th:myth>",
new MarkupBlock(
new MarkupTagHelperBlock(
"th:myth",
attributes: new Dictionary<string, SyntaxTreeNode>
{
{ "class", factory.Markup("btn") }
},
children: factory.Markup("words and spaces"))),
availableDescriptorsColon
},
{
"<PREFIXmyth class=\"btn\">words and spaces</PREFIXmyth>",
new MarkupBlock(
new MarkupTagHelperBlock(
"PREFIXmyth",
attributes: new Dictionary<string, SyntaxTreeNode>
{
{ "class", factory.Markup("btn") }
},
children: factory.Markup("words and spaces"))),
availableDescriptorsText
},
{
"<th:myth2 bound=\"@DateTime.Now\" />",
new MarkupBlock(
new MarkupTagHelperBlock(
"th:myth2",
selfClosing: true,
attributes: new Dictionary<string, SyntaxTreeNode>
{
{
"bound",
new MarkupBlock(
new MarkupBlock(
new ExpressionBlock(
factory.CodeTransition(),
factory.Code("DateTime.Now")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))) }
})),
availableDescriptorsColon
},
{
"<PREFIXmyth2 bound=\"@DateTime.Now\" />",
new MarkupBlock(
new MarkupTagHelperBlock(
"PREFIXmyth2",
selfClosing: true,
attributes: new Dictionary<string, SyntaxTreeNode>
{
{
"bound",
new MarkupBlock(
new MarkupBlock(
new ExpressionBlock(
factory.CodeTransition(),
factory.Code("DateTime.Now")
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
.Accepts(AcceptedCharacters.NonWhiteSpace)))) }
})),
availableDescriptorsText
},
};
}
}
[Theory]
[MemberData(nameof(PrefixedTagHelperBoundData))]
public void Rewrite_AllowsPrefixedTagHelpers(
string documentContent,
MarkupBlock expectedOutput,
IEnumerable<TagHelperDescriptor> availableDescriptors)
{
// Arrange
var descriptorProvider = new TagHelperDescriptorProvider(availableDescriptors);
// Act & Assert
EvaluateData(
descriptorProvider,
documentContent,
expectedOutput,
expectedErrors: Enumerable.Empty<RazorError>());
}
public static TheoryData EmptyTagHelperBoundAttributeData
{
get

View File

@ -0,0 +1,55 @@
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class BasicTagHelpers.Prefixed
{
private static object @__o;
private void @__RazorDesignTimeHelpers__()
{
#pragma warning disable 219
string __tagHelperDirectiveSyntaxHelper = null;
__tagHelperDirectiveSyntaxHelper =
#line 1 "BasicTagHelpers.Prefixed.cshtml"
"THS"
#line default
#line hidden
;
__tagHelperDirectiveSyntaxHelper =
#line 2 "BasicTagHelpers.Prefixed.cshtml"
"something, nice"
#line default
#line hidden
;
#pragma warning restore 219
}
#line hidden
private PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
#line hidden
public BasicTagHelpers.Prefixed()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__InputTagHelper.Type = "checkbox";
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__InputTagHelper2.Type = __InputTagHelper.Type;
#line 8 "BasicTagHelpers.Prefixed.cshtml"
__InputTagHelper2.Checked = true;
#line default
#line hidden
__PTagHelper = CreateTagHelper<PTagHelper>();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,97 @@
#pragma checksum "BasicTagHelpers.Prefixed.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "27630097585fd58e68cb0ac5b772154eff02a52a"
namespace TestOutput
{
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Threading.Tasks;
public class BasicTagHelpers.Prefixed
{
#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 PTagHelper __PTagHelper = null;
private InputTagHelper __InputTagHelper = null;
private InputTagHelper2 __InputTagHelper2 = null;
#line hidden
public BasicTagHelpers.Prefixed()
{
}
#pragma warning disable 1998
public override async Task ExecuteAsync()
{
Instrumentation.BeginContext(57, 52, true);
WriteLiteral("\r\n<THSdiv class=\"randomNonTagHelperAttribute\">\r\n ");
Instrumentation.EndContext();
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("p", false, "test", async() => {
WriteLiteral("\r\n <p></p>\r\n <input type=\"text\" />\r\n ");
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("input", true, "test", async() => {
}
, StartWritingScope, EndWritingScope);
__InputTagHelper = CreateTagHelper<InputTagHelper>();
__tagHelperExecutionContext.Add(__InputTagHelper);
__InputTagHelper.Type = "checkbox";
__tagHelperExecutionContext.AddTagHelperAttribute("type", __InputTagHelper.Type);
__InputTagHelper2 = CreateTagHelper<InputTagHelper2>();
__tagHelperExecutionContext.Add(__InputTagHelper2);
__InputTagHelper2.Type = __InputTagHelper.Type;
#line 8 "BasicTagHelpers.Prefixed.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();
WriteLiteral("\r\n ");
}
, StartWritingScope, EndWritingScope);
__PTagHelper = CreateTagHelper<PTagHelper>();
__tagHelperExecutionContext.Add(__PTagHelper);
__tagHelperExecutionContext.AddHtmlAttribute("class", "Hello World");
__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(249, 11, true);
WriteLiteral("\r\n</THSdiv>");
Instrumentation.EndContext();
}
#pragma warning restore 1998
}
}

View File

@ -0,0 +1,10 @@
@tagHelperPrefix "THS"
@addTagHelper "something, nice"
<THSdiv class="randomNonTagHelperAttribute">
<THSp class="Hello World">
<p></p>
<input type="text" />
<THSinput type="checkbox" checked="true" />
</THSp>
</THSdiv>