[Fixes #453] Added unit tests for Display and Value Extensions

- Added more HtmlHelper tests
- Added some tests to cover complex expressions
This commit is contained in:
Ajay Bhargav Baaskaran 2016-06-29 15:02:41 -07:00
parent 7ce344270a
commit e7de647c10
6 changed files with 782 additions and 1 deletions

View File

@ -0,0 +1,360 @@
// Copyright (c) .NET Foundation. 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.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.TestCommon;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Rendering
{
public class HtmlHelperDisplayExtensionsTest
{
[Fact]
public void DisplayHelpers_FindsModel_WhenViewDataIsNotSet()
{
// Arrange
var expected = $"<div class=\"HtmlEncode[[display-label]]\">HtmlEncode[[SomeProperty]]</div>{Environment.NewLine}" +
$"<div class=\"HtmlEncode[[display-field]]\">HtmlEncode[[PropValue]]</div>{Environment.NewLine}";
var model = new SomeModel
{
SomeProperty = "PropValue"
};
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.Display(expression: string.Empty);
var displayNullResult = helper.Display(expression: null); // null is another alias for current model
var displayForResult = helper.DisplayFor(m => m);
var displayForModelResult = helper.DisplayForModel();
// Assert
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayResult));
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayNullResult));
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayForResult));
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayForModelResult));
}
[Fact]
public void Display_UsesAdditionalViewData()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.Display(expression: "SomeProperty", additionalViewData: new { SomeProperty = "ViewDataValue" });
// Assert
Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void Display_UsesTemplateName()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", Mock.Of<IView>()))
.Verifiable();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.Display(expression: "SomeProperty", templateName: "SomeTemplate");
// Assert
viewEngine.Verify();
}
[Fact]
public void Display_UsesTemplateNameAndAdditionalViewData()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.Display(
expression: "SomeProperty",
templateName: "SomeTemplate",
additionalViewData: new { SomeProperty = "ViewDataValue" });
// Assert
Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void Display_UsesTemplateNameAndHtmlFieldName()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.Display(
expression: "SomeProperty",
templateName: "SomeTemplate",
htmlFieldName: "SomeField");
// Assert
Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void DisplayFor_UsesAdditionalViewData()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayFor(expression: m => m.SomeProperty, additionalViewData: new { SomeProperty = "ViewDataValue" });
// Assert
Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void DisplayFor_UsesTemplateName()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", Mock.Of<IView>()))
.Verifiable();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayFor(expression: m => m.SomeProperty, templateName: "SomeTemplate");
// Assert
viewEngine.Verify();
}
[Fact]
public void DisplayFor_UsesTemplateNameAndAdditionalViewData()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayFor(
expression: m => m.SomeProperty,
templateName: "SomeTemplate",
additionalViewData: new { SomeProperty = "ViewDataValue" });
// Assert
Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void DisplayFor_UsesTemplateNameAndHtmlFieldName()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayFor(
expression: m => m.SomeProperty,
templateName: "SomeTemplate",
htmlFieldName: "SomeField");
// Assert
Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void DisplayForModel_UsesAdditionalViewData()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayForModel(additionalViewData: new { SomeProperty = "ViewDataValue" });
// Assert
Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void DisplayForModel_UsesTemplateName()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", Mock.Of<IView>()))
.Verifiable();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayForModel(templateName: "SomeTemplate");
// Assert
viewEngine.Verify();
}
[Fact]
public void DisplayForModel_UsesTemplateNameAndAdditionalViewData()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayForModel(
templateName: "SomeTemplate",
additionalViewData: new { SomeProperty = "ViewDataValue" });
// Assert
Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void DisplayForModel_UsesTemplateNameAndHtmlFieldName()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
.Returns(Task.FromResult(0));
var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
viewEngine
.Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
.Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
viewEngine
.Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayForModel(
templateName: "SomeTemplate",
htmlFieldName: "SomeField");
// Assert
Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
}
private class SomeModel
{
public string SomeProperty { get; set; }
}
}
}

View File

@ -439,6 +439,61 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
return viewData;
}
public static TheoryData PasswordFor_IgnoresExpressionValueForComplexExpressionsData
{
get
{
return new TheoryData<Expression<Func<PasswordModel, string>>, string>
{
{
model => model.Property3["key"],
@"<input id=""HtmlEncode[[pre_Property3_key_]]"" name=""HtmlEncode[[pre.Property3[key]]]"" " +
@"type=""HtmlEncode[[password]]"" />"
},
{
model => model.Property4.Property5,
@"<input id=""HtmlEncode[[pre_Property4_Property5]]"" name=""HtmlEncode[[pre.Property4.Property5]]"" " +
@"type=""HtmlEncode[[password]]"" />"
},
{
model => model.Property4.Property6[0],
@"<input id=""HtmlEncode[[pre_Property4_Property6_0_]]"" " +
@"name=""HtmlEncode[[pre.Property4.Property6[0]]]"" type=""HtmlEncode[[password]]"" />"
}
};
}
}
[Theory]
[MemberData(nameof(PasswordFor_IgnoresExpressionValueForComplexExpressionsData))]
public void PasswordFor_ComplexExpressions_IgnoresValueFromViewDataModelStateAndModel(
Expression<Func<PasswordModel, string>> expression,
string expected)
{
// Arrange
var model = new PasswordModel();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
helper.ViewData.ModelState.SetModelValue("pre.Property3[key]", "MProp3Val", "MProp3Val");
helper.ViewData.ModelState.SetModelValue("pre.Property4.Property5", "MProp5Val", "MProp5Val");
helper.ViewData.ModelState.SetModelValue("pre.Property4.Property6[0]", "MProp6Val", "MProp6Val");
helper.ViewData["pre.Property3[key]"] = "VDProp3Val";
helper.ViewData["pre.Property4.Property5"] = "VDProp5Val";
helper.ViewData["pre.Property4.Property6"] = "VDProp6Val";
helper.ViewData.Model.Property3["key"] = "Prop3Val";
helper.ViewData.Model.Property4.Property5 = "Prop5Val";
helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
// Act
var result = helper.PasswordFor(expression);
// Assert
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
}
public class PasswordModel
{
public string Property1 { get; set; }

View File

@ -286,6 +286,53 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
Assert.Equal(expectedString, result.ToString());
}
[Theory]
[InlineData("SomeName", "SomeName")]
[InlineData("Obj1.Prop1", "Obj1_Prop1")]
[InlineData("Obj1.Prop1[0]", "Obj1_Prop1_0_")]
[InlineData("Obj1.Prop1[0].Prop2", "Obj1_Prop1_0__Prop2")]
public void GenerateIdFromName_ReturnsExpectedValues(string fullname, string expected)
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var result = helper.GenerateIdFromName(fullname);
// Assert
Assert.Equal(expected, result);
}
[Theory]
[InlineData(FormMethod.Get, "get")]
[InlineData(FormMethod.Post, "post")]
[InlineData((FormMethod)42, "post")]
public void GetFormMethodString_ReturnsExpectedValues(FormMethod method, string expected)
{
// Act
var result = HtmlHelper.GetFormMethodString(method);
// Assert
Assert.Equal(expected, result);
}
[Theory]
[InlineData("-{0}-", "-<b>boldFromObject</b>-")]
[InlineData("-%{0}%-", "-%<b>boldFromObject</b>%-")]
[InlineData("-=={0}=={0}==-", "-==<b>boldFromObject</b>==<b>boldFromObject</b>==-")]
public void FormatValue_ReturnsExpectedValues(string format, string expected)
{
// Arrange
var value = new ObjectWithToStringOverride();
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var result = helper.FormatValue(value, format);
// Assert
Assert.Equal(expected, result);
}
private class ObjectWithToStringOverride
{
public override string ToString()

View File

@ -2,13 +2,15 @@
// 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.Linq.Expressions;
using Microsoft.AspNetCore.Mvc.TestCommon;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Rendering
{
public class HtmlHelperTextBoxAreaTest
public class HtmlHelperTextAreaTest
{
[Fact]
public void TextAreaFor_GeneratesPlaceholderAttribute_WhenDisplayAttributePromptIsSetAndTypeIsValid()
@ -40,6 +42,125 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
Assert.DoesNotContain(@"placeholder=""HtmlEncode[[placeholder]]""", result, StringComparison.Ordinal);
}
public static TheoryData TextAreaFor_UsesModelValueForComplexExpressionsData
{
get
{
return new TheoryData<Expression<Func<ComplexModel, string>>, string>
{
{
model => model.Property3["key"],
"<textarea id=\"HtmlEncode[[pre_Property3_key_]]\" name=\"HtmlEncode[[pre.Property3[key]]]\">" + Environment.NewLine +
"HtmlEncode[[Prop3Val]]</textarea>"
},
{
model => model.Property4.Property5,
"<textarea id=\"HtmlEncode[[pre_Property4_Property5]]\" name=\"HtmlEncode[[pre.Property4.Property5]]\">" + Environment.NewLine +
"HtmlEncode[[Prop5Val]]</textarea>"
},
{
model => model.Property4.Property6[0],
"<textarea id=\"HtmlEncode[[pre_Property4_Property6_0_]]\" name=\"HtmlEncode[[pre.Property4.Property6[0]]]\">" + Environment.NewLine +
"HtmlEncode[[Prop6Val]]</textarea>"
}
};
}
}
[Theory]
[MemberData(nameof(TextAreaFor_UsesModelValueForComplexExpressionsData))]
public void TextAreaFor_ComplexExpressions_UsesModelValueForComplexExpressions(
Expression<Func<ComplexModel, string>> expression,
string expected)
{
// Arrange
var model = new ComplexModel();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
helper.ViewData.Model.Property3["key"] = "Prop3Val";
helper.ViewData.Model.Property4.Property5 = "Prop5Val";
helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
// Act
var result = helper.TextAreaFor(expression);
// Assert
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
}
public static TheoryData TextAreaFor_UsesModelStateValueForComplexExpressionsData
{
get
{
return new TheoryData<Expression<Func<ComplexModel, string>>, string>
{
{
model => model.Property3["key"],
"<textarea id=\"HtmlEncode[[pre_Property3_key_]]\" name=\"HtmlEncode[[pre.Property3[key]]]\">" + Environment.NewLine +
"HtmlEncode[[MProp3Val]]</textarea>"
},
{
model => model.Property4.Property5,
"<textarea id=\"HtmlEncode[[pre_Property4_Property5]]\" name=\"HtmlEncode[[pre.Property4.Property5]]\">" + Environment.NewLine +
"HtmlEncode[[MProp5Val]]</textarea>"
},
{
model => model.Property4.Property6[0],
"<textarea id=\"HtmlEncode[[pre_Property4_Property6_0_]]\" name=\"HtmlEncode[[pre.Property4.Property6[0]]]\">" + Environment.NewLine +
"HtmlEncode[[MProp6Val]]</textarea>"
}
};
}
}
[Theory]
[MemberData(nameof(TextAreaFor_UsesModelStateValueForComplexExpressionsData))]
public void TextAreaFor_ComplexExpressions_UsesModelStateValueForComplexExpressions(
Expression<Func<ComplexModel, string>> expression,
string expected)
{
// Arrange
var model = new ComplexModel();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
helper.ViewData.ModelState.SetModelValue("pre.Property3[key]", "MProp3Val", "MProp3Val");
helper.ViewData.ModelState.SetModelValue("pre.Property4.Property5", "MProp5Val", "MProp5Val");
helper.ViewData.ModelState.SetModelValue("pre.Property4.Property6[0]", "MProp6Val", "MProp6Val");
helper.ViewData.Model.Property3["key"] = "Prop3Val";
helper.ViewData.Model.Property4.Property5 = "Prop5Val";
helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
// Act
var result = helper.TextAreaFor(expression);
// Assert
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
}
public class ComplexModel
{
public string Property1 { get; set; }
public byte[] Bytes { get; set; }
[Required]
public string Property2 { get; set; }
public Dictionary<string, string> Property3 { get; } = new Dictionary<string, string>();
public NestedClass Property4 { get; } = new NestedClass();
}
public class NestedClass
{
public string Property5 { get; set; }
public List<string> Property6 { get; } = new List<string>();
}
private class TextAreaModelWithAPlaceholder
{
[Display(Prompt = "placeholder")]

View File

@ -2,7 +2,9 @@
// 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.Linq.Expressions;
using Microsoft.AspNetCore.Mvc.TestCommon;
using Xunit;
@ -58,6 +60,125 @@ namespace Microsoft.AspNetCore.Mvc.Rendering
Assert.DoesNotContain(@"placeholder=""HtmlEncode[[placeholder]]""", result, StringComparison.Ordinal);
}
public static TheoryData TextBoxFor_UsesModelValueForComplexExpressionsData
{
get
{
return new TheoryData<Expression<Func<ComplexModel, string>>, string>
{
{
model => model.Property3["key"],
@"<input id=""HtmlEncode[[pre_Property3_key_]]"" name=""HtmlEncode[[pre.Property3[key]]]"" " +
@"type=""HtmlEncode[[text]]"" value=""HtmlEncode[[Prop3Val]]"" />"
},
{
model => model.Property4.Property5,
@"<input id=""HtmlEncode[[pre_Property4_Property5]]"" name=""HtmlEncode[[pre.Property4.Property5]]"" " +
@"type=""HtmlEncode[[text]]"" value=""HtmlEncode[[Prop5Val]]"" />"
},
{
model => model.Property4.Property6[0],
@"<input id=""HtmlEncode[[pre_Property4_Property6_0_]]"" " +
@"name=""HtmlEncode[[pre.Property4.Property6[0]]]"" type=""HtmlEncode[[text]]"" value=""HtmlEncode[[Prop6Val]]"" />"
}
};
}
}
[Theory]
[MemberData(nameof(TextBoxFor_UsesModelValueForComplexExpressionsData))]
public void TextBoxFor_ComplexExpressions_UsesModelValueForComplexExpressions(
Expression<Func<ComplexModel, string>> expression,
string expected)
{
// Arrange
var model = new ComplexModel();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
helper.ViewData.Model.Property3["key"] = "Prop3Val";
helper.ViewData.Model.Property4.Property5 = "Prop5Val";
helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
// Act
var result = helper.TextBoxFor(expression);
// Assert
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
}
public static TheoryData TextBoxFor_UsesModelStateValueForComplexExpressionsData
{
get
{
return new TheoryData<Expression<Func<ComplexModel, string>>, string>
{
{
model => model.Property3["key"],
@"<input id=""HtmlEncode[[pre_Property3_key_]]"" name=""HtmlEncode[[pre.Property3[key]]]"" " +
@"type=""HtmlEncode[[text]]"" value=""HtmlEncode[[MProp3Val]]"" />"
},
{
model => model.Property4.Property5,
@"<input id=""HtmlEncode[[pre_Property4_Property5]]"" name=""HtmlEncode[[pre.Property4.Property5]]"" " +
@"type=""HtmlEncode[[text]]"" value=""HtmlEncode[[MProp5Val]]"" />"
},
{
model => model.Property4.Property6[0],
@"<input id=""HtmlEncode[[pre_Property4_Property6_0_]]"" " +
@"name=""HtmlEncode[[pre.Property4.Property6[0]]]"" type=""HtmlEncode[[text]]"" value=""HtmlEncode[[MProp6Val]]"" />"
}
};
}
}
[Theory]
[MemberData(nameof(TextBoxFor_UsesModelStateValueForComplexExpressionsData))]
public void TextBoxFor_ComplexExpressions_UsesModelStateValueForComplexExpressions(
Expression<Func<ComplexModel, string>> expression,
string expected)
{
// Arrange
var model = new ComplexModel();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "pre";
helper.ViewData.ModelState.SetModelValue("pre.Property3[key]", "MProp3Val", "MProp3Val");
helper.ViewData.ModelState.SetModelValue("pre.Property4.Property5", "MProp5Val", "MProp5Val");
helper.ViewData.ModelState.SetModelValue("pre.Property4.Property6[0]", "MProp6Val", "MProp6Val");
helper.ViewData.Model.Property3["key"] = "Prop3Val";
helper.ViewData.Model.Property4.Property5 = "Prop5Val";
helper.ViewData.Model.Property4.Property6.Add("Prop6Val");
// Act
var result = helper.TextBoxFor(expression);
// Assert
Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(result));
}
public class ComplexModel
{
public string Property1 { get; set; }
public byte[] Bytes { get; set; }
[Required]
public string Property2 { get; set; }
public Dictionary<string, string> Property3 { get; } = new Dictionary<string, string>();
public NestedClass Property4 { get; } = new NestedClass();
}
public class NestedClass
{
public string Property5 { get; set; }
public List<string> Property6 { get; } = new List<string>();
}
private class TextBoxModel
{
[Display(Prompt = "placeholder")]

View File

@ -0,0 +1,77 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Rendering
{
public class HtmlHelperValueExtensionsTest
{
[Fact]
public void Value_ReturnsModelValue()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
// Act
var result = helper.Value("SomeProperty");
// Assert
Assert.Equal("ModelValue", result);
}
[Fact]
public void ValueFor_ReturnsModelValue()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
// Act
var result = helper.ValueFor(m => m.SomeProperty);
// Assert
Assert.Equal("ModelValue", result);
}
[Fact]
public void ValueForModel_ReturnsModelValue()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
// Act
var result = helper.ValueForModel();
// Assert
Assert.Equal("{ SomeProperty = ModelValue }", result);
}
[Fact]
public void ValueForModel_ReturnsModelValueWithSpecificFormat()
{
// Arrange
var model = new SomeModel { SomeProperty = "ModelValue" };
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model);
// Act
var result = helper.ValueForModel(format: "-{0}-");
// Assert
Assert.Equal("-{ SomeProperty = ModelValue }-", result);
}
private class SomeModel
{
public string SomeProperty { get; set; }
public override string ToString()
{
return string.Format(
"{{ SomeProperty = {0} }}", SomeProperty ?? "(null)");
}
}
}
}