|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.Extensions.Localization;
using Moq;
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();
}
public static TheoryData<FormatModel, string> EnumFormatModels
{
get
{
return new TheoryData<FormatModel, string>
{
{
new FormatModel{ FormatProperty = Status.Created },
"Value: Created"
},
{
new FormatModel { FormatProperty = Status.Done },
"Value: Done"
}
};
}
}
public static TheoryData<FormatModel, string> EnumUnformattedModels
{
get
{
return new TheoryData<FormatModel, string>
{
{
new FormatModel {NonFormatProperty = Status.Created },
"CreatedKey"
},
{
new FormatModel {NonFormatProperty = Status.Done },
"Done"
}
};
}
}
[Theory]
[MemberData(nameof(EnumUnformattedModels))]
public void Display_UsesTemplateUnFormatted(FormatModel model, string expectedResult)
{
// Arrange
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.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/Status", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("Status", view.Object))
.Verifiable();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayFor(x => x.NonFormatProperty);
// Assert
Assert.Equal(expectedResult, HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Theory]
[MemberData(nameof(EnumFormatModels))]
public void Display_UsesTemplateFormatted(FormatModel model, string expectedResult)
{
// Arrange
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.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/Status", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("Status", view.Object))
.Verifiable();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayFor(x => x.FormatProperty);
// Assert
Assert.Equal(expectedResult, HtmlContentUtilities.HtmlContentToString(displayResult));
}
[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_EnumProperty_IStringLocalizedValue()
{
// Arrange
var model = new StatusModel
{
Status = Status.Created
};
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.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/Status", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var stringLocalizer = new Mock<IStringLocalizer>(MockBehavior.Strict);
stringLocalizer
.Setup(s => s["CreatedKey"])
.Returns<string>((key) =>
{
return new LocalizedString(key, "created from IStringLocalizer");
});
var stringLocalizerFactory = new Mock<IStringLocalizerFactory>();
stringLocalizerFactory
.Setup(s => s.Create(typeof(Status)))
.Returns(stringLocalizer.Object);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object, stringLocalizerFactory.Object);
// Act
var displayResult = helper.DisplayFor(m => m.Status);
// Assert
Assert.Equal("created from IStringLocalizer", HtmlContentUtilities.HtmlContentToString(displayResult));
}
[Fact]
public void DisplayFor_EnumProperty_ResourceTypeLocalizedValue()
{
// Arrange
var model = new StatusModel
{
Status = Status.Faulted
};
var view = new Mock<IView>();
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
.Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.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/Status", /*isMainPage*/ false))
.Returns(ViewEngineResult.Found("SomeView", view.Object));
var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);
// Act
var displayResult = helper.DisplayFor(m => m.Status);
// Assert
Assert.Equal("Faulted from ResourceType", 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));
}
public class StatusResource
{
public static string FaultedKey { get { return "Faulted from ResourceType"; } }
}
public enum Status : byte
{
[Display(Name = "CreatedKey")]
Created,
[Display(Name = "FaultedKey", ResourceType = typeof(StatusResource))]
Faulted,
Done
}
public class FormatModel
{
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "Value: {0}")]
public Status FormatProperty { get; set; }
public Status NonFormatProperty { get; set; }
}
private class SomeModel
{
public string SomeProperty { get; set; }
}
private class StatusModel
{
public Status Status { get; set; }
}
}
|