diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultTemplatesUtilities.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultTemplatesUtilities.cs index 05443e1585..baf673d303 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultTemplatesUtilities.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/DefaultTemplatesUtilities.cs @@ -55,6 +55,15 @@ namespace Microsoft.AspNet.Mvc.Rendering provider: CreateModelMetadataProvider()); } + public static HtmlHelper GetHtmlHelperForViewData(ViewDataDictionary viewData) + { + return GetHtmlHelper(viewData, + CreateUrlHelper(), + CreateViewEngine(), + CreateModelMetadataProvider(), + innerHelperWrapper: null); + } + public static HtmlHelper GetHtmlHelper(TModel model) { return GetHtmlHelper(model, CreateViewEngine()); @@ -107,6 +116,16 @@ namespace Microsoft.AspNet.Mvc.Rendering var viewData = new ViewDataDictionary(provider); viewData.Model = model; + return GetHtmlHelper(viewData, urlHelper, viewEngine, provider, innerHelperWrapper); + } + + private static HtmlHelper GetHtmlHelper( + ViewDataDictionary viewData, + IUrlHelper urlHelper, + ICompositeViewEngine viewEngine, + IModelMetadataProvider provider, + Func innerHelperWrapper) + { var httpContext = new Mock(); httpContext .Setup(o => o.Response) @@ -124,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.Rendering Mock.Of(), Mock.Of(), Mock.Of(), - Mock.Of()); + new DataAnnotationsModelValidatorProvider()); var actionBindingContextProvider = new Mock(); actionBindingContextProvider .Setup(c => c.GetActionBindingContextAsync(It.IsAny())) diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperInputTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperInputTest.cs new file mode 100644 index 0000000000..0e4fa572b9 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperInputTest.cs @@ -0,0 +1,396 @@ +// 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 Microsoft.AspNet.Mvc.ModelBinding; +using Microsoft.AspNet.Routing; +using Xunit; + +namespace Microsoft.AspNet.Mvc.Rendering +{ + public class HtmlHelperInputTest + { + // CheckBox + + [Fact] + public void CheckBoxOverridesCalculatedValuesWithValuesFromHtmlAttributes() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + + // Act + var html = helper.CheckBox("Property3", + isChecked: null, + htmlAttributes: new { @checked = "checked", value = "false" }); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxExplicitParametersOverrideDictionary_ForValueInModel() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + + // Act + var html = helper.CheckBox("Property3", + isChecked: true, + htmlAttributes: new { @checked = "unchecked", value = "false" }); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxExplicitParametersOverrideDictionary_ForNullModel() + { + // Arrange + var expected = @"" + + @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(); + + // Act + var html = helper.CheckBox("foo", + isChecked: true, + htmlAttributes: new { @checked = "unchecked", value = "false" }); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxWithInvalidBooleanThrows() + { + // Arrange + var expected = "String was not recognized as a valid Boolean."; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + + // Act & Assert + var ex = Assert.Throws( + () => helper.CheckBox("Property2", isChecked: null, htmlAttributes: null)); + Assert.Equal(expected, ex.Message); + } + + [Fact] + public void CheckBoxCheckedWithOnlyName() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + + // Act + var html = helper.CheckBox("Property1", isChecked: true, htmlAttributes: null); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxUsesAttemptedValueFromModelState() + { + // Arrange + var expected = @"" + + @""; + var valueProviderResult = new ValueProviderResult("false", "false", CultureInfo.InvariantCulture); + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + helper.ViewData.ModelState.SetModelValue("Property1", valueProviderResult); + + // Act + var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxGeneratesUnobtrusiveValidationAttributes() + { + // Arrange + var expected = @"" + + @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetModelWithValidationViewData()); + + // Act + var html = helper.CheckBox("Name", isChecked: null, htmlAttributes: null); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxReplacesUnderscoresInHtmlAttributesWithDashes() + { + // Arrange + var expected = @"" + + @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData()); + var htmlAttributes = new { Property1_Property3 = "Property3ObjValue" }; + + // Act + var html = helper.CheckBox("Property1", isChecked: true, htmlAttributes: htmlAttributes); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxWithPrefix_ReplaceDotsInIdByDefaultWithUnderscores() + { + // Arrange + var expected = @""; + var dictionary = new RouteValueDictionary(new { Property3 = "Property3Value" }); + var helper = DefaultTemplatesUtilities.GetHtmlHelper(); + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + + // Act + var html = helper.CheckBox("Property1", isChecked: false, htmlAttributes: dictionary); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxWithPrefix_ReplacesDotsInIdWithIdDotReplacement() + { + // Arrange + var expected = @""; + var dictionary = new Dictionary { { "Property3", "Property3Value" } }; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(); + helper.IdAttributeDotReplacement = "!!!"; + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + + // Act + var html = helper.CheckBox("Property1", isChecked: false, htmlAttributes: dictionary); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxWithPrefixAndEmptyName() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelper(model: false); + var attributes = new Dictionary { { "Property3", "Property3Value" } }; + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + + // Act + var html = helper.CheckBox(string.Empty, isChecked: false, htmlAttributes: attributes); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxWithComplexExpressionsEvaluatesValuesInViewDataDictionary() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetModelWithValidationViewData()); + + // Act + var html = helper.CheckBox("ComplexProperty.Property1", isChecked: null, htmlAttributes: null); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + //// CheckBoxFor + + [Fact] + public void CheckBoxForWithInvalidBooleanThrows() + { + // Arrange + var expected = "String was not recognized as a valid Boolean."; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + + // Act & Assert + // "Property2" in ViewData isn't a valid boolean + var ex = Assert.Throws(() => helper.CheckBoxFor(m => m.Property2)); + Assert.Equal(expected, ex.Message); + } + + [Fact] + public void CheckBoxForOverridesCalculatedParametersWithValuesFromHtmlAttributes() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + + // Act + var html = helper.CheckBoxFor(m => m.Property3, new { @checked = "checked", value = "false" }); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxForGeneratesUnobtrusiveValidationAttributes() + { + // Arrange + var expected = @"" + + @""; + var metadataProvider = new DataAnnotationsModelMetadataProvider(); + var viewDataDictionary = new ViewDataDictionary(metadataProvider) + { + Model = new ModelWithValidation() + }; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(viewDataDictionary); + + // Act + var html = helper.CheckBoxFor(m => m.Name, htmlAttributes: null); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxForUsesModelStateAttemptedValue() + { + // Arrange + var expected = @"" + + @""; + var viewData = GetTestModelViewData(); + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(viewData); + var valueProviderResult = new ValueProviderResult("false", "false", CultureInfo.InvariantCulture); + viewData.ModelState.SetModelValue("Property1", valueProviderResult); + + // Act + var html = helper.CheckBoxFor(m => m.Property1); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxForWithObjectAttributeWithUnderscores() + { + // Arrange + var expected = @"" + + @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + var htmlAttributes = new { Property1_Property3 = "Property3ObjValue" }; + + // Act + var html = helper.CheckBoxFor(m => m.Property1, htmlAttributes); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxForWithAttributeDictionary() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + var attributes = new Dictionary { { "Property3", "Property3Value" } }; + + // Act + var html = helper.CheckBoxFor(m => m.Property1, attributes); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckBoxForWithPrefix() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetTestModelViewData()); + helper.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "MyPrefix"; + var attributes = new Dictionary { { "Property3", "PropValue" } }; + + // Act + var html = helper.CheckBoxFor(m => m.Property1, attributes); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + [Fact] + public void CheckboxForWithComplexExpressionsUsesValuesFromViewDataDictionary() + { + // Arrange + var expected = @""; + var helper = DefaultTemplatesUtilities.GetHtmlHelperForViewData(GetModelWithValidationViewData()); + + // Act + var html = helper.CheckBoxFor(m => m.ComplexProperty.Property1, htmlAttributes: null); + + // Assert + Assert.Equal(expected, html.ToString()); + } + + private static ViewDataDictionary GetTestModelViewData() + { + return new ViewDataDictionary(new EmptyModelMetadataProvider()) + { + { "Property1", true }, + { "Property2", "NotTrue" }, + { "Property3", false } + }; + } + + private static ViewDataDictionary GetModelWithValidationViewData() + { + var provider = new DataAnnotationsModelMetadataProvider(); + var viewData = new ViewDataDictionary(provider) + { + { "ComplexProperty.Property1", true }, + { "ComplexProperty.Property2", "NotTrue" }, + { "ComplexProperty.Property3", false } + }; + viewData.Model = new ModelWithValidation(); + + return viewData; + } + + private class TestModel + { + public bool Property1 { get; set; } + + public bool Property2 { get; set; } + + public bool Property3 { get; set; } + } + + private class ModelWithValidation + { + [Required] + public bool Name { get; set; } + + public TestModel ComplexProperty { get; set; } + } + } +} \ No newline at end of file