From 8a668eb9d1d550e627f38aec9699ceccc9a247a1 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 17 Nov 2014 11:27:16 -0800 Subject: [PATCH] Adding unit tests for HtmlHelper.Password Partial fix for #453 --- .../Rendering/HtmlHelperPasswordTest.cs | 386 ++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperPasswordTest.cs diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperPasswordTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperPasswordTest.cs new file mode 100644 index 0000000000..1d76883ec2 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperPasswordTest.cs @@ -0,0 +1,386 @@ +// 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; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Globalization; +using System.Linq.Expressions; +using Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Testing; +using Xunit; + +namespace Microsoft.AspNet.Mvc.Rendering +{ + public class HtmlHelperPasswordTest + { + public static IEnumerable PasswordWithViewDataAndAttributesData + { + get + { + var attributes1 = new Dictionary + { + { "test-key", "test-value" }, + { "value", "attribute-value" } + }; + + var attributes2 = new { test_key = "test-value", value = "attribute-value" }; + + var vdd = GetViewDataWithModelStateAndModelAndViewDataValues(); + vdd.Model.Property1 = "does-not-get-used"; + yield return new object[] { vdd, attributes1 }; + yield return new object[] { vdd, attributes2 }; + + var nullModelVdd = GetViewDataWithNullModelAndNonEmptyViewData(); + yield return new object[] { nullModelVdd, attributes1 }; + yield return new object[] { nullModelVdd, attributes2 }; + } + } + + [Theory] + [MemberData(nameof(PasswordWithViewDataAndAttributesData))] + public void Password_UsesAttributeValueWhenValueArgumentIsNull(ViewDataDictionary vdd, + object attributes) + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(vdd); + + // Act + var result = helper.Password("Property1", value: null, htmlAttributes: attributes); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Theory] + [MemberData(nameof(PasswordWithViewDataAndAttributesData))] + public void Password_UsesExplicitValue_IfSpecified(ViewDataDictionary vdd, + object attributes) + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(vdd); + + // Act + var result = helper.Password("Property1", "explicit-value", attributes); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordWithPrefix_GeneratesExpectedValue() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + + // Act + var result = helper.Password("Property1", "explicit-value", htmlAttributes: null); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordWithPrefix_UsesIdDotReplacementToken() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + helper.IdAttributeDotReplacement = "$"; + + // Act + var result = helper.Password("Property1", "explicit-value", htmlAttributes: null); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordWithPrefixAndEmptyName_GeneratesExpectedValue() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + var name = string.Empty; + + // Act + var result = helper.Password(name, "explicit-value", htmlAttributes: null); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordWithEmptyNameAndPrefixThrows() + { + // Arrange + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); + var name = string.Empty; + var value = string.Empty; + + // Act and Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty(() => helper.Password(name, value, htmlAttributes: null), + "name"); + } + + [Fact] + public void Password_UsesModelStateErrors_ButDoesNotUseModelOrViewDataOrModelStateForValueAttribute() + { + // Arrange + var expected = @""; + var vdd = GetViewDataWithErrors(); + vdd.Model.Property1 = "property-value"; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(vdd); + var attributes = new Dictionary + { + { "test-key", "test-value" }, + { "class", "some-class"} + }; + + // Act + var result = helper.Password("Property1", value: null, htmlAttributes: attributes); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordGeneratesUnobtrusiveValidation() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); + + // Act + var result = helper.Password("Property2", value: null, htmlAttributes: null); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + public static IEnumerable PasswordWithComplexExpressions_UsesIdDotSeparatorData + { + get + { + yield return new object[] + { + "Property4.Property5", + @"", + }; + + yield return new object[] + { + "Property4.Property6[0]", + @"", + }; + } + } + + [Theory] + [MemberData(nameof(PasswordWithComplexExpressions_UsesIdDotSeparatorData))] + public void PasswordWithComplexExpressions_UsesIdDotSeparator(string expression, string expected) + { + // Arrange + var viewData = GetViewDataWithModelStateAndModelAndViewDataValues(); + var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); + helper.IdAttributeDotReplacement = "$$"; + var attributes = new Dictionary { { "data-test", "val" } }; + + // Act + var result = helper.Password(expression, value: null, htmlAttributes: attributes); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Theory] + [MemberData(nameof(PasswordWithViewDataAndAttributesData))] + public void PasswordForWithAttributes_GeneratesExpectedValue(ViewDataDictionary vdd, + object htmlAttributes) + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); + helper.ViewData.Model.Property1 = "test"; + + // Act + var result = helper.PasswordFor(m => m.Property1, htmlAttributes); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordForWithPrefix_GeneratesExpectedValue() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithModelStateAndModelAndViewDataValues()); + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + + // Act + var result = helper.PasswordFor(m => m.Property1, htmlAttributes: null); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordFor_UsesModelStateErrors_ButDoesNotUseModelOrViewDataOrModelStateForValueAttribute() + { + // Arrange + var expected = @""; + var vdd = GetViewDataWithErrors(); + vdd.Model.Property1 = "prop1-value"; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(vdd); + var attributes = new Dictionary + { + { "baz", "BazValue" }, + { "class", "some-class"} + }; + + // Act + var result = helper.PasswordFor(m => m.Property1, attributes); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + [Fact] + public void PasswordFor_GeneratesUnobtrusiveValidationAttributes() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetViewDataWithErrors()); + + // Act + var result = helper.PasswordFor(m => m.Property2, htmlAttributes: null); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + public static TheoryData PasswordFor_WithComplexExpressionsData + { + get + { + return new TheoryData>, string> + { + { + model => model.Property3["key"], + @"" + }, + { + model => model.Property4.Property5, + @"" + }, + { + model => model.Property4.Property6[0], + @"" + } + }; + } + } + + [Theory] + [MemberData(nameof(PasswordFor_WithComplexExpressionsData))] + public void PasswordFor_WithComplexExpressionsAndFieldPrefix_UsesAttributeValueIfSpecified( + Expression> expression, + string expected) + { + // Arrange + var viewData = GetViewDataWithModelStateAndModelAndViewDataValues(); + viewData.ModelState.Add("pre.Property3[key]", GetModelState("Property3Val")); + viewData.ModelState.Add("pre.Property4.Property5", GetModelState("Property5Val")); + viewData.ModelState.Add("pre.Property4.Property6[0]", GetModelState("Property6Val")); + viewData["pre.Property3[key]"] = "vdd-value1"; + viewData["pre.Property4.Property5"] = "vdd-value2"; + viewData["pre.Property4.Property6[0]"] = "vdd-value3"; + viewData.Model.Property3["key"] = "prop-value1"; + viewData.Model.Property4.Property5 = "prop-value2"; + viewData.Model.Property4.Property6.Add("prop-value3"); + + var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); + viewData.TemplateInfo.HtmlFieldPrefix = "pre"; + var attributes = new { data_val = "true", value = "attr-value" }; + + // Act + var result = helper.PasswordFor(expression, attributes); + + // Assert + Assert.Equal(expected, result.ToString()); + } + + private static ViewDataDictionary GetViewDataWithNullModelAndNonEmptyViewData() + { + return new ViewDataDictionary(new EmptyModelMetadataProvider()) + { + ["Property1"] = "view-data-val", + }; + } + + private static ViewDataDictionary GetViewDataWithModelStateAndModelAndViewDataValues() + { + var viewData = GetViewDataWithNullModelAndNonEmptyViewData(); + viewData.Model = new PasswordModel(); + viewData.ModelState.Add("Property1", GetModelState("ModelStateValue")); + + return viewData; + } + + private static ViewDataDictionary GetViewDataWithErrors() + { + var viewData = GetViewDataWithModelStateAndModelAndViewDataValues(); + viewData.ModelState.AddModelError("Property1", "error 1"); + viewData.ModelState.AddModelError("Property1", "error 2"); + return viewData; + } + + private static ModelState GetModelState(string value) + { + return new ModelState + { + Value = new ValueProviderResult(value, value, CultureInfo.InvariantCulture) + }; + } + + public class PasswordModel + { + public string Property1 { get; set; } + + [Required] + public string Property2 { get; set; } + + public Dictionary Property3 { get; } = new Dictionary(); + + public NestedClass Property4 { get; } = new NestedClass(); + } + + public class NestedClass + { + public string Property5 { get; set; } + + public List Property6 { get; } = new List(); + } + } +} \ No newline at end of file