From eb1eca9e1a8cfb6a2db4849040b1ac9a7f92471b Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Wed, 17 Dec 2014 16:33:07 -0800 Subject: [PATCH] Modify TagHelper tests to abide by new content mode design. - React to aspnet/Razor#221 - Modified existing TagHelper tests to no longer rely on ContentBehavior. - Updated signatures of TagHelperExecutionContext and TagHelperContext pieces. --- .../Runtime/ModelExpressionTagHelper.cs | 36 ++++- .../AnchorTagHelperTest.cs | 35 ++-- .../FormTagHelperTest.cs | 76 +++++---- .../InputTagHelperTest.cs | 112 ++++++++++--- .../LabelTagHelperTest.cs | 153 +++++++++++++++--- .../OptionTagHelperTest.cs | 32 +++- .../SelectTagHelperTest.cs | 82 +++++++--- .../TagHelperOutputExtensionsTest.cs | 46 +++--- .../TextAreaTagHelperTest.cs | 20 ++- .../ValidationMessageTagHelperTest.cs | 127 ++++++++++++--- .../ValidationSummaryTagHelperTest.cs | 77 +++++++-- .../TagHelpers/HiddenTagHelper.cs | 2 +- .../TagHelpers/RepeatContentTagHelper.cs | 2 +- .../RequestScopedTagHelper.cs | 1 - .../TagHelpers/ATagHelper.cs | 3 +- .../TagHelpers/AutoLinkerTagHelper.cs | 8 +- .../TagHelpers/ConditionTagHelper.cs | 4 +- .../TagHelpers/NestedViewStartTagHelper.cs | 1 - .../TagHelpers/PrettyTagHelper.cs | 5 +- .../TagHelpers/RootViewStartTagHelper.cs | 1 - .../TagCloudViewComponentTagHelper.cs | 1 - .../TagHelpers/WebsiteInformationTagHelper.cs | 4 +- 22 files changed, 627 insertions(+), 201 deletions(-) diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs index c0bfc2df2f..7aadb85538 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs @@ -45,7 +45,9 @@ namespace Asp BeginContext(120, 2, true); WriteLiteral("\r\n"); EndContext(); - __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", "test"); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", "test", async() => { + } + , StartWritingScope, EndWritingScope); __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = CreateTagHelper(); __tagHelperExecutionContext.Add(__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper); #line 5 "TestFiles/Input/ModelExpressionTagHelper.cshtml" @@ -56,12 +58,28 @@ __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__mo __tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For); __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(); BeginContext(146, 2, true); WriteLiteral("\r\n"); EndContext(); - __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", "test"); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", "test", async() => { + } + , StartWritingScope, EndWritingScope); __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = CreateTagHelper(); __tagHelperExecutionContext.Add(__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper); #line 6 "TestFiles/Input/ModelExpressionTagHelper.cshtml" @@ -72,6 +90,20 @@ __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__mo __tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For); __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(); } diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs index 56427a00b7..e38d39037d 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs @@ -32,15 +32,18 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "asp-host", "contoso.com" }, { "asp-protocol", "http" } }, - uniqueId: "test"); + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something Else")); var output = new TagHelperOutput( expectedTagName, attributes: new Dictionary { { "id", "myanchor" }, { "asp-route-foo", "bar" }, - }, - content: "Something"); + }) + { + Content = "Something" + }; var urlHelper = new Mock(); urlHelper @@ -85,11 +88,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { // Arrange var context = new TagHelperContext( - allAttributes: new Dictionary(), uniqueId: "test"); + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var output = new TagHelperOutput( "a", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()) + { + Content = string.Empty + }; var generator = new Mock(MockBehavior.Strict); generator @@ -119,11 +126,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { // Arrange var context = new TagHelperContext( - allAttributes: new Dictionary(), uniqueId: "test"); + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var output = new TagHelperOutput( "a", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()) + { + Content = string.Empty + }; var generator = new Mock(); generator @@ -166,8 +177,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers attributes: new Dictionary() { { "href", "http://www.contoso.com" } - }, - content: string.Empty); + }); if (propertyName == "asp-route-") { output.Attributes.Add("asp-route-foo", "bar"); @@ -202,8 +212,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers typeof(AnchorTagHelper).GetProperty(propertyName).SetValue(anchorTagHelper, "Home"); var output = new TagHelperOutput( "a", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var expectedErrorMessage = "Cannot determine an 'href' attribute for . An with a specified " + "'asp-route' must not have an 'asp-action' or 'asp-controller' attribute."; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs index 8494fb6bd3..7fc7153888 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs @@ -33,15 +33,18 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "method", "post" }, { "asp-anti-forgery", true } }, - uniqueId: "test"); + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something Else")); var output = new TagHelperOutput( expectedTagName, attributes: new Dictionary { { "id", "myform" }, { "asp-route-foo", "bar" }, - }, - content: "Something"); + }) + { + PostContent = "Something" + }; var urlHelper = new Mock(); urlHelper .Setup(mock => mock.Action(It.IsAny(), @@ -56,8 +59,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var viewContext = TestableHtmlGenerator.GetViewContext(model: null, htmlGenerator: htmlGenerator, metadataProvider: metadataProvider); - var expectedContent = "Something" + htmlGenerator.GenerateAntiForgery(viewContext) - .ToString(TagRenderMode.SelfClosing); + var expectedPostContent = "Something" + htmlGenerator.GenerateAntiForgery(viewContext) + .ToString(TagRenderMode.SelfClosing); var formTagHelper = new FormTagHelper { Action = "index", @@ -79,7 +82,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal("post", attribute.Value); attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("action")); Assert.Equal("home/index", attribute.Value); - Assert.Equal(expectedContent, output.Content); + Assert.Empty(output.PreContent); + Assert.Empty(output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.Equal(expectedTagName, output.TagName); } @@ -87,16 +92,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers [InlineData(true, "")] [InlineData(false, "")] [InlineData(null, "")] - public async Task ProcessAsync_GeneratesAntiForgeryCorrectly(bool? antiForgery, string expectedContent) + public async Task ProcessAsync_GeneratesAntiForgeryCorrectly(bool? antiForgery, string expectedPostContent) { // Arrange var viewContext = CreateViewContext(); var context = new TagHelperContext( - allAttributes: new Dictionary(), uniqueId: "test"); + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var output = new TagHelperOutput( "form", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var generator = new Mock(MockBehavior.Strict); generator .Setup(mock => mock.GenerateForm( @@ -124,7 +130,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal("form", output.TagName); Assert.Empty(output.Attributes); - Assert.Equal(expectedContent, output.Content); + Assert.Empty(output.PreContent); + Assert.Empty(output.Content); + Assert.Equal(expectedPostContent, output.PostContent); } [Fact] @@ -133,7 +141,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var testViewContext = CreateViewContext(); var context = new TagHelperContext( - allAttributes: new Dictionary(), uniqueId: "test"); + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var expectedAttribute = new KeyValuePair("asp-ROUTEE-NotRoute", "something"); var output = new TagHelperOutput( "form", @@ -141,8 +151,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "asp-route-val", "hello" }, { "asp-roUte--Foo", "bar" } - }, - content: string.Empty); + }); output.Attributes.Add(expectedAttribute); var generator = new Mock(MockBehavior.Strict); @@ -184,7 +193,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal("form", output.TagName); var attribute = Assert.Single(output.Attributes); Assert.Equal(expectedAttribute, attribute); + Assert.Empty(output.PreContent); Assert.Empty(output.Content); + Assert.Empty(output.PostContent); generator.Verify(); } @@ -194,11 +205,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var viewContext = CreateViewContext(); var context = new TagHelperContext( - allAttributes: new Dictionary(), uniqueId: "test"); + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var output = new TagHelperOutput( "form", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var generator = new Mock(MockBehavior.Strict); generator .Setup(mock => mock.GenerateForm(viewContext, "Index", "Home", null, "POST", null)) @@ -220,7 +232,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal("form", output.TagName); Assert.Empty(output.Attributes); + Assert.Empty(output.PreContent); Assert.Empty(output.Content); + Assert.Empty(output.PostContent); } [Theory] @@ -238,14 +252,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers attributes: new Dictionary { { "aCTiON", htmlAction }, - }, - content: string.Empty); + }); + var context = new TagHelperContext( allAttributes: new Dictionary() { { "METhod", "POST" } }, - uniqueId: "test"); + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); // Act await formTagHelper.ProcessAsync(context, output); @@ -257,7 +272,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal(htmlAction, attribute.Value); attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("METhod")); Assert.Equal("POST", attribute.Value); + Assert.Empty(output.PreContent); Assert.Empty(output.Content); + Assert.Empty(output.PostContent); } [Theory] @@ -266,11 +283,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers [InlineData(null, "")] public async Task ProcessAsync_SupportsAntiForgeryIfActionIsSpecified( bool? antiForgery, - string expectedContent) + string expectedPostContent) { // Arrange var viewContext = CreateViewContext(); var generator = new Mock(); + generator.Setup(mock => mock.GenerateAntiForgery(It.IsAny())) .Returns(new TagBuilder("input")); var formTagHelper = new FormTagHelper @@ -284,9 +302,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers attributes: new Dictionary { { "aCTiON", "my-action" }, - }, - content: string.Empty); - var context = new TagHelperContext(allAttributes: new Dictionary(), uniqueId: "test"); + }); + var context = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + // Act await formTagHelper.ProcessAsync(context, output); @@ -295,7 +316,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal("form", output.TagName); var attribute = Assert.Single(output.Attributes); Assert.Equal(new KeyValuePair("aCTiON", "my-action"), attribute); - Assert.Equal(expectedContent, output.Content); + Assert.Empty(output.PreContent); + Assert.Empty(output.Content); + Assert.Equal(expectedPostContent, output.PostContent); } [Theory] @@ -314,8 +337,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers attributes: new Dictionary { { "action", "my-action" }, - }, - content: string.Empty); + }); if (propertyName == "asp-route-") { tagHelperOutput.Attributes.Add("asp-route-foo", "bar"); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs index ac62d6a1e7..adf43c2d35 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/InputTagHelperTest.cs @@ -89,16 +89,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "valid", "from validation attributes" }, { "value", expectedValue }, }; + var expectedPreContent = "original pre-content"; var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "not-input"; - var context = new TagHelperContext(new Dictionary(), uniqueId: "test"); + var context = new TagHelperContext(allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var originalAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(expectedTagName, originalAttributes, expectedContent) + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = false, }; @@ -124,7 +131,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.True(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -133,17 +142,24 @@ namespace Microsoft.AspNet.Mvc.TagHelpers public async Task ProcessAsync_CallsGenerateCheckBox_WithExpectedParameters() { // Arrange - var originalContent = "something"; + var originalContent = "original content"; var originalTagName = "not-input"; + var expectedPreContent = "original pre-content"; var expectedContent = originalContent + ""; + var expectedPostContent = "original post-content"; - var context = new TagHelperContext(allAttributes: new Dictionary(), uniqueId: "test"); + var context = new TagHelperContext(allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var originalAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(originalTagName, originalAttributes, content: originalContent) + var output = new TagHelperOutput(originalTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = originalContent, + PostContent = expectedPostContent, SelfClosing = true, }; @@ -180,9 +196,11 @@ namespace Microsoft.AspNet.Mvc.TagHelpers htmlGenerator.Verify(); Assert.Empty(output.Attributes); // Moved to Content and cleared + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.False(output.SelfClosing); - Assert.Empty(output.TagName); // Cleared + Assert.Null(output.TagName); // Cleared } [Theory] @@ -214,16 +232,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "class", "form-control hidden-control" }, { "type", inputTypeName ?? "hidden" }, // Generator restores type attribute; adds "hidden" if none. }; - var expectedContent = "something"; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "not-input"; - var context = new TagHelperContext(allAttributes: contextAttributes, uniqueId: "test"); + var context = new TagHelperContext(allAttributes: contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var originalAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent) + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = false, }; @@ -257,7 +282,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers htmlGenerator.Verify(); Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.True(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -291,16 +318,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "class", "form-control password-control" }, { "type", inputTypeName ?? "password" }, // Generator restores type attribute; adds "password" if none. }; - var expectedContent = "something"; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "not-input"; - var context = new TagHelperContext(allAttributes: contextAttributes, uniqueId: "test"); + var context = new TagHelperContext(allAttributes: contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var originalAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent) + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = false, }; @@ -333,7 +367,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers htmlGenerator.Verify(); Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.True(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -365,16 +401,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "type", inputTypeName ?? "radio" }, // Generator restores type attribute; adds "radio" if none. { "value", value }, }; - var expectedContent = "something"; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "not-input"; - var context = new TagHelperContext(allAttributes: contextAttributes, uniqueId: "test"); + var context = new TagHelperContext(allAttributes: contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var originalAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent) + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = false, }; @@ -408,7 +451,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers htmlGenerator.Verify(); Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.True(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -454,16 +499,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "class", "form-control text-control" }, { "type", inputTypeName ?? "text" }, // Generator restores type attribute; adds "text" if none. }; - var expectedContent = "something"; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "not-input"; - var context = new TagHelperContext(allAttributes: contextAttributes, uniqueId: "test"); + var context = new TagHelperContext(allAttributes: contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var originalAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent) + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = false, }; @@ -497,7 +549,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers htmlGenerator.Verify(); Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.True(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -512,12 +566,20 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "type", "datetime" }, { "value", "2014-10-15T23:24:19.000-7:00" }, }; + var expectedPreContent = "original pre-content"; var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "input"; - var tagHelperContext = new TagHelperContext(new Dictionary(), uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, expectedAttributes, expectedContent) + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, expectedAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = false, }; @@ -536,7 +598,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.False(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -558,13 +622,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var contextAttributes = new Dictionary(); var originalAttributes = new Dictionary(); - var content = "original content"; var expectedTagName = "select"; var expectedMessage = "Unable to format without a 'asp-for' expression for . 'asp-format' must " + "be null if 'asp-for' is null."; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, originalAttributes, content); + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, originalAttributes); var tagHelper = new InputTagHelper { Format = "{0}", diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs index ebce192391..b3b0accf7f 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/LabelTagHelperTest.cs @@ -44,45 +44,111 @@ namespace Microsoft.AspNet.Mvc.TagHelpers return new TheoryData, string, TagHelperOutputContent> { { null, typeof(Model), () => null, "Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "Text") }, + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "Text") }, + { null, typeof(Model), () => null, "Text", + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "Text") }, { modelWithNull, typeof(Model), () => modelWithNull.Text, "Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "Text") }, + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "Text") }, + { modelWithNull, typeof(Model), () => modelWithNull.Text, "Text", + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "Text") }, + { modelWithNull, typeof(Model), () => modelWithNull.Text, "Text", + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "Text") }, { modelWithText, typeof(Model), () => modelWithText.Text, "Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "Text") }, + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "Text") }, + { modelWithText, typeof(Model), () => modelWithText.Text, "Text", + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "Text") }, + { modelWithText, typeof(Model), () => modelWithText.Text, "Text", + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "Text") }, { modelWithText, typeof(Model), () => modelWithNull.Text, "Text", - new TagHelperOutputContent("Hello World", "Hello World", "Text") }, + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "Text") }, { modelWithText, typeof(Model), () => modelWithText.Text, "Text", - new TagHelperOutputContent("Hello World", "Hello World", "Text") }, + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "Text") }, + { modelWithText, typeof(Model), () => modelWithNull.Text, "Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "Text") }, + { modelWithText, typeof(Model), () => modelWithText.Text, "Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "Text") }, + { modelWithText, typeof(Model), () => modelWithNull.Text, "Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "Text") }, + { modelWithText, typeof(Model), () => modelWithText.Text, "Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "Text") }, { modelWithNull, typeof(NestedModel), () => modelWithNull.NestedModel.Text, "NestedModel.Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "NestedModel_Text") }, - { modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "NestedModel_Text") }, + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "NestedModel_Text") }, { modelWithNull, typeof(NestedModel), () => modelWithNull.NestedModel.Text, "NestedModel.Text", - new TagHelperOutputContent("Hello World", "Hello World", "NestedModel_Text") }, + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "NestedModel_Text") }, + { modelWithNull, typeof(NestedModel), () => modelWithNull.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "NestedModel_Text") }, { modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text", - new TagHelperOutputContent("Hello World", "Hello World", "NestedModel_Text") }, + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "NestedModel_Text") }, + { modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "NestedModel_Text") }, + { modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "NestedModel_Text") }, + { modelWithNull, typeof(NestedModel), () => modelWithNull.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "NestedModel_Text") }, + { modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "NestedModel_Text") }, + { modelWithNull, typeof(NestedModel), () => modelWithNull.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "NestedModel_Text") }, + { modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "NestedModel_Text") }, + { modelWithNull, typeof(NestedModel), () => modelWithNull.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "NestedModel_Text") }, + { modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "NestedModel_Text") }, // Note: Tests cases below here will not work in practice due to current limitations on indexing // into ModelExpressions. Will be fixed in https://github.com/aspnet/Mvc/issues/1345. { models, typeof(Model), () => models[0].Text, "[0].Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "z0__Text") }, - { models, typeof(Model), () => models[1].Text, "[1].Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "z1__Text") }, + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "z0__Text") }, { models, typeof(Model), () => models[0].Text, "[0].Text", - new TagHelperOutputContent("Hello World", "Hello World", "z0__Text") }, + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "z0__Text") }, + { models, typeof(Model), () => models[0].Text, "[0].Text", + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "z0__Text") }, { models, typeof(Model), () => models[1].Text, "[1].Text", - new TagHelperOutputContent("Hello World", "Hello World", "z1__Text") }, + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "z1__Text") }, + { models, typeof(Model), () => models[1].Text, "[1].Text", + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "z1__Text") }, + { models, typeof(Model), () => models[1].Text, "[1].Text", + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "z1__Text") }, + { models, typeof(Model), () => models[0].Text, "[0].Text", + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "z0__Text") }, + { models, typeof(Model), () => models[1].Text, "[1].Text", + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "z1__Text") }, + { models, typeof(Model), () => models[0].Text, "[0].Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "z0__Text") }, + { models, typeof(Model), () => models[1].Text, "[1].Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "z1__Text") }, + { models, typeof(Model), () => models[0].Text, "[0].Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "z0__Text") }, + { models, typeof(Model), () => models[1].Text, "[1].Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "z1__Text") }, { models, typeof(NestedModel), () => models[0].NestedModel.Text, "[0].NestedModel.Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "z0__NestedModel_Text") }, - { models, typeof(NestedModel), () => models[1].NestedModel.Text, "[1].NestedModel.Text", - new TagHelperOutputContent(Environment.NewLine, "Text", "z1__NestedModel_Text") }, + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "z0__NestedModel_Text") }, { models, typeof(NestedModel), () => models[0].NestedModel.Text, "[0].NestedModel.Text", - new TagHelperOutputContent("Hello World", "Hello World", "z0__NestedModel_Text") }, + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "z0__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[0].NestedModel.Text, "[0].NestedModel.Text", + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "z0__NestedModel_Text") }, { models, typeof(NestedModel), () => models[1].NestedModel.Text, "[1].NestedModel.Text", - new TagHelperOutputContent("Hello World", "Hello World", "z1__NestedModel_Text") }, + new TagHelperOutputContent(Environment.NewLine, string.Empty, "Text", "z1__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[1].NestedModel.Text, "[1].NestedModel.Text", + new TagHelperOutputContent(Environment.NewLine, "Hello World", "Hello World", "z1__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[1].NestedModel.Text, "[1].NestedModel.Text", + new TagHelperOutputContent(string.Empty, Environment.NewLine, Environment.NewLine, "z1__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[0].NestedModel.Text, "[0].NestedModel.Text", + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "z0__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[1].NestedModel.Text, "[1].NestedModel.Text", + new TagHelperOutputContent(string.Empty, "Hello World", "Hello World", "z1__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[0].NestedModel.Text, "[0].NestedModel.Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "z0__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[1].NestedModel.Text, "[1].NestedModel.Text", + new TagHelperOutputContent("Hello World", string.Empty, "Hello World", "z1__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[0].NestedModel.Text, "[0].NestedModel.Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "z0__NestedModel_Text") }, + { models, typeof(NestedModel), () => models[1].NestedModel.Text, "[1].NestedModel.Text", + new TagHelperOutputContent("Hello World1", "Hello World2", "Hello World2", "z1__NestedModel_Text") }, }; } } @@ -112,13 +178,30 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { For = modelExpression, }; + var expectedPreContent = "original pre-content"; + var expectedPostContent = "original post-content"; - var tagHelperContext = new TagHelperContext(allAttributes: new Dictionary(), uniqueId: "test"); + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult(tagHelperOutputContent.OriginalChildContent)); var htmlAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(expectedTagName, htmlAttributes, tagHelperOutputContent.OriginalContent); + var output = new TagHelperOutput(expectedTagName, htmlAttributes) + { + PreContent = expectedPreContent, + PostContent = expectedPostContent, + }; + + // LabelTagHelper checks ContentSet so we don't want to forcibly set it if + // tagHelperOutputContent.OriginalContent is going to be null or empty. + if (!string.IsNullOrEmpty(tagHelperOutputContent.OriginalContent)) + { + output.Content = tagHelperOutputContent.OriginalContent; + } + var htmlGenerator = new TestableHtmlGenerator(metadataProvider); var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); tagHelper.ViewContext = viewContext; @@ -129,7 +212,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(tagHelperOutputContent.ExpectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.False(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -142,7 +227,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "class", "form-control" }, }; + var expectedPreContent = "original pre-content"; var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "label"; var metadataProvider = new DataAnnotationsModelMetadataProvider(); @@ -153,8 +240,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var modelExpression = new ModelExpression(nameof(Model.Text), metadata); var tagHelper = new LabelTagHelper(); - var tagHelperContext = new TagHelperContext(allAttributes: new Dictionary(), uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, expectedAttributes, expectedContent); + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, expectedAttributes) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, + }; var htmlGenerator = new TestableHtmlGenerator(metadataProvider); Model model = null; @@ -167,19 +262,27 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.Equal(expectedTagName, output.TagName); } public class TagHelperOutputContent { - public TagHelperOutputContent(string outputContent, string expectedContent, string expectedId) + public TagHelperOutputContent(string originalChildContent, + string outputContent, + string expectedContent, + string expectedId) { + OriginalChildContent = originalChildContent; OriginalContent = outputContent; ExpectedContent = expectedContent; ExpectedId = expectedId; } + public string OriginalChildContent { get; set; } + public string OriginalContent { get; set; } public string ExpectedContent { get; set; } diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs index 24ceea9704..d5089f4024 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/OptionTagHelperTest.cs @@ -136,9 +136,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "selected", selected }, { "value", value }, }; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, originalAttributes, originalContent) + var tagHelperContext = new TagHelperContext( + contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult(originalContent)); + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + Content = originalContent, SelfClosing = false, }; @@ -188,9 +192,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "selected", selected }, { "value", value }, }; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(originalTagName, originalAttributes, originalContent) + var originalPreContent = "original pre-content"; + var originalPostContent = "original post-content"; + var tagHelperContext = new TagHelperContext( + contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult(originalContent)); + var output = new TagHelperOutput(originalTagName, originalAttributes) { + PreContent = originalPreContent, + Content = originalContent, + PostContent = originalPostContent, SelfClosing = false, }; @@ -235,9 +247,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "selected", selected }, { "value", value }, }; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(originalTagName, originalAttributes, originalContent) + var originalPreContent = "original pre-content"; + var originalPostContent = "original post-content"; + var tagHelperContext = new TagHelperContext( + contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult(originalContent)); + var output = new TagHelperOutput(originalTagName, originalAttributes) { + PreContent = originalPreContent, + Content = originalContent, + PostContent = originalPostContent, SelfClosing = false, }; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs index 07b90efa4e..ff8036dbd0 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs @@ -165,7 +165,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "class", "form-control" }, }; - var originalContent = "original content"; + var originalPostContent = "original content"; var expectedAttributes = new Dictionary(originalAttributes) { @@ -173,7 +173,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "name", nameAndId.Name }, { "valid", "from validation attributes" }, }; - var expectedContent = originalContent; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = originalPostContent; var expectedTagName = "not-select"; var metadataProvider = new DataAnnotationsModelMetadataProvider(); @@ -182,9 +184,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var metadata = metadataProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName: "Text"); var modelExpression = new ModelExpression(nameAndId.Name, metadata); - var tagHelperContext = new TagHelperContext(new Dictionary(), uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, originalAttributes, expectedContent) + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = originalPostContent, SelfClosing = true, }; @@ -208,7 +216,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.False(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); @@ -235,7 +245,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "class", "form-control" }, }; - var originalContent = "original content"; + var originalPostContent = "original content"; var expectedAttributes = new Dictionary(originalAttributes) { @@ -243,7 +253,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "name", nameAndId.Name }, { "valid", "from validation attributes" }, }; - var expectedContent = originalContent + expectedOptions; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = originalPostContent + expectedOptions; var expectedTagName = "select"; var metadataProvider = new DataAnnotationsModelMetadataProvider(); @@ -252,9 +264,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var metadata = metadataProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName: "Text"); var modelExpression = new ModelExpression(nameAndId.Name, metadata); - var tagHelperContext = new TagHelperContext(new Dictionary(), uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, originalAttributes, originalContent) + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = originalPostContent, SelfClosing = true, }; @@ -280,7 +298,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.False(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); @@ -308,12 +328,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { "multiple", multiple }, }; var originalAttributes = new Dictionary(); - var content = "original content"; var propertyName = "Property1"; var expectedTagName = "select"; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, originalAttributes, content); + var tagHelperContext = new TagHelperContext( + contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, originalAttributes); var metadataProvider = new EmptyModelMetadataProvider(); string model = null; @@ -372,12 +394,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var contextAttributes = new Dictionary(); var originalAttributes = new Dictionary(); - var content = "original content"; var propertyName = "Property1"; var tagName = "select"; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(tagName, originalAttributes, content); + var tagHelperContext = new TagHelperContext( + contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(tagName, originalAttributes); var metadataProvider = new EmptyModelMetadataProvider(); var metadata = metadataProvider.GetMetadataForType(() => model, modelType); @@ -437,12 +461,20 @@ namespace Microsoft.AspNet.Mvc.TagHelpers }; var expectedAttributes = new Dictionary(originalAttributes); expectedAttributes[attributeName] = (string)contextAttributes[attributeName]; + var expectedPreContent = "original pre-content"; var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "select"; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, originalAttributes, expectedContent) + var tagHelperContext = new TagHelperContext( + contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, originalAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = true, }; @@ -456,7 +488,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal(expectedAttributes, output.Attributes); + Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.True(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); } @@ -467,12 +501,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var contextAttributes = new Dictionary(); var originalAttributes = new Dictionary(); - var content = "original content"; var expectedTagName = "select"; var expectedMessage = "Cannot determine body for . Acceptable values are 'false', 'true' and 'multiple'."; - var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, originalAttributes, content); + var tagHelperContext = new TagHelperContext( + contextAttributes, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, originalAttributes); var metadataProvider = new EmptyModelMetadataProvider(); string model = null; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs index ba0a980c95..cc7ad9fa4b 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TagHelperOutputExtensionsTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Xunit; @@ -19,14 +20,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var tagHelperContext = new TagHelperContext( - new Dictionary(StringComparer.Ordinal) + allAttributes: new Dictionary(StringComparer.Ordinal) { { attributeName, attributeValue } }, - uniqueId: "test"); + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var expectedAttribute = new KeyValuePair(attributeName, attributeValue); // Act @@ -47,15 +48,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers attributes: new Dictionary() { { attributeName, "world2" } - }, - content: string.Empty); + }); var expectedAttribute = new KeyValuePair(attributeName, "world2"); var tagHelperContext = new TagHelperContext( - new Dictionary(StringComparer.Ordinal) + allAttributes: new Dictionary(StringComparer.Ordinal) { { attributeName, "world" } - } - , uniqueId: "test"); + }, + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); // Act tagHelperOutput.CopyHtmlAttribute(attributeName, tagHelperContext); @@ -75,8 +76,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "route-Hello", "World" }, { "Route-I", "Am" } - }, - content: string.Empty); + }); var expectedAttribute = new KeyValuePair("type", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); var attributes = tagHelperOutput.FindPrefixedAttributes("route-"); @@ -99,8 +99,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "routeHello", "World" }, { "Routee-I", "Am" } - }, - content: string.Empty); + }); // Act var attributes = tagHelperOutput.FindPrefixedAttributes("route-"); @@ -119,8 +118,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var expectedAttribute = new KeyValuePair("type", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); @@ -141,8 +139,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); tagHelperOutput.Attributes.Add("class", "Hello"); var tagBuilder = new TagBuilder("p"); @@ -168,8 +165,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); tagHelperOutput.Attributes.Add(originalName, "Hello"); var tagBuilder = new TagBuilder("p"); @@ -189,8 +185,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var tagBuilder = new TagBuilder("p"); var expectedAttribute = new KeyValuePair("visible", "val < 3"); @@ -210,8 +205,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var tagBuilder = new TagBuilder("p"); var expectedAttribute1 = new KeyValuePair("class", "btn"); @@ -236,8 +230,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var expectedAttribute = new KeyValuePair("class", "btn"); tagHelperOutput.Attributes.Add(expectedAttribute); @@ -257,8 +250,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Arrange var tagHelperOutput = new TagHelperOutput( "p", - attributes: new Dictionary(), - content: string.Empty); + attributes: new Dictionary()); var expectedOutputAttribute = new KeyValuePair("class", "btn"); tagHelperOutput.Attributes.Add(expectedOutputAttribute); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs index 1b098e9e04..5d3ae03516 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/TextAreaTagHelperTest.cs @@ -107,13 +107,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers For = modelExpression, }; - var tagHelperContext = new TagHelperContext(new Dictionary(), uniqueId: "test"); + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var htmlAttributes = new Dictionary { { "class", "form-control" }, }; - var output = new TagHelperOutput(expectedTagName, htmlAttributes, "original content") + var output = new TagHelperOutput(expectedTagName, htmlAttributes) { + Content = "original content", SelfClosing = true, }; @@ -146,7 +150,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { { "class", "form-control" }, }; + var expectedPreContent = "original pre-content"; var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var expectedTagName = "textarea"; var metadataProvider = new DataAnnotationsModelMetadataProvider(); @@ -157,9 +163,15 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var modelExpression = new ModelExpression(nameof(Model.Text), metadata); var tagHelper = new TextAreaTagHelper(); - var tagHelperContext = new TagHelperContext(new Dictionary(), uniqueId: "test"); - var output = new TagHelperOutput(expectedTagName, expectedAttributes, expectedContent) + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); + var output = new TagHelperOutput(expectedTagName, expectedAttributes) { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, SelfClosing = true, }; diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs index 44e4f6beef..29bfa1b599 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationMessageTagHelperTest.cs @@ -28,20 +28,29 @@ namespace Microsoft.AspNet.Mvc.TagHelpers For = modelExpression }; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; + var tagHelperContext = new TagHelperContext( allAttributes: new Dictionary { { "id", "myvalidationmessage" }, { "for", modelExpression }, }, - uniqueId: "test"); + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var output = new TagHelperOutput( expectedTagName, attributes: new Dictionary { { "id", "myvalidationmessage" } - }, - content: "Something"); + }) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, + }; var htmlGenerator = new TestableHtmlGenerator(metadataProvider); var viewContext = TestableHtmlGenerator.GetViewContext(model: null, htmlGenerator: htmlGenerator, @@ -62,7 +71,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal("Name", attribute.Value); attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-replace")); Assert.Equal("true", attribute.Value); - Assert.Equal("Something", output.Content); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); Assert.Equal(expectedTagName, output.TagName); } @@ -74,10 +85,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { For = CreateModelExpression("Hello") }; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; + var context = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var output = new TagHelperOutput( "span", - attributes: new Dictionary(), - content: "Content of validation message"); + attributes: new Dictionary()) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, + }; var expectedViewContext = CreateViewContext(); var generator = new Mock(); generator @@ -89,19 +111,22 @@ namespace Microsoft.AspNet.Mvc.TagHelpers validationMessageTagHelper.ViewContext = expectedViewContext; // Act & Assert - await validationMessageTagHelper.ProcessAsync(context: null, output: output); + await validationMessageTagHelper.ProcessAsync(context, output: output); generator.Verify(); Assert.Equal("span", output.TagName); Assert.Empty(output.Attributes); - Assert.Equal("Content of validation message", output.Content); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); } [Theory] - [InlineData("Content of validation message", "Content of validation message")] - [InlineData("\r\n \r\n", "New HTML")] - public async Task ProcessAsync_MergesTagBuilderFromGenerateValidationMessage( - string outputContent, string expectedOutputContent) + [InlineData("Content of validation message", "Some Content", "Some Content")] + [InlineData("\r\n \r\n", "\r\n Something Else \r\n", "\r\n Something Else \r\n")] + [InlineData("\r\n \r\n", "Some Content", "Some Content")] + public async Task ProcessAsync_DoesNotOverrideOutputContent( + string childContent, string outputContent, string expectedOutputContent) { // Arrange var validationMessageTagHelper = new ValidationMessageTagHelper @@ -110,8 +135,14 @@ namespace Microsoft.AspNet.Mvc.TagHelpers }; var output = new TagHelperOutput( "span", - attributes: new Dictionary(), - content: outputContent); + attributes: new Dictionary()) + { + Content = outputContent + }; + + var context = new TagHelperContext(allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult(childContent)); var tagBuilder = new TagBuilder("span2") { InnerHtml = "New HTML" @@ -133,7 +164,58 @@ namespace Microsoft.AspNet.Mvc.TagHelpers validationMessageTagHelper.Generator = generator.Object; // Act - await validationMessageTagHelper.ProcessAsync(context: null, output: output); + await validationMessageTagHelper.ProcessAsync(context, output: output); + + // Assert + Assert.Equal("span", output.TagName); + Assert.Equal(2, output.Attributes.Count); + var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-foo")); + Assert.Equal("bar", attribute.Value); + attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-hello")); + Assert.Equal("world", attribute.Value); + Assert.Equal(expectedOutputContent, output.Content); + } + + [Theory] + [InlineData("Content of validation message", "Content of validation message")] + [InlineData("\r\n \r\n", "New HTML")] + public async Task ProcessAsync_MergesTagBuilderFromGenerateValidationMessage( + string childContent, string expectedOutputContent) + { + // Arrange + var validationMessageTagHelper = new ValidationMessageTagHelper + { + For = CreateModelExpression("Hello") + }; + var output = new TagHelperOutput( + "span", + attributes: new Dictionary()); + + var context = new TagHelperContext(allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult(childContent)); + var tagBuilder = new TagBuilder("span2") + { + InnerHtml = "New HTML" + }; + tagBuilder.Attributes.Add("data-foo", "bar"); + tagBuilder.Attributes.Add("data-hello", "world"); + + var generator = new Mock(MockBehavior.Strict); + var setup = generator + .Setup(mock => mock.GenerateValidationMessage( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(tagBuilder); + var viewContext = CreateViewContext(); + validationMessageTagHelper.ViewContext = viewContext; + validationMessageTagHelper.Generator = generator.Object; + + // Act + await validationMessageTagHelper.ProcessAsync(context, output: output); // Assert Assert.Equal("span", output.TagName); @@ -150,10 +232,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { // Arrange var validationMessageTagHelper = new ValidationMessageTagHelper(); + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var output = new TagHelperOutput( "span", - attributes: new Dictionary(), - content: "Content of validation message"); + attributes: new Dictionary()) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, + }; var viewContext = CreateViewContext(); var generator = new Mock(MockBehavior.Strict); validationMessageTagHelper.ViewContext = viewContext; @@ -165,7 +254,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal("span", output.TagName); Assert.Empty(output.Attributes); - Assert.Equal("Content of validation message", output.Content); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); } private static ModelExpression CreateModelExpression(string name) diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs index bdad85e1a3..5cfeddef10 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/ValidationSummaryTagHelperTest.cs @@ -40,14 +40,23 @@ namespace Microsoft.AspNet.Mvc.TagHelpers ValidationSummary = ValidationSummary.All, }; - var tagHelperContext = new TagHelperContext(new Dictionary(), uniqueId: "test"); + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var tagHelperContext = new TagHelperContext( + allAttributes: new Dictionary(), + uniqueId: "test", + getChildContentAsync: () => Task.FromResult("Something")); var output = new TagHelperOutput( expectedTagName, attributes: new Dictionary { { "class", "form-control" } - }, - content: "Custom Content"); + }) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = "Custom Content", + }; var htmlGenerator = new TestableHtmlGenerator(metadataProvider); Model model = null; @@ -64,8 +73,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal("form-control validation-summary-valid", attribute.Value); attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-summary")); Assert.Equal("true", attribute.Value); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); Assert.Equal("Custom Content
  • " + Environment.NewLine + "
", - output.Content); + output.PostContent); Assert.Equal(expectedTagName, output.TagName); } @@ -81,10 +92,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { ValidationSummary = validationSummary, }; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var output = new TagHelperOutput( "div", - attributes: new Dictionary(), - content: "Content of validation summary"); + attributes: new Dictionary()) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, + }; var expectedViewContext = CreateViewContext(); var generator = new Mock(); generator @@ -105,7 +123,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers generator.Verify(); Assert.Equal("div", output.TagName); Assert.Empty(output.Attributes); - Assert.Equal("Content of validation summary", output.Content); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); } [Fact] @@ -116,10 +136,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { ValidationSummary = ValidationSummary.ModelOnly, }; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; var output = new TagHelperOutput( "div", - attributes: new Dictionary(), - content: "Content of validation summary"); + attributes: new Dictionary()) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = "Content of validation summary" + }; var tagBuilder = new TagBuilder("span2") { InnerHtml = "New HTML" @@ -154,7 +180,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.Equal("world", attribute.Value); attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("anything")); Assert.Equal("something", attribute.Value); - Assert.Equal("Content of validation summaryNew HTML", output.Content); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); + Assert.Equal("Content of validation summaryNew HTML", output.PostContent); } [Fact] @@ -165,10 +193,17 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { ValidationSummary = ValidationSummary.None, }; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; + var expectedPostContent = "original post-content"; var output = new TagHelperOutput( "div", - attributes: new Dictionary(), - content: "Content of validation message"); + attributes: new Dictionary()) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = expectedPostContent, + }; var generator = new Mock(MockBehavior.Strict); var viewContext = CreateViewContext(); @@ -181,7 +216,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal("div", output.TagName); Assert.Empty(output.Attributes); - Assert.Equal("Content of validation message", output.Content); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); + Assert.Equal(expectedPostContent, output.PostContent); } [Theory] @@ -194,10 +231,16 @@ namespace Microsoft.AspNet.Mvc.TagHelpers { ValidationSummary = validationSummary, }; + var expectedPreContent = "original pre-content"; + var expectedContent = "original content"; var output = new TagHelperOutput( "div", - attributes: new Dictionary(), - content: "Content of validation message"); + attributes: new Dictionary()) + { + PreContent = expectedPreContent, + Content = expectedContent, + PostContent = "Content of validation message", + }; var tagBuilder = new TagBuilder("span2") { InnerHtml = "New HTML" @@ -223,7 +266,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers // Assert Assert.Equal("div", output.TagName); Assert.Empty(output.Attributes); - Assert.Equal("Content of validation messageNew HTML", output.Content); + Assert.Equal(expectedPreContent, output.PreContent); + Assert.Equal(expectedContent, output.Content); + Assert.Equal("Content of validation messageNew HTML", output.PostContent); generator.Verify(); } diff --git a/test/WebSites/ActivatorWebSite/TagHelpers/HiddenTagHelper.cs b/test/WebSites/ActivatorWebSite/TagHelpers/HiddenTagHelper.cs index f57d7daf0f..b031b4a14f 100644 --- a/test/WebSites/ActivatorWebSite/TagHelpers/HiddenTagHelper.cs +++ b/test/WebSites/ActivatorWebSite/TagHelpers/HiddenTagHelper.cs @@ -1,10 +1,10 @@ // 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.Threading.Tasks; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Razor.Runtime.TagHelpers; -using System.Threading.Tasks; namespace ActivatorWebSite.TagHelpers { diff --git a/test/WebSites/ActivatorWebSite/TagHelpers/RepeatContentTagHelper.cs b/test/WebSites/ActivatorWebSite/TagHelpers/RepeatContentTagHelper.cs index da9d85dce5..07ba4230d7 100644 --- a/test/WebSites/ActivatorWebSite/TagHelpers/RepeatContentTagHelper.cs +++ b/test/WebSites/ActivatorWebSite/TagHelpers/RepeatContentTagHelper.cs @@ -1,10 +1,10 @@ // 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.Threading.Tasks; using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Razor.Runtime.TagHelpers; -using System.Threading.Tasks; namespace ActivatorWebSite.TagHelpers { diff --git a/test/WebSites/RequestServicesWebSite/RequestScopedTagHelper.cs b/test/WebSites/RequestServicesWebSite/RequestScopedTagHelper.cs index 1b918cfe6e..d0743d66d2 100644 --- a/test/WebSites/RequestServicesWebSite/RequestScopedTagHelper.cs +++ b/test/WebSites/RequestServicesWebSite/RequestScopedTagHelper.cs @@ -7,7 +7,6 @@ using Microsoft.AspNet.Razor.TagHelpers; namespace RequestServicesWebSite { - [ContentBehavior(ContentBehavior.Replace)] public class RequestScopedTagHelper : TagHelper { [Activate] diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/ATagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/ATagHelper.cs index 65a0afb35a..40355cf6b8 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/ATagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/ATagHelper.cs @@ -8,7 +8,6 @@ using Microsoft.AspNet.Razor.TagHelpers; namespace TagHelpersWebSite.TagHelpers { - [ContentBehavior(ContentBehavior.Prepend)] public class ATagHelper : TagHelper { [Activate] @@ -31,7 +30,7 @@ namespace TagHelpersWebSite.TagHelpers output.Attributes["href"] = UrlHelper.Action(Action, Controller, methodParameters); - output.Content = "My "; + output.PreContent = "My "; } } } diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/AutoLinkerTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/AutoLinkerTagHelper.cs index 678b6fd591..71a0111864 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/AutoLinkerTagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/AutoLinkerTagHelper.cs @@ -2,20 +2,22 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Text.RegularExpressions; +using System.Threading.Tasks; using Microsoft.AspNet.Razor.Runtime.TagHelpers; using Microsoft.AspNet.Razor.TagHelpers; namespace TagHelpersWebSite.TagHelpers { [HtmlElementName("p")] - [ContentBehavior(ContentBehavior.Modify)] public class AutoLinkerTagHelper : TagHelper { - public override void Process(TagHelperContext context, TagHelperOutput output) + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { + var childContent = await context.GetChildContentAsync(); + // Find Urls in the content and replace them with their anchor tag equivalent. output.Content = Regex.Replace( - output.Content, + childContent, @"\b(?:https?://|www\.)(\S+)\b", "$0"); } diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/ConditionTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/ConditionTagHelper.cs index 290c30a6c8..9bf4b13116 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/ConditionTagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/ConditionTagHelper.cs @@ -7,7 +7,6 @@ using Microsoft.AspNet.Razor.TagHelpers; namespace TagHelpersWebSite.TagHelpers { [HtmlElementName("div", "style", "p")] - [ContentBehavior(ContentBehavior.Modify)] public class ConditionTagHelper : TagHelper { public bool? Condition { get; set; } @@ -17,8 +16,7 @@ namespace TagHelpersWebSite.TagHelpers // If a condition is set and evaluates to false, don't render the tag. if (Condition.HasValue && !Condition.Value) { - output.TagName = null; - output.Content = null; + output.SuppressOutput(); } } } diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/NestedViewStartTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/NestedViewStartTagHelper.cs index cd07dabb7e..8ef3daa358 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/NestedViewStartTagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/NestedViewStartTagHelper.cs @@ -7,7 +7,6 @@ using Microsoft.AspNet.Razor.TagHelpers; namespace TagHelpersWebSite.TagHelpers { [HtmlElementName("nested")] - [ContentBehavior(ContentBehavior.Modify)] public class NestedViewStartTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/PrettyTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/PrettyTagHelper.cs index be22553fc7..c1d6f211c2 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/PrettyTagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/PrettyTagHelper.cs @@ -33,7 +33,10 @@ namespace TagHelpersWebSite.TagHelpers public override void Process(TagHelperContext context, TagHelperOutput output) { - if (MakePretty.HasValue && !MakePretty.Value) + // Need to check if output.TagName == null in-case the ConditionTagHelper calls into SuppressOutput and + // therefore sets the TagName to null. + if (MakePretty.HasValue && !MakePretty.Value || + output.TagName == null) { return; } diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/RootViewStartTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/RootViewStartTagHelper.cs index c25be05c1a..d5d9fa15d0 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/RootViewStartTagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/RootViewStartTagHelper.cs @@ -7,7 +7,6 @@ using Microsoft.AspNet.Razor.TagHelpers; namespace TagHelpersWebSite.TagHelpers { [HtmlElementName("root")] - [ContentBehavior(ContentBehavior.Replace)] public class RootViewStartTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/TagCloudViewComponentTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/TagCloudViewComponentTagHelper.cs index 4bfcdea267..a356c0b98a 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/TagCloudViewComponentTagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/TagCloudViewComponentTagHelper.cs @@ -14,7 +14,6 @@ namespace MvcSample.Web.Components { [HtmlElementName("tag-cloud")] [ViewComponent(Name = "Tags")] - [ContentBehavior(ContentBehavior.Replace)] public class TagCloudViewComponentTagHelper : ITagHelper { private static readonly string[] Tags = diff --git a/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs b/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs index c98e1f152a..8647e6acac 100644 --- a/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs +++ b/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs @@ -3,12 +3,10 @@ using System; using Microsoft.AspNet.Razor.Runtime.TagHelpers; -using Microsoft.AspNet.Razor.TagHelpers; using TagHelpersWebSite.Models; namespace TagHelpersWebSite.TagHelpers { - [ContentBehavior(ContentBehavior.Append)] public class WebsiteInformationTagHelper : TagHelper { public WebsiteContext Info { get; set; } @@ -16,7 +14,7 @@ namespace TagHelpersWebSite.TagHelpers public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "section"; - output.Content = string.Format( + output.PostContent = string.Format( "

Version: {0}

" + Environment.NewLine + "

Copyright Year: {1}

" + Environment.NewLine + "

Approved: {2}

" + Environment.NewLine +