From b1a3c8c1d471fdd817a0cbb0f19f548192fa4076 Mon Sep 17 00:00:00 2001 From: NTaylorMullen Date: Thu, 25 Sep 2014 01:05:22 -0700 Subject: [PATCH] Test TagHelperRunner, TagHelperOutput and TagHelperExecutionContext. #154 --- .../TagHelpers/CommonTagHelpers.cs | 8 +- .../TagHelpers/TagHelperOutputTest.cs | 212 ++++++++++++++++++ .../TagHelpers/TagHelperRunnerTest.cs | 109 +++++++++ .../TagHelpers/TagHelperTypeResolverTest.cs | 29 +++ .../TagHelpersExecutionContextTest.cs | 91 ++++++++ 5 files changed, 445 insertions(+), 4 deletions(-) create mode 100644 test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs create mode 100644 test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperRunnerTest.cs create mode 100644 test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelpersExecutionContextTest.cs diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/CommonTagHelpers.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/CommonTagHelpers.cs index 5ef221dd4b..d9edeca8ca 100644 --- a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/CommonTagHelpers.cs +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/CommonTagHelpers.cs @@ -3,7 +3,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { - public class Valid_PlainTagHelper : ITagHelper + public class Valid_PlainTagHelper : TagHelper { } @@ -11,19 +11,19 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers { } - public class SingleAttributeTagHelper : ITagHelper + public class SingleAttributeTagHelper : TagHelper { public int IntAttribute { get; set; } } - public class MissingAccessorTagHelper : ITagHelper + public class MissingAccessorTagHelper : TagHelper { public string ValidAttribute { get; set; } public string InvalidNoGetAttribute { set { } } public string InvalidNoSetAttribute { get { return string.Empty; } } } - public class PrivateAccessorTagHelper : ITagHelper + public class PrivateAccessorTagHelper : TagHelper { public string ValidAttribute { get; set; } public string InvalidPrivateSetAttribute { get; private set; } diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs new file mode 100644 index 0000000000..363ac7424d --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperOutputTest.cs @@ -0,0 +1,212 @@ +// 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 Xunit; + +namespace Microsoft.AspNet.Razor.Runtime.TagHelpers +{ + public class TagHelperOutputTest + { + [Fact] + public void TagName_CannotSetToNullInCtor() + { + // Arrange & Act + var tagHelperOutput = new TagHelperOutput(null); + + // Assert + Assert.Empty(tagHelperOutput.TagName); + } + + [Fact] + public void TagName_CannotSetToNull() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p"); + + // Act + tagHelperOutput.TagName = null; + + // Assert + Assert.Empty(tagHelperOutput.TagName); + } + + [Fact] + public void Content_CannotSetToNull() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p"); + + // Act + tagHelperOutput.Content = null; + + // Assert + Assert.Empty(tagHelperOutput.Content); + } + + [Fact] + public void GenerateStartTag_ReturnsFullStartTag() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p", attributes: + new Dictionary + { + { "class", "btn" }, + { "something", " spaced " } + }); + + // Act + var output = tagHelperOutput.GenerateStartTag(); + + // Assert + Assert.Equal("

", output); + } + + [Fact] + public void GenerateStartTag_ReturnsNoAttributeStartTag() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p"); + + // Act + var output = tagHelperOutput.GenerateStartTag(); + + // Assert + Assert.Equal("

", output); + } + + [Fact] + public void GenerateStartTag_ReturnsSelfClosingStartTag_Attributes() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p", + attributes: new Dictionary + { + { "class", "btn" }, + { "something", " spaced " } + }); + + tagHelperOutput.SelfClosing = true; + + // Act + var output = tagHelperOutput.GenerateStartTag(); + + // Assert + Assert.Equal("

", output); + } + + [Fact] + public void GenerateStartTag_ReturnsSelfClosingStartTag_NoAttributes() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p"); + + tagHelperOutput.SelfClosing = true; + + // Act + var output = tagHelperOutput.GenerateStartTag(); + + // Assert + Assert.Equal("

", output); + } + + [Fact] + public void GenerateStartTag_ReturnsNothingIfWhitespaceTagName() + { + // Arrange + var tagHelperOutput = new TagHelperOutput(" ", + attributes: new Dictionary + { + { "class", "btn" }, + { "something", " spaced " } + }); + + tagHelperOutput.SelfClosing = true; + + // Act + var output = tagHelperOutput.GenerateStartTag(); + + // Assert + Assert.Empty(output); + } + + + [Fact] + public void GenerateEndTag_ReturnsNothingIfWhitespaceTagName() + { + // Arrange + var tagHelperOutput = new TagHelperOutput(" "); ; + + tagHelperOutput.Content = "Hello World"; + + // Act + var output = tagHelperOutput.GenerateEndTag(); + + // Assert + Assert.Empty(output); + } + + [Fact] + public void GenerateContent_ReturnsContent() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p"); + + tagHelperOutput.Content = "Hello World"; + + // Act + var output = tagHelperOutput.GenerateContent(); + + // Assert + Assert.Equal("Hello World", output); + } + + + [Fact] + public void GenerateContent_ReturnsNothingIfSelfClosing() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p") + { + SelfClosing = true + }; + + tagHelperOutput.Content = "Hello World"; + + // Act + var output = tagHelperOutput.GenerateContent(); + + // Assert + Assert.Empty(output); + } + + [Fact] + public void GenerateEndTag_ReturnsEndTag() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p"); + + // Act + var output = tagHelperOutput.GenerateEndTag(); + + // Assert + Assert.Equal("

", output); + } + + [Fact] + public void GenerateEndTag_ReturnsNothingIfSelfClosing() + { + // Arrange + var tagHelperOutput = new TagHelperOutput("p") + { + SelfClosing = true + }; + + // Act + var output = tagHelperOutput.GenerateEndTag(); + + // Assert + Assert.Empty(output); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperRunnerTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperRunnerTest.cs new file mode 100644 index 0000000000..f7ce46ee9b --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperRunnerTest.cs @@ -0,0 +1,109 @@ +// 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.IO; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.AspNet.Razor.Runtime.TagHelpers +{ + public class TagHelperRunnerTest + { + [Fact] + public async Task RunAsync_ProcessesAllTagHelpers() + { + // Arrange + var runner = new TagHelperRunner(); + var executionContext = new TagHelpersExecutionContext("p"); + var executableTagHelper1 = new ExecutableTagHelper(); + var executableTagHelper2 = new ExecutableTagHelper(); + + // Act + executionContext.Add(executableTagHelper1); + executionContext.Add(executableTagHelper2); + await runner.RunAsync(executionContext); + + // Assert + Assert.True(executableTagHelper1.Processed); + Assert.True(executableTagHelper2.Processed); + } + + [Fact] + public async Task RunAsync_AllowsModificationOfTagHelperOutput() + { + // Arrange + var runner = new TagHelperRunner(); + var executionContext = new TagHelpersExecutionContext("p"); + var executableTagHelper = new ExecutableTagHelper(); + + // Act + executionContext.Add(executableTagHelper); + executionContext.AddHtmlAttribute("class", "btn"); + var output = await runner.RunAsync(executionContext); + + // Assert + Assert.Equal("foo", output.TagName); + Assert.Equal("somethingelse", output.Attributes["class"]); + Assert.Equal("world", output.Attributes["hello"]); + Assert.Equal(true, output.SelfClosing); + } + + [Fact] + public async Task RunAsync_AllowsDataRetrievalFromTagHelperContext() + { + // Arrange + var runner = new TagHelperRunner(); + var executionContext = new TagHelpersExecutionContext("p"); + var tagHelper = new TagHelperContextTouchingTagHelper(); + + // Act + executionContext.Add(tagHelper); + executionContext.AddTagHelperAttribute("foo", true); + var output = await runner.RunAsync(executionContext); + + // Assert + Assert.Equal("True", output.Attributes["foo"]); + } + + [Fact] + public async Task RunAsync_WithContentSetsOutputsContent() + { + // Arrange + var runner = new TagHelperRunner(); + var executionContext = new TagHelpersExecutionContext("p"); + var tagHelper = new ExecutableTagHelper(); + var contentWriter = new StringWriter(new StringBuilder("Hello World")); + + // Act + executionContext.Add(tagHelper); + var output = await runner.RunAsync(executionContext, contentWriter); + + // Assert + Assert.Equal(output.Content, "Hello World"); + } + + private class ExecutableTagHelper : TagHelper + { + public bool Processed { get; set; } + + public override void Process(TagHelperContext context, TagHelperOutput output) + { + Processed = true; + + output.TagName = "foo"; + output.Attributes["class"] = "somethingelse"; + output.Attributes["hello"] = "world"; + output.SelfClosing = true; + } + } + + private class TagHelperContextTouchingTagHelper : TagHelper + { + public override void Process(TagHelperContext context, TagHelperOutput output) + { + output.Attributes["foo"] = context.AllAttributes["foo"].ToString(); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs index 425e587ff0..8641a0970d 100644 --- a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelperTypeResolverTest.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using Xunit; namespace Microsoft.AspNet.Razor.Runtime.TagHelpers @@ -122,18 +123,34 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers public class Invalid_NestedPublicTagHelper : ITagHelper { + public Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + return Task.FromResult(result: true); + } } internal class Invalid_NestedInternalTagHelper : ITagHelper { + public Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + return Task.FromResult(result: true); + } } private class Invalid_PrivateTagHelper : ITagHelper { + public Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + return Task.FromResult(result: true); + } } protected class Invalid_ProtectedTagHelper : ITagHelper { + public Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + return Task.FromResult(result: true); + } } } @@ -141,13 +158,25 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers // In this case they do not fulfill other TagHelper requirements. public abstract class Invalid_AbstractTagHelper : ITagHelper { + public Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + return Task.FromResult(result: true); + } } public class Invalid_GenericTagHelper : ITagHelper { + public Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + return Task.FromResult(result: true); + } } internal class Invalid_InternalTagHelper : ITagHelper { + public Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + { + return Task.FromResult(result: true); + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelpersExecutionContextTest.cs b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelpersExecutionContextTest.cs new file mode 100644 index 0000000000..75f8ff38f5 --- /dev/null +++ b/test/Microsoft.AspNet.Razor.Runtime.Test/TagHelpers/TagHelpersExecutionContextTest.cs @@ -0,0 +1,91 @@ +// 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 System.Linq; +using Xunit; + +namespace Microsoft.AspNet.Razor.Runtime.TagHelpers +{ + public class TagHelpersExecutionContextTest + { + [Fact] + public void AddHtmlAttribute_MaintainsHTMLAttributes() + { + // Arrange + var executionContext = new TagHelpersExecutionContext("p"); + var expectedAttributes = new Dictionary + { + { "class", "btn" }, + { "foo", "bar" } + }; + + // Act + executionContext.AddHtmlAttribute("class", "btn"); + executionContext.AddHtmlAttribute("foo", "bar"); + + // Assert + Assert.Equal(expectedAttributes, executionContext.HTMLAttributes); + } + + [Fact] + public void TagHelpersExecutionContext_MaintainsAllAttributes() + { + // Arrange + var executionContext = new TagHelpersExecutionContext("p"); + var expectedAttributes = new Dictionary + { + { "class", "btn" }, + { "something", true }, + { "foo", "bar" } + }; + + // Act + executionContext.AddHtmlAttribute("class", "btn"); + executionContext.AddTagHelperAttribute("something", true); + executionContext.AddHtmlAttribute("foo", "bar"); + + // Assert + Assert.Equal(expectedAttributes, executionContext.AllAttributes); + } + + [Fact] + public void Add_MaintainsTagHelpers() + { + // Arrange + var executionContext = new TagHelpersExecutionContext("p"); + var tagHelper = new PTagHelper(); + + // Act + executionContext.Add(tagHelper); + + // Assert + var singleTagHelper = Assert.Single(executionContext.TagHelpers); + Assert.Same(tagHelper, singleTagHelper); + } + + [Fact] + public void Add_MaintainsMultipleTagHelpers() + { + // Arrange + var executionContext = new TagHelpersExecutionContext("p"); + var tagHelper1 = new PTagHelper(); + var tagHelper2 = new PTagHelper(); + + // Act + executionContext.Add(tagHelper1); + executionContext.Add(tagHelper2); + + // Assert + var tagHelpers = executionContext.TagHelpers.ToArray(); + Assert.Equal(2, tagHelpers.Length); + Assert.Same(tagHelper1, tagHelpers[0]); + Assert.Same(tagHelper2, tagHelpers[1]); + + } + + private class PTagHelper : TagHelper + { + } + } +} \ No newline at end of file