// 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.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.TestCommon; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.Extensions.Localization; using Moq; using Xunit; namespace Microsoft.AspNetCore.Mvc.Rendering { public class HtmlHelperDisplayExtensionsTest { [Fact] public void DisplayHelpers_FindsModel_WhenViewDataIsNotSet() { // Arrange var expected = $"
HtmlEncode[[SomeProperty]]
{Environment.NewLine}" + $"
HtmlEncode[[PropValue]]
{Environment.NewLine}"; var model = new SomeModel { SomeProperty = "PropValue" }; var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); 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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*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(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false)) .Returns(ViewEngineResult.Found("SomeView", Mock.Of())) .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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix)) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*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(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false)) .Returns(ViewEngineResult.Found("SomeView", Mock.Of())) .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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/Status", /*isMainPage*/ false)) .Returns(ViewEngineResult.Found("SomeView", view.Object)); var stringLocalizer = new Mock(MockBehavior.Strict); stringLocalizer .Setup(s => s["CreatedKey"]) .Returns((key) => { return new LocalizedString(key, "created from IStringLocalizer"); }); var stringLocalizerFactory = new Mock(); 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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix)) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), It.IsAny(), /*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(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false)) .Returns(ViewEngineResult.Found("SomeView", Mock.Of())) .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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString())) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "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(); view.Setup(v => v.RenderAsync(It.IsAny())) .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix)) .Returns(Task.FromResult(0)); var viewEngine = new Mock(MockBehavior.Strict); viewEngine .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny(), /*isMainPage*/ false)) .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty())); viewEngine .Setup(v => v.FindView(It.IsAny(), "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; } } private class StatusModel { public Status Status { get; set; } } public class StatusResource { public static string FaultedKey { get { return "Faulted from ResourceType"; } } } private enum Status : byte { [Display(Name = "CreatedKey")] Created, [Display(Name = "FaultedKey", ResourceType = typeof(StatusResource))] Faulted, Done } } }