Add tests to verify TagHelperParseTreeVisitor.
- Added tests to validate TagHelperParseTreeVisitor when dealing with valid HTML elements. #71
This commit is contained in:
parent
bb3ad0ede4
commit
20824f37e0
|
|
@ -0,0 +1,982 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
using Microsoft.AspNet.Razor.Parser.TagHelpers.Internal;
|
||||
using Microsoft.AspNet.Razor.TagHelpers;
|
||||
using Microsoft.AspNet.Razor.Test.Framework;
|
||||
using Microsoft.AspNet.Razor.Text;
|
||||
using Microsoft.AspNet.Razor.Tokenizer;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.Test.TagHelpers
|
||||
{
|
||||
public class TagHelperParseTreeRewriterTest : CsHtmlMarkupParserTestBase
|
||||
{
|
||||
public static IEnumerable<object[]> TextTagsBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
|
||||
// Should re-write text tags that aren't in C# blocks
|
||||
yield return new object[] {
|
||||
"<text>Hello World</text>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("text",
|
||||
factory.Markup("Hello World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"@{<text>Hello World</text>}",
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.MarkupTransition("<text>")),
|
||||
factory.Markup("Hello World").Accepts(AcceptedCharacters.None),
|
||||
new MarkupTagBlock(
|
||||
factory.MarkupTransition("</text>"))),
|
||||
factory.EmptyCSharp().AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml())
|
||||
};
|
||||
yield return new object[] {
|
||||
"@{<text><p>Hello World</p></text>}",
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.MarkupTransition("<text>")),
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello World")),
|
||||
new MarkupTagBlock(
|
||||
factory.MarkupTransition("</text>"))),
|
||||
factory.EmptyCSharp().AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml())
|
||||
};
|
||||
yield return new object[] {
|
||||
"@{<p><text>Hello World</text></p>}",
|
||||
new MarkupBlock(
|
||||
factory.EmptyHtml(),
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.MetaCode("{").Accepts(AcceptedCharacters.None),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new MarkupTagHelperBlock("text",
|
||||
factory.Markup("Hello World")))),
|
||||
factory.EmptyCSharp().AsStatement(),
|
||||
factory.MetaCode("}").Accepts(AcceptedCharacters.None)),
|
||||
factory.EmptyHtml())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TextTagsBlockData))]
|
||||
public void TagHelperParseTreeRewriter_DoesntRewriteTextTagTransitionTagHelpers(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "text");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SpecialTagsBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
|
||||
yield return new object[] {
|
||||
"<foo><!-- Hello World --></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<!-- Hello World -->"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<foo><!-- @foo --></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<!-- "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" -->"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<foo><?xml Hello World ?></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<?xml Hello World ?>"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<foo><?xml @foo ?></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<?xml "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" ?>"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<foo><!DOCTYPE @foo ></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<!DOCTYPE "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" >"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<foo><!DOCTYPE hello=\"world\" ></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<!DOCTYPE hello=\"world\" >"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<foo><![CDATA[ Hello World ]]></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<![CDATA[ Hello World ]]>"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<foo><![CDATA[ @foo ]]></foo>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<foo>")),
|
||||
factory.Markup("<![CDATA[ "),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("foo")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)),
|
||||
factory.Markup(" ]]>"),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("</foo>")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SpecialTagsBlockData))]
|
||||
public void TagHelperParseTreeRewriter_DoesntRewriteSpecialTagTagHelpers(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "!--", "?xml", "![CDATA[", "!DOCTYPE");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> OddlySpacedBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
|
||||
yield return new object[] {
|
||||
"<p class=\" foo\" style=\" color : red ; \" ></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup(" foo")) },
|
||||
{ "style",
|
||||
new MarkupBlock(
|
||||
factory.Markup(" color"),
|
||||
factory.Markup(" :"),
|
||||
factory.Markup(" red"),
|
||||
factory.Markup(" ;"),
|
||||
factory.Markup(" "))
|
||||
}
|
||||
}))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=\" foo\" style=\" color : red ; \" >Hello World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup(" foo")) },
|
||||
{ "style",
|
||||
new MarkupBlock(
|
||||
factory.Markup(" color"),
|
||||
factory.Markup(" :"),
|
||||
factory.Markup(" red"),
|
||||
factory.Markup(" ;"),
|
||||
factory.Markup(" "))
|
||||
}
|
||||
},
|
||||
factory.Markup("Hello World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=\" foo \" >Hello</p> <p style=\" color:red; \" >World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup(" foo"), factory.Markup(" ")) }
|
||||
},
|
||||
factory.Markup("Hello")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "style", new MarkupBlock(factory.Markup(" color:red;"), factory.Markup(" ")) }
|
||||
},
|
||||
factory.Markup("World")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(OddlySpacedBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesOddlySpacedTagHelperTagBlocks(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ComplexAttributeTagHelperBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
var dateTimeNowString = "@DateTime.Now";
|
||||
var dateTimeNow = new MarkupBlock(
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("DateTime.Now")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
var doWhileString = "@do { var foo = bar; <text>Foo</text> foo++; } while (foo<bar>);";
|
||||
var doWhile = new MarkupBlock(
|
||||
new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("do { var foo = bar;").AsStatement(),
|
||||
new MarkupBlock(
|
||||
factory.Markup(" "),
|
||||
new MarkupTagBlock(
|
||||
factory.MarkupTransition("<text>")),
|
||||
factory.Markup("Foo").Accepts(AcceptedCharacters.None),
|
||||
new MarkupTagBlock(
|
||||
factory.MarkupTransition("</text>")),
|
||||
factory.Markup(" ").Accepts(AcceptedCharacters.None)),
|
||||
factory.Code("foo++; } while (foo<bar>);").AsStatement().Accepts(AcceptedCharacters.None)));
|
||||
|
||||
var currentFormattedString = "<p class=\"{0}\" style='{0}'></p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", new MarkupBlock(dateTimeNow) }
|
||||
}))
|
||||
};
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, doWhileString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(doWhile) },
|
||||
{ "style", new MarkupBlock(doWhile) }
|
||||
}))
|
||||
};
|
||||
|
||||
currentFormattedString = "<p class=\"{0}\" style='{0}'>Hello World</p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", new MarkupBlock(dateTimeNow) }
|
||||
},
|
||||
factory.Markup("Hello World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, doWhileString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(doWhile) },
|
||||
{ "style", new MarkupBlock(doWhile) }
|
||||
},
|
||||
factory.Markup("Hello World")))
|
||||
};
|
||||
|
||||
currentFormattedString = "<p class=\"{0}\">Hello</p> <p style='{0}'>World</p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(dateTimeNow) }
|
||||
},
|
||||
factory.Markup("Hello")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "style", new MarkupBlock(dateTimeNow) }
|
||||
},
|
||||
factory.Markup("World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, doWhileString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(doWhile) }
|
||||
},
|
||||
factory.Markup("Hello")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "style", new MarkupBlock(doWhile) }
|
||||
},
|
||||
factory.Markup("World")))
|
||||
};
|
||||
|
||||
currentFormattedString =
|
||||
"<p class=\"{0}\" style='{0}'>Hello World <strong class=\"{0}\">inside of strong tag</strong></p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", new MarkupBlock(dateTimeNow) }
|
||||
},
|
||||
factory.Markup("Hello World "),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<strong"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "class",
|
||||
prefix: new LocationTagged<string>(" class=\"", 66, 0, 66),
|
||||
suffix: new LocationTagged<string>("\"", 87, 0, 87)),
|
||||
factory.Markup(" class=\"").With(SpanCodeGenerator.Null),
|
||||
new MarkupBlock(new DynamicAttributeBlockCodeGenerator(new LocationTagged<string>(string.Empty, 74, 0, 74), 74, 0, 74),
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("DateTime.Now")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace))),
|
||||
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
factory.Markup(">")),
|
||||
factory.Markup("inside of strong tag"),
|
||||
blockFactory.MarkupTagBlock("</strong>")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ComplexAttributeTagHelperBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlocks(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ComplexTagHelperBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
var dateTimeNowString = "@DateTime.Now";
|
||||
var dateTimeNow = new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("DateTime.Now")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace));
|
||||
var doWhileString = "@do { var foo = bar; <p>Foo</p> foo++; } while (foo<bar>);";
|
||||
var doWhile = new StatementBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("do { var foo = bar;").AsStatement(),
|
||||
new MarkupBlock(
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Foo")),
|
||||
factory.Markup(" ").Accepts(AcceptedCharacters.None)),
|
||||
factory.Code("foo++; } while (foo<bar>);").AsStatement().Accepts(AcceptedCharacters.None));
|
||||
|
||||
var currentFormattedString = "<p>{0}</p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p", dateTimeNow))
|
||||
};
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, doWhileString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p", doWhile))
|
||||
};
|
||||
|
||||
currentFormattedString = "<p>Hello World {0}</p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello World "),
|
||||
dateTimeNow))
|
||||
};
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, doWhileString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello World "),
|
||||
doWhile))
|
||||
};
|
||||
|
||||
currentFormattedString = "<p>{0}</p> <p>{0}</p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p", dateTimeNow),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p", dateTimeNow))
|
||||
};
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, doWhileString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p", doWhile),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p", doWhile))
|
||||
};
|
||||
|
||||
currentFormattedString = "<p>Hello {0}<strong>inside of {0} strong tag</strong></p>";
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, dateTimeNowString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello "),
|
||||
dateTimeNow,
|
||||
blockFactory.MarkupTagBlock("<strong>"),
|
||||
factory.Markup("inside of "),
|
||||
dateTimeNow,
|
||||
factory.Markup(" strong tag"),
|
||||
blockFactory.MarkupTagBlock("</strong>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
string.Format(currentFormattedString, doWhileString),
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello "),
|
||||
doWhile,
|
||||
blockFactory.MarkupTagBlock("<strong>"),
|
||||
factory.Markup("inside of "),
|
||||
doWhile,
|
||||
factory.Markup(" strong tag"),
|
||||
blockFactory.MarkupTagBlock("</strong>")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ComplexTagHelperBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ScriptBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
|
||||
yield return new object[] {
|
||||
"<script><script></foo></script>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("script",
|
||||
factory.Markup("<script></foo>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<script>Hello World <div></div></script>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("script",
|
||||
factory.Markup("Hello World <div></div>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<script>Hel<p>lo</p></script> <p><div>World</div></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("script",
|
||||
factory.Markup("Hel<p>lo</p>")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new MarkupTagHelperBlock("div",
|
||||
factory.Markup("World"))))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<script>Hel<strong>lo</strong></script> <script><span>World</span></script>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("script",
|
||||
factory.Markup("Hel<strong>lo</strong>")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("script",
|
||||
factory.Markup("<span>World</span>")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<script class=\"foo\" style=\"color:red;\" />",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("script",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
}))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hello <script class=\"foo\" style=\"color:red;\"></script> World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello "),
|
||||
new MarkupTagHelperBlock("script",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
}),
|
||||
factory.Markup(" World")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ScriptBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesScriptTagHelpers(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div", "script");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SelfClosingBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
|
||||
yield return new object[] {
|
||||
"<p class=\"foo\" style=\"color:red;\" />",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
}))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hello <p class=\"foo\" style=\"color:red;\" /> World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
}),
|
||||
factory.Markup(" World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"Hello<p class=\"foo\" /> <p style=\"color:red;\" />World",
|
||||
new MarkupBlock(
|
||||
factory.Markup("Hello"),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) }
|
||||
}),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
}),
|
||||
factory.Markup("World"))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SelfClosingBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesSelfClosingTagHelpers(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> QuotelessAttributeBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
var dateTimeNow = new MarkupBlock(
|
||||
new ExpressionBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code("DateTime.Now")
|
||||
.AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
|
||||
.Accepts(AcceptedCharacters.NonWhiteSpace)));
|
||||
|
||||
yield return new object[] {
|
||||
"<p class=foo dynamic=@DateTime.Now style=color:red;></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "dynamic", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
}))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=foo dynamic=@DateTime.Now style=color:red;>Hello World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "dynamic", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
},
|
||||
factory.Markup("Hello World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=foo dynamic=@DateTime.Now>Hello</p> <p style=color:red; dynamic=@DateTime.Now>World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "dynamic", new MarkupBlock(dateTimeNow) }
|
||||
},
|
||||
factory.Markup("Hello")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) },
|
||||
{ "dynamic", new MarkupBlock(dateTimeNow) }
|
||||
},
|
||||
factory.Markup("World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=foo dynamic=@DateTime.Now style=color:red;>Hello World <strong class=\"foo\">inside of strong tag</strong></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "dynamic", new MarkupBlock(dateTimeNow) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
},
|
||||
factory.Markup("Hello World "),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<strong"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "class",
|
||||
prefix: new LocationTagged<string>(" class=\"", 71, 0, 71),
|
||||
suffix: new LocationTagged<string>("\"", 82, 0, 82)),
|
||||
factory.Markup(" class=\"").With(SpanCodeGenerator.Null),
|
||||
factory.Markup("foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(string.Empty, 79, 0, 79),
|
||||
value: new LocationTagged<string>("foo", 79, 0, 79))),
|
||||
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
factory.Markup(">")),
|
||||
factory.Markup("inside of strong tag"),
|
||||
blockFactory.MarkupTagBlock("</strong>")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(QuotelessAttributeBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesTagHelpersWithQuotelessAttributes(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> PlainAttributeBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
yield return new object[] {
|
||||
"<p class=\"foo\" style=\"color:red;\"></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
}))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=\"foo\" style=\"color:red;\">Hello World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
},
|
||||
factory.Markup("Hello World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=\"foo\">Hello</p> <p style=\"color:red;\">World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) }
|
||||
},
|
||||
factory.Markup("Hello")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
},
|
||||
factory.Markup("World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p class=\"foo\" style=\"color:red;\">Hello World <strong class=\"foo\">inside of strong tag</strong></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new Dictionary<string, SyntaxTreeNode>
|
||||
{
|
||||
{ "class", new MarkupBlock(factory.Markup("foo")) },
|
||||
{ "style", new MarkupBlock(factory.Markup("color:red;")) }
|
||||
},
|
||||
factory.Markup("Hello World "),
|
||||
new MarkupTagBlock(
|
||||
factory.Markup("<strong"),
|
||||
new MarkupBlock(new AttributeBlockCodeGenerator(name: "class",
|
||||
prefix: new LocationTagged<string>(" class=\"", 53, 0, 53),
|
||||
suffix: new LocationTagged<string>("\"", 64, 0, 64)),
|
||||
factory.Markup(" class=\"").With(SpanCodeGenerator.Null),
|
||||
factory.Markup("foo").With(new LiteralAttributeCodeGenerator(prefix: new LocationTagged<string>(string.Empty, 61, 0, 61),
|
||||
value: new LocationTagged<string>("foo", 61, 0, 61))),
|
||||
factory.Markup("\"").With(SpanCodeGenerator.Null)),
|
||||
factory.Markup(">")),
|
||||
factory.Markup("inside of strong tag"),
|
||||
blockFactory.MarkupTagBlock("</strong>")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(PlainAttributeBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesTagHelpersWithPlainAttributes(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> PlainBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
yield return new object[] {
|
||||
"<p></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p"))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hello World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hello</p> <p>World</p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("World")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hello World <strong>inside of strong tag</strong></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello World "),
|
||||
blockFactory.MarkupTagBlock("<strong>"),
|
||||
factory.Markup("inside of strong tag"),
|
||||
blockFactory.MarkupTagBlock("</strong>")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(PlainBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesPlainTagHelperTagBlocks(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p");
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> NestedBlockData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = CreateDefaultSpanFactory();
|
||||
var blockFactory = new BlockFactory(factory);
|
||||
|
||||
yield return new object[] {
|
||||
"<p><div></div></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
new MarkupTagHelperBlock("div")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hello World <div></div></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hello World "),
|
||||
new MarkupTagHelperBlock("div")))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hel<p>lo</p></p> <p><div>World</div></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hel"),
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("lo"))),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
new MarkupTagHelperBlock("div",
|
||||
factory.Markup("World"))))
|
||||
};
|
||||
yield return new object[] {
|
||||
"<p>Hel<strong>lo</strong></p> <p><span>World</span></p>",
|
||||
new MarkupBlock(
|
||||
new MarkupTagHelperBlock("p",
|
||||
factory.Markup("Hel"),
|
||||
blockFactory.MarkupTagBlock("<strong>"),
|
||||
factory.Markup("lo"),
|
||||
blockFactory.MarkupTagBlock("</strong>")),
|
||||
factory.Markup(" "),
|
||||
new MarkupTagHelperBlock("p",
|
||||
blockFactory.MarkupTagBlock("<span>"),
|
||||
factory.Markup("World"),
|
||||
blockFactory.MarkupTagBlock("</span>")))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(NestedBlockData))]
|
||||
public void TagHelperParseTreeRewriter_RewritesNestedTagHelperTagBlocks(
|
||||
string documentContent,
|
||||
MarkupBlock expectedOutput)
|
||||
{
|
||||
RunParseTreeRewriterTest(documentContent, expectedOutput, "p", "div");
|
||||
}
|
||||
|
||||
private void RunParseTreeRewriterTest(string documentContent,
|
||||
MarkupBlock expectedOutput,
|
||||
params string[] tagNames)
|
||||
{
|
||||
// Arrange
|
||||
var providerContext = BuildProviderContext(tagNames);
|
||||
|
||||
// Act & Assert
|
||||
EvaluateData(providerContext, documentContent, expectedOutput);
|
||||
}
|
||||
|
||||
private TagHelperDescriptorProvider BuildProviderContext(params string[] tagNames)
|
||||
{
|
||||
var descriptors = new List<TagHelperDescriptor>();
|
||||
|
||||
foreach (var tagName in tagNames)
|
||||
{
|
||||
descriptors.Add(
|
||||
new TagHelperDescriptor(tagName, tagName + "taghelper", ContentBehavior.None));
|
||||
}
|
||||
|
||||
return new TagHelperDescriptorProvider(descriptors);
|
||||
}
|
||||
|
||||
private void EvaluateData(TagHelperDescriptorProvider provider, string documentContent, MarkupBlock expectedOutput)
|
||||
{
|
||||
var results = ParseDocument(documentContent);
|
||||
var rewritten = new TagHelperParseTreeRewriter(provider).Rewrite(results.Document);
|
||||
|
||||
Assert.Empty(results.ParserErrors);
|
||||
EvaluateParseTree(rewritten, expectedOutput);
|
||||
}
|
||||
|
||||
private static SpanFactory CreateDefaultSpanFactory()
|
||||
{
|
||||
return new SpanFactory
|
||||
{
|
||||
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
|
||||
CodeTokenizerFactory = doc => new CSharpTokenizer(doc)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue