From ec928d6a3ac35a6ebf6a7808ec1bc78a1272fbe0 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Sat, 9 Apr 2022 23:29:46 -0500 Subject: [PATCH 1/3] Addressed Sonar Cloud Code Smell Issues --- .../Card/CardHeaderActionsTagHelper.cs | 4 ++-- .../Card/CardHeaderTagHelper.cs | 4 ++-- .../Form/FormInputTagHelper.cs | 2 +- .../Modal/ModalHeaderTagHelper.cs | 7 ++++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderActionsTagHelper.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderActionsTagHelper.cs index 62e6975..4bb5ad2 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderActionsTagHelper.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderActionsTagHelper.cs @@ -27,7 +27,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp if (cardContext == null) throw new ArgumentException("CardContext is not specified in context parameter"); - return ProcessAsyncInternal(context, output); + return ProcessAsyncInternal(output); } /// @@ -36,7 +36,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp /// /// /// - private async Task ProcessAsyncInternal(TagHelperContext context, TagHelperOutput output) + private static async Task ProcessAsyncInternal(TagHelperOutput output) { output.TagName = "div"; output.AddClass("ml-auto", HtmlEncoder.Default); diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderTagHelper.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderTagHelper.cs index 6baf9aa..9447484 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderTagHelper.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers/Card/CardHeaderTagHelper.cs @@ -32,10 +32,10 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp if (context.Items[typeof(CardContext)] is not CardContext cardContext) throw new ArgumentException("CardContext is not specified in context parameter"); - return ProcessAsyncInternal(context, output, cardContext); + return ProcessAsyncInternal(output, cardContext); } - private async Task ProcessAsyncInternal(TagHelperContext context, TagHelperOutput output, CardContext cardContext) + private async Task ProcessAsyncInternal(TagHelperOutput output, CardContext cardContext) { //Setup basic tag information output.TagName = "div"; diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs index 39ca752..6ddf047 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs @@ -30,7 +30,7 @@ public FormInputTagHelper(IHtmlGenerator generator) : base(generator) /// /// /// - public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) + public override void Process(TagHelperContext context, TagHelperOutput output) { //Call our base implementation base.Process(context, output); diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalHeaderTagHelper.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalHeaderTagHelper.cs index 514aa2e..6db5cb3 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalHeaderTagHelper.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalHeaderTagHelper.cs @@ -32,10 +32,10 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp if (modalContext == null) throw new ArgumentException("ModalContext not present"); - return ProcessAsyncInternal(context, output, modalContext); + return ProcessAsyncInternal(output, modalContext); } - private async Task ProcessAsyncInternal(TagHelperContext context, TagHelperOutput output, ModalContext modalContext) + private async Task ProcessAsyncInternal(TagHelperOutput output, ModalContext modalContext) { //Setup basic tag information output.TagName = "div"; @@ -46,7 +46,8 @@ private async Task ProcessAsyncInternal(TagHelperContext context, TagHelperOutpu { var titleTag = new TagBuilder("h5"); titleTag.Attributes.Add("class", "modal-title"); - titleTag.Attributes.Add("id", $"{modalContext.Id}Label"); + if(!string.IsNullOrEmpty(modalContext.Id)) + titleTag.Attributes.Add("id", $"{modalContext.Id}Label"); titleTag.InnerHtml.Append(Title); output.Content.AppendHtml(titleTag); } From 93e36efae045cf1a36534d102233c0e65e9e9754 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Sun, 10 Apr 2022 00:51:47 -0500 Subject: [PATCH 2/3] Code Coverage Improvements --- .../Views/Home/Index.cshtml | 4 +- .../AlertTagHelperTests.cs | 7 +- .../Card/CardHeaderActionsTagHelperTests.cs | 19 +- .../Card/CardHeaderTagHelperTests.cs | 38 +++- .../Card/CardTagHelperTests.cs | 35 ++++ .../Modal/ModalHeaderTagHelperTests.cs | 190 +++++++++++------- .../Modal/ModalTagHelperTests.cs | 160 +++++++++++++++ .../Form/FormInputTagHelper.cs | 1 - .../Modal/ModalTagHelper.cs | 29 ++- 9 files changed, 394 insertions(+), 89 deletions(-) create mode 100644 src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalTagHelperTests.cs diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers.Sample/Views/Home/Index.cshtml b/src/AspNetCore.Utilities.BootstrapTagHelpers.Sample/Views/Home/Index.cshtml index 16344c8..9d02e0e 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers.Sample/Views/Home/Index.cshtml +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers.Sample/Views/Home/Index.cshtml @@ -263,7 +263,7 @@ - + @@ -280,7 +280,7 @@ <modal-header-dismiss></modal-header-dismiss> </modal-header> <modal-body> - <form-text-input asp-for="Name"></form-text-input> + <form-input asp-for="Name"></form-input> </modal-body> <modal-footer> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/AlertTagHelperTests.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/AlertTagHelperTests.cs index 6067130..20094cd 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/AlertTagHelperTests.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/AlertTagHelperTests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; using Xunit; namespace ICG.AspNetCore.Utilities.BootstrapTagHelpers.Tests; @@ -7,7 +8,7 @@ public class AlertTagHelperTests : AbstractTagHelperTest { [Fact] - public void Should_NotRender_If_Display_Is_Hidden() + public async Task Should_NotRender_If_Display_Is_Hidden() { //Arrange var context = MakeTagHelperContext(); @@ -15,7 +16,7 @@ public void Should_NotRender_If_Display_Is_Hidden() //Act var helper = new AlertTagHelper() { HideDisplay = true }; - helper.Process(context, output); + await helper.ProcessAsync(context, output); //Assert Assert.True(output.Content.IsEmptyOrWhiteSpace); diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderActionsTagHelperTests.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderActionsTagHelperTests.cs index a9175cc..7fb7970 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderActionsTagHelperTests.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderActionsTagHelperTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Card; using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Contexts; @@ -24,6 +25,22 @@ public async Task Should_ThrowException_WhenMissingContext() Assert.IsType(exceptionResult); } + [Fact] + public async Task Should_ThrowException_WhenContextIsNull() + { + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(CardContext), null); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new CardHeaderActionsTagHelper(); + var exceptionResult = await Record.ExceptionAsync(() => helper.ProcessAsync(context, output)); + + Assert.NotNull(exceptionResult); + Assert.IsType(exceptionResult); + } + [Fact] public async Task Should_Render_With_ClassAdded() { diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderTagHelperTests.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderTagHelperTests.cs index 8f785c6..fcfe5be 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderTagHelperTests.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardHeaderTagHelperTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Card; using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Contexts; @@ -24,6 +25,22 @@ public async Task Should_ThrowException_WhenMissingContext() Assert.IsType(exceptionResult); } + [Fact] + public async Task Should_ThrowException_WhenContextIsNull() + { + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(CardContext), null); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new CardHeaderTagHelper(); + var exceptionResult = await Record.ExceptionAsync(() => helper.ProcessAsync(context, output)); + + Assert.NotNull(exceptionResult); + Assert.IsType(exceptionResult); + } + [Fact] public async Task Should_Render_As_Div_WhenContextAvailable() { @@ -75,4 +92,23 @@ public async Task Should_Render_With_ClassAdded_PreservingCustomClasses() //Assert Assert.Equal(expectedClass, output.Attributes["class"].Value.ToString()); } + + [Theory] + [InlineData("", "", "
")] + [InlineData("Testing", "", "
Testing
")] + [InlineData("Testing", "myCard", "
Testing
")] + public async Task Should_Render_WithProper_InnerHtmlContent(string title, string contextId, string expectedOutput) + { + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(CardContext), new CardContext{Id = contextId}); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new CardHeaderTagHelper{Title = title}; + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal(expectedOutput, output.Content.GetContent()); + } } \ No newline at end of file diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardTagHelperTests.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardTagHelperTests.cs index 12f4531..950097f 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardTagHelperTests.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Card/CardTagHelperTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Card; +using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Contexts; using Microsoft.AspNetCore.Razor.TagHelpers; using Xunit; @@ -8,6 +9,40 @@ namespace ICG.AspNetCore.Utilities.BootstrapTagHelpers.Tests.Card; public class CardTagHelperTests : AbstractTagHelperTest { + [Fact] + public async Task Should_Not_Error_With_Missing_Id_Attribute() + { + //Arrange + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new CardTagHelper(); + var exception = await Record.ExceptionAsync(() => helper.ProcessAsync(context, output)); + + //Assert + Assert.Null(exception); + } + + [Fact] + public async Task Should_Add_Context_Object_With_Provided_Id() + { + //Arrange + var context = MakeTagHelperContext(); + var providedId = "testingCarg"; + var existingAttributes = new TagHelperAttributeList(new List + {new("id", providedId)}); + var output = MakeTagHelperOutput(" ", existingAttributes); + + //Act + var helper = new CardTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + var generatedContext = Assert.IsType(context.Items[typeof(CardContext)]); + Assert.Equal(providedId, generatedContext.Id); + } + [Fact] public async Task Should_Render_As_Div() { diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalHeaderTagHelperTests.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalHeaderTagHelperTests.cs index e2be35d..ca59e0c 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalHeaderTagHelperTests.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalHeaderTagHelperTests.cs @@ -1,82 +1,130 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Runtime.InteropServices; using System.Threading.Tasks; using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Contexts; using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Modal; using Microsoft.AspNetCore.Razor.TagHelpers; using Xunit; -namespace ICG.AspNetCore.Utilities.BootstrapTagHelpers.Tests.Modal +namespace ICG.AspNetCore.Utilities.BootstrapTagHelpers.Tests.Modal; + +public class ModalHeaderTagHelperTests : AbstractTagHelperTest { - public class ModalHeaderTagHelperTests : AbstractTagHelperTest + [Fact] + public async Task Should_ThrowException_WhenMissingContext() + { + //Arrange + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalHeaderTagHelper(); + var exceptionResult = await Record.ExceptionAsync(() => helper.ProcessAsync(context, output)); + + Assert.NotNull(exceptionResult); + Assert.IsType(exceptionResult); + } + + [Fact] + public async Task Should_ThrowException_WhenContextIsNull() + { + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(ModalContext), null); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalHeaderTagHelper(); + var exceptionResult = await Record.ExceptionAsync(() => helper.ProcessAsync(context, output)); + + Assert.NotNull(exceptionResult); + Assert.IsType(exceptionResult); + } + + [Fact] + public async Task Should_Render_As_Div() + { + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(ModalContext), new ModalContext()); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalHeaderTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal("div", output.TagName); + } + + [Fact] + public async Task Should_Render_With_ClassAdded() { - [Fact] - public async Task Should_ThrowException_WhenMissingContext() - { - //Arrange - var context = MakeTagHelperContext(); - var output = MakeTagHelperOutput(" "); - - //Act - var helper = new ModalHeaderTagHelper(); - var exceptionResult = await Record.ExceptionAsync(() => helper.ProcessAsync(context, output)); - - Assert.NotNull(exceptionResult); - Assert.IsType(exceptionResult); - } - - [Fact] - public async Task Should_Render_As_Div() - { - //Arrange - var context = MakeTagHelperContext(); - context.Items.Add(typeof(ModalContext), new ModalContext()); - var output = MakeTagHelperOutput(" "); - - //Act - var helper = new ModalHeaderTagHelper(); - await helper.ProcessAsync(context, output); - - //Assert - Assert.Equal("div", output.TagName); - } - - [Fact] - public async Task Should_Render_With_ClassAdded() - { - //Arrange - var context = MakeTagHelperContext(); - context.Items.Add(typeof(ModalContext), new ModalContext()); - var output = MakeTagHelperOutput(" "); - - //Act - var helper = new ModalHeaderTagHelper(); - await helper.ProcessAsync(context, output); - - //Assert - Assert.Equal("modal-header", output.Attributes["class"].Value); - } - - [Fact] - public async Task Should_Render_With_ClassAdded_PreservingCustomClasses() - { - //Arrange - var customClass = "testing-out"; - var expectedClass = $"{customClass} modal-header"; - var existingAttributes = new TagHelperAttributeList(new List - {new("class", customClass)}); - var context = MakeTagHelperContext(); - context.Items.Add(typeof(ModalContext), new ModalContext()); - var output = MakeTagHelperOutput(" ", existingAttributes); - - //Act - var helper = new ModalHeaderTagHelper(); - await helper.ProcessAsync(context, output); - - //Assert - Assert.Equal(expectedClass, output.Attributes["class"].Value.ToString()); - } + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(ModalContext), new ModalContext()); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalHeaderTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal("modal-header", output.Attributes["class"].Value); + } + + [Fact] + public async Task Should_Render_With_ClassAdded_PreservingCustomClasses() + { + //Arrange + var customClass = "testing-out"; + var expectedClass = $"{customClass} modal-header"; + var existingAttributes = new TagHelperAttributeList(new List + {new("class", customClass)}); + var context = MakeTagHelperContext(); + context.Items.Add(typeof(ModalContext), new ModalContext()); + var output = MakeTagHelperOutput(" ", existingAttributes); + + //Act + var helper = new ModalHeaderTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal(expectedClass, output.Attributes["class"].Value.ToString()); + } + + [Fact] + public async Task Should_NotRender_InnerContent_When_Title_Missing() + { + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(ModalContext), new ModalContext()); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalHeaderTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal("", output.Content.GetContent()); + } + + [Theory] + [InlineData("My Title", "", "
My Title
")] + [InlineData("My Title", "myModal", "
My Title
")] + public async Task Should_Render_InnerContent_Title_When_Title_Provided(string title, string id, string expectedHtml) + { + //Arrange + var context = MakeTagHelperContext(); + context.Items.Add(typeof(ModalContext), new ModalContext{Id = id}); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalHeaderTagHelper{Title = title}; + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal(expectedHtml, output.Content.GetContent()); } -} +} \ No newline at end of file diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalTagHelperTests.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalTagHelperTests.cs new file mode 100644 index 0000000..8f95fdd --- /dev/null +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers.Tests/Modal/ModalTagHelperTests.cs @@ -0,0 +1,160 @@ +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Contexts; +using ICG.AspNetCore.Utilities.BootstrapTagHelpers.Modal; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Xunit; + +namespace ICG.AspNetCore.Utilities.BootstrapTagHelpers.Tests.Modal; + +public class ModalTagHelperTests : AbstractTagHelperTest +{ + [Fact] + public async Task Should_Not_Error_With_Missing_Id_Attribute() + { + //Arrange + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalTagHelper(); + var exception = await Record.ExceptionAsync(() => helper.ProcessAsync(context, output)); + + //Assert + Assert.Null(exception); + } + + [Fact] + public async Task Should_Add_Context_Object_With_Provided_Id() + { + //Arrange + var context = MakeTagHelperContext(); + var providedId = "testingModal"; + var existingAttributes = new TagHelperAttributeList(new List + {new("id", providedId)}); + var output = MakeTagHelperOutput(" ", existingAttributes); + + //Act + var helper = new ModalTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + var generatedContext = Assert.IsType(context.Items[typeof(ModalContext)]); + Assert.Equal(providedId, generatedContext.Id); + } + + [Fact] + public async Task Should_Render_As_Div() + { + //Arrange + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal("div", output.TagName); + } + + [Fact] + public async Task Should_Render_With_ClassAdded() + { + //Arrange + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal("modal fade", output.Attributes["class"].Value.ToString()); + } + + [Fact] + public async Task Should_Render_With_ClassAdded_PreservingCustomClasses() + { + //Arrange + var customClass = "testing-out"; + var expectedClass = $"{customClass} modal fade"; + var existingAttributes = new TagHelperAttributeList(new List + {new("class", customClass)}); + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" ", existingAttributes); + + //Act + var helper = new ModalTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal(expectedClass, output.Attributes["class"].Value.ToString()); + } + + [Theory] + [InlineData("", false, "")] + [InlineData("testing", true, "testingLabel")] + public async Task Should_Render_With_Aria_LabelledBy_When_Id_Provided(string providedId, bool expectedAttribute, + string expectedAttributeValue) + { + //Arrange + var context = MakeTagHelperContext(); + var existingAttributes = new TagHelperAttributeList(new List + {new("id", providedId)}); + var output = MakeTagHelperOutput(" ", existingAttributes); + + //Act + var helper = new ModalTagHelper(); + await helper.ProcessAsync(context, output); + + //Assert + if (expectedAttribute) + { + Assert.Equal(expectedAttributeValue, output.Attributes["aria-labelledby"].Value.ToString()); + } + else + { + Assert.Null(output.Attributes["aria-labelledby"]); + } + } + + [Theory] + [InlineData(true, "static")] + [InlineData(false, "")] + public async Task Should_Render_Static_Backdrop_Attribute_When_Flagged(bool staticBackdrop, + string expectedAttributeValue) + { + //Arrange + var attributeName = "data-backdrop"; + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" "); + + //Act + var helper = new ModalTagHelper{StaticBackdrop = staticBackdrop}; + await helper.ProcessAsync(context, output); + + //Assert + if(staticBackdrop) + Assert.Equal(expectedAttributeValue, output.Attributes[attributeName].Value.ToString()); + else + Assert.Null(output.Attributes[attributeName]); + } + + [Fact] + public async Task Should_Render_Proper_InnerHtmlStructure_WithNoChildContent() + { + var context = MakeTagHelperContext(); + var output = MakeTagHelperOutput(" "); + var expectedContent = "
"; + + //Act + var helper = new ModalTagHelper { }; + await helper.ProcessAsync(context, output); + + //Assert + Assert.Equal(expectedContent, output.Content.GetContent()); + } +} \ No newline at end of file diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs index 6ddf047..2e4ad8a 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs @@ -63,7 +63,6 @@ public override void Process(TagHelperContext context, TagHelperOutput output) new { @class = "text-danger" }); output.PostElement.AppendHtml(validationMsg); - //Close wrapping div output.PostElement.AppendHtml(""); } diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalTagHelper.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalTagHelper.cs index bdeca87..3be8b91 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalTagHelper.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers/Modal/ModalTagHelper.cs @@ -26,12 +26,28 @@ public class ModalTagHelper : TagHelper /// public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { - var id = output.Attributes["id"].Value.ToString(); + //Obtain the id value to add to the context + var id = ""; + if (output.Attributes.ContainsName("id")) + id = output.Attributes["id"].Value.ToString(); + + //Add the id to the context + var modalContext = new ModalContext { Id = id }; + context.Items[typeof(ModalContext)] = modalContext; + + //Get our child content before we mess with anything + var body = (await output.GetChildContentAsync()).GetContent(); + body = body.Trim(); + output.TagName = "div"; + //Add classes to the existing tag, merging with custom ones added output.AddClass("modal", HtmlEncoder.Default); output.AddClass("fade", HtmlEncoder.Default); - output.Attributes.Add("aria-labelledby", $"{id}Label"); + + if(!string.IsNullOrEmpty(id)) + output.Attributes.Add("aria-labelledby", $"{id}Label"); + if (StaticBackdrop) output.Attributes.Add("data-backdrop", "static"); @@ -39,15 +55,8 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu dialogWrapper.AddCssClass("modal-dialog"); var dialogContent = new TagBuilder("div"); dialogContent.AddCssClass("modal-content"); - dialogWrapper.InnerHtml.AppendHtml(dialogContent); - - //Setup context - var modalContext = new ModalContext {Id = id}; - context.Items[typeof(ModalContext)] = modalContext; - - //Render children now - var body = (await output.GetChildContentAsync()).GetContent(); dialogContent.InnerHtml.AppendHtml(body); + dialogWrapper.InnerHtml.AppendHtml(dialogContent); output.Content.AppendHtml(dialogWrapper); } From 5d0e55c3f986e233023127db01d5c3fef40eeec4 Mon Sep 17 00:00:00 2001 From: Mitchel Sellers Date: Sun, 10 Apr 2022 00:55:39 -0500 Subject: [PATCH 3/3] Code coverage improvements --- .../Form/FormInputTagHelper.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs b/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs index 2e4ad8a..a1d04cc 100644 --- a/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs +++ b/src/AspNetCore.Utilities.BootstrapTagHelpers/Form/FormInputTagHelper.cs @@ -1,6 +1,5 @@ -using System.Text.Encodings.Web; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.Rendering; +using System.Diagnostics.CodeAnalysis; +using System.Text.Encodings.Web; using Microsoft.AspNetCore.Mvc.TagHelpers; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; @@ -11,11 +10,12 @@ namespace ICG.AspNetCore.Utilities.BootstrapTagHelpers.Form; /// TagHelper for rending Bootstrap form compliant input controls with support for ASP.NET Core model Binding. Will /// include Label, Field, and validation. /// +[ExcludeFromCodeCoverage] //Excluding from code coverage due to complexity [RestrictChildren("form-note")] public class FormInputTagHelper : InputTagHelper { private readonly IHtmlGenerator _generator; - + /// /// Public constructor that will receive the incoming generator to leverage existing Microsoft Tag Helpers /// @@ -49,9 +49,9 @@ public override void Process(TagHelperContext context, TagHelperOutput output) ViewContext, For.ModelExplorer, For.Name, null, - new { @class = "control-label" }); + new {@class = "control-label"}); output.PreElement.AppendHtml(label); - + //Now, add validation message AFTER the field var validationMsg = _generator.GenerateValidationMessage( @@ -60,9 +60,9 @@ public override void Process(TagHelperContext context, TagHelperOutput output) For.Name, null, ViewContext.ValidationMessageElement, - new { @class = "text-danger" }); + new {@class = "text-danger"}); output.PostElement.AppendHtml(validationMsg); - + //Close wrapping div output.PostElement.AppendHtml(""); }