From 3ced6016a1bff14188ea8a8ae09c65dfc6279ae3 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Wed, 11 Feb 2015 08:19:32 -0800 Subject: [PATCH] Deep copy user's select list before making changes - #524 - add tests of `DropDownList` and `ListBox` HTML helpers - extend tests of `" + + Environment.NewLine + + "" + Environment.NewLine + + "" + Environment.NewLine + + "" + Environment.NewLine + + "", + "" + }, + { + SomeDisabledOneSelectedSelectList, + "", + "" + }, + { + SomeGroupedSomeSelectedSelectList, + "", + "" + }, + { + OneGroupSomeSelectedSelectList, + "", + "" + }, + { + OneDisabledGroupAllSelectedSelectList, + "", + "" + }, + }; + } + } + + // Select list -> expected HTML with null model, with model containing "2", and with model containing "1", "3". + public static TheoryData, string, string, string> ListBoxDataSet + { + get + { + return new TheoryData, string, string, string> + { + { + BasicSelectList, + "", + "", + "" + }, + { + SomeDisabledOneSelectedSelectList, + "", + "", + "" + }, + { + SomeGroupedSomeSelectedSelectList, + "", + "", + "" + }, + { + OneGroupSomeSelectedSelectList, + "", + "", + "" + }, + { + OneDisabledGroupAllSelectedSelectList, + "", + "", + "" + }, + }; + } + } + + [Theory] + [MemberData(nameof(DropDownListDataSet))] + public void DropDownList_WithNullModel_GeneratesExpectedValue_DoesNotChangeSelectList( + IEnumerable selectList, + string expectedHtml, + string ignoredHtml) + { + // Arrange + var helper = DefaultTemplatesUtilities.GetHtmlHelper(); + var savedDisabled = selectList.Select(item => item.Disabled).ToList(); + var savedGroup = selectList.Select(item => item.Group).ToList(); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + var savedText = selectList.Select(item => item.Text).ToList(); + var savedValue = selectList.Select(item => item.Value).ToList(); + + // Act + var html = helper.DropDownList("Property1", selectList, optionLabel: null, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedDisabled, selectList.Select(item => item.Disabled)); + Assert.Equal(savedGroup, selectList.Select(item => item.Group)); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + Assert.Equal(savedText, selectList.Select(item => item.Text)); + Assert.Equal(savedValue, selectList.Select(item => item.Value)); + } + + [Theory] + [MemberData(nameof(DropDownListDataSet))] + public void DropDownList_WithModelValue_GeneratesExpectedValue( + IEnumerable selectList, + string ignoredHtml, + string expectedHtml) + { + // Arrange + var model = new DefaultTemplatesUtilities.ObjectTemplateModel { Property1 = "2" }; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.DropDownList("Property1", selectList, optionLabel: null, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + [Theory] + [MemberData(nameof(DropDownListDataSet))] + public void DropDownListFor_WithNullModel_GeneratesExpectedValue( + IEnumerable selectList, + string expectedHtml, + string ignoredHtml) + { + // Arrange + var helper = DefaultTemplatesUtilities.GetHtmlHelper(); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.DropDownListFor( + value => value.Property1, + selectList, + optionLabel: null, + htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + [Theory] + [MemberData(nameof(DropDownListDataSet))] + public void DropDownListFor_WithModelValue_GeneratesExpectedValue( + IEnumerable selectList, + string ignoredHtml, + string expectedHtml) + { + // Arrange + var model = new DefaultTemplatesUtilities.ObjectTemplateModel { Property1 = "2" }; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.DropDownListFor( + value => value.Property1, + selectList, + optionLabel: null, + htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + [Theory] + [MemberData(nameof(ListBoxDataSet))] + public void ListBox_WithNullModel_GeneratesExpectedValue_DoesNotChangeSelectList( + IEnumerable selectList, + string expectedHtml, + string ignoredHtml1, + string ignoredHtml2) + { + // Arrange + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: null); + var savedDisabled = selectList.Select(item => item.Disabled).ToList(); + var savedGroup = selectList.Select(item => item.Group).ToList(); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + var savedText = selectList.Select(item => item.Text).ToList(); + var savedValue = selectList.Select(item => item.Value).ToList(); + + // Act + var html = helper.ListBox("Property1", selectList, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedDisabled, selectList.Select(item => item.Disabled)); + Assert.Equal(savedGroup, selectList.Select(item => item.Group)); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + Assert.Equal(savedText, selectList.Select(item => item.Text)); + Assert.Equal(savedValue, selectList.Select(item => item.Value)); + } + + [Theory] + [MemberData(nameof(ListBoxDataSet))] + public void ListBox_WithModelValue_GeneratesExpectedValue( + IEnumerable selectList, + string ignoredHtml1, + string expectedHtml, + string ignoredHtml2) + { + // Arrange + var model = new ModelContainingList { Property1 = { "2" } }; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.ListBox("Property1", selectList, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + [Theory] + [MemberData(nameof(ListBoxDataSet))] + public void ListBox_WithMultipleModelValues_GeneratesExpectedValue( + IEnumerable selectList, + string ignoredHtml1, + string ignoredHtml2, + string expectedHtml) + { + // Arrange + var model = new ModelContainingList { Property1 = { "1", "3" } }; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.ListBox("Property1", selectList, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + [Theory] + [MemberData(nameof(ListBoxDataSet))] + public void ListBoxFor_WithNullModel_GeneratesExpectedValue( + IEnumerable selectList, + string expectedHtml, + string ignoredHtml1, + string ignoredHtml2) + { + // Arrange + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: null); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.ListBoxFor(value => value.Property1, selectList, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + [Theory] + [MemberData(nameof(ListBoxDataSet))] + public void ListBoxFor_WithModelValue_GeneratesExpectedValue( + IEnumerable selectList, + string ignoredHtml1, + string expectedHtml, + string ignoredHtml2) + { + // Arrange + var model = new ModelContainingList { Property1 = { "2" } }; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.ListBoxFor(value => value.Property1, selectList, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + [Theory] + [MemberData(nameof(ListBoxDataSet))] + public void ListBoxFor_WithMultipleModelValues_GeneratesExpectedValue( + IEnumerable selectList, + string ignoredHtml1, + string ignoredHtml2, + string expectedHtml) + { + // Arrange + var model = new ModelContainingList { Property1 = { "1", "3" } }; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model); + var savedSelected = selectList.Select(item => item.Selected).ToList(); + + // Act + var html = helper.ListBoxFor(value => value.Property1, selectList, htmlAttributes: null); + + // Assert + Assert.Equal(expectedHtml, html.ToString()); + Assert.Equal(savedSelected, selectList.Select(item => item.Selected)); + } + + private class ModelContainingList + { + public List Property1 { get; } = new List(); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html index a9e3d25b38..6f80cb84a0 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html @@ -19,7 +19,15 @@
- + + + +
+
+ + + diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.OrderUsingHtmlHelpers.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.OrderUsingHtmlHelpers.html index f617c0eb65..550a5fb8a7 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.OrderUsingHtmlHelpers.html +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.OrderUsingHtmlHelpers.html @@ -19,7 +19,15 @@
- + + + +
+
+ + + diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs index cb14e38953..fd380a81e2 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs @@ -243,7 +243,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers [Theory] [MemberData(nameof(GeneratesExpectedDataSet))] - public async Task ProcessAsync_GeneratesExpectedOutput_WithItems( + public async Task ProcessAsync_WithItems_GeneratesExpectedOutput_DoesNotChangeSelectList( object model, Type containerType, Func modelAccessor, @@ -286,7 +286,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers SelfClosing = true, }; - var items = new SelectList(new[] { "", "outer text", "inner text", "other text" }); var htmlGenerator = new TestableHtmlGenerator(metadataProvider) { ValidationAttributes = @@ -295,6 +294,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers } }; var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); + + var items = new SelectList(new[] { "", "outer text", "inner text", "other text" }); + var savedDisabled = items.Select(item => item.Disabled).ToList(); + var savedGroup = items.Select(item => item.Group).ToList(); + var savedSelected = items.Select(item => item.Selected).ToList(); + var savedText = items.Select(item => item.Text).ToList(); + var savedValue = items.Select(item => item.Value).ToList(); var tagHelper = new SelectTagHelper { For = modelExpression, @@ -321,6 +327,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers Assert.NotNull(keyValuePair.Value); var selectedValues = Assert.IsAssignableFrom>(keyValuePair.Value); Assert.InRange(selectedValues.Count, 0, 1); + + Assert.Equal(savedDisabled, items.Select(item => item.Disabled)); + Assert.Equal(savedGroup, items.Select(item => item.Group)); + Assert.Equal(savedSelected, items.Select(item => item.Selected)); + Assert.Equal(savedText, items.Select(item => item.Text)); + Assert.Equal(savedValue, items.Select(item => item.Value)); } [Theory] diff --git a/test/WebSites/MvcTagHelpersWebSite/Controllers/MvcTagHelper_HomeController.cs b/test/WebSites/MvcTagHelpersWebSite/Controllers/MvcTagHelper_HomeController.cs index 5025db10aa..391e29270f 100644 --- a/test/WebSites/MvcTagHelpersWebSite/Controllers/MvcTagHelper_HomeController.cs +++ b/test/WebSites/MvcTagHelpersWebSite/Controllers/MvcTagHelper_HomeController.cs @@ -45,6 +45,7 @@ namespace MvcTagHelpersWebSite.Controllers }, NeedSpecialHandle = true, PaymentMethod = new List { "Check" }, + Products = new List { 0, 1 }, }; public MvcTagHelper_HomeController() diff --git a/test/WebSites/MvcTagHelpersWebSite/Models/Order.cs b/test/WebSites/MvcTagHelpersWebSite/Models/Order.cs index 67c17dad60..d0f348aa2b 100644 --- a/test/WebSites/MvcTagHelpersWebSite/Models/Order.cs +++ b/test/WebSites/MvcTagHelpersWebSite/Models/Order.cs @@ -44,6 +44,12 @@ namespace MvcTagHelpersWebSite.Models set; } + public IEnumerable SubstituteProducts + { + get; + set; + } + public Customer Customer { get; diff --git a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml index a380d5d4e4..dbf3daf534 100644 --- a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml +++ b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml @@ -32,6 +32,11 @@ @{ var @object = "multiple"; } +
+
+ @Html.LabelFor(m => m.SubstituteProducts, htmlAttributes: new { @class = "order" }) + @* Use same select list as Products. Selection when Products is non-null is not used here. *@ + @Html.ListBoxFor(m => m.SubstituteProducts, productSelectList) +
@Html.LabelFor(m => m.OrderDate, htmlAttributes: new { @class = "order" }) @Html.TextBoxFor(m => m.OrderDate, format: "{0:yyyy/MM/dd/ g}", htmlAttributes: new { type = "datetime" })