|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace Microsoft.AspNetCore.Mvc.Core;
/// <summary>
/// Test the <see cref="HtmlHelperLabelExtensions" /> class.
/// </summary>
public class HtmlHelperLabelExtensionsTest
{
[Fact]
public void LabelHelpers_ReturnEmptyForModel()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
// Assert
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
[Fact]
public void LabelHelpers_ReturnExpectedElementForModel_WithLabelText()
{
// Arrange
var expectedLabel = "<label for=\"\">HtmlEncode[[a label]]</label>";
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelResult = helper.Label(expression: string.Empty, labelText: "a label");
var labelNullResult = helper.Label(expression: null, labelText: "a label");
var labelForResult = helper.LabelFor(m => m, labelText: "a label");
var labelForModelResult = helper.LabelForModel(labelText: "a label");
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
// Prior to aspnet/Mvc#6638 fix, helpers generated nothing with this setup.
[Fact]
public void LabelHelpers_ReturnExpectedElementForModel_WithEmptyLabelText()
{
// Arrange
var expectedLabel = "<label for=\"\"></label>";
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelResult = helper.Label(expression: string.Empty, labelText: string.Empty);
var labelNullResult = helper.Label(expression: null, labelText: string.Empty);
var labelForResult = helper.LabelFor(m => m, labelText: string.Empty);
var labelForModelResult = helper.LabelForModel(labelText: string.Empty);
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
[Fact]
public void LabelHelpers_DisplayPropertyName()
{
// Arrange
var expectedLabel = "<label for=\"HtmlEncode[[Property1]]\">HtmlEncode[[Property1]]</label>";
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelResult = helper.Label("Property1");
var labelForResult = helper.LabelFor(m => m.Property1);
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
}
[Fact]
public void LabelHelpers_DisplayPropertyName_ForNestedProperty()
{
// Arrange
var expectedLabel = "<label for=\"HtmlEncode[[Inner_Id]]\">HtmlEncode[[Id]]</label>";
var helper = DefaultTemplatesUtilities.GetHtmlHelper<OuterClass>(model: null);
// Act
var labelResult = helper.Label("Inner.Id");
var labelForResult = helper.LabelFor(m => m.Inner.Id);
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
}
[Fact]
public void LabelHelpers_DisplayMetadataPropertyNameForProperty()
{
// Arrange
var propertyName = "Property1";
var provider = new EmptyModelMetadataProvider();
var modelExplorer = provider
.GetModelExplorerForType(typeof(DefaultTemplatesUtilities.ObjectTemplateModel), model: null)
.GetExplorerForProperty(propertyName);
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
helper.ViewData.ModelExplorer = modelExplorer;
// Act
var labelResult = helper.Label(expression: string.Empty);
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
// Assert
Assert.Equal("<label for=\"\">HtmlEncode[[" + propertyName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal("<label for=\"\">HtmlEncode[[" + propertyName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal("<label for=\"\">HtmlEncode[[" + propertyName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
// If the metadata is for a type (not property), then Label(expression) will evaluate the expression
[Fact]
public void LabelHelpers_Label_Evaluates_Expression()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
helper.ViewData["value"] = "testvalue";
// Act
var labelResult = helper.Label(expression: "value");
// Assert
Assert.Equal("<label for=\"HtmlEncode[[value]]\">HtmlEncode[[value]]</label>", HtmlContentUtilities.HtmlContentToString(labelResult));
}
// Following test is identical to LabelHelpers_ReturnEmptyForModel() from the HTML helpers' perspective. But,
// test confirms the added metadata does not change the behavior.
[Fact]
public void LabelHelpers_ReturnEmptyForModel_IfDisplayNameEmpty()
{
// Arrange
var provider = new TestModelMetadataProvider();
provider
.ForType<DefaultTemplatesUtilities.ObjectTemplateModel>()
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
// Assert
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Empty(HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
// Prior to aspnet/Mvc#6638 fix, helpers generated nothing with this setup.
// Following test mimics use of an identity expression in an editor template if invoked for an element in a
// collection. See also LabelHelpers_ReturnExpectedElementForProperty_IfDisplayNameEmptyAndNotTopLevel().
[Fact]
public void LabelHelpers_ReturnExpectedElementForModel_IfDisplayNameEmptyAndNotTopLevel()
{
// Arrange
var expectedLabel = "<label for=\"HtmlEncode[[prefix]]\"></label>";
var provider = new TestModelMetadataProvider();
provider
.ForType<DefaultTemplatesUtilities.ObjectTemplateModel>()
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
helper.ViewData.TemplateInfo.HtmlFieldPrefix = "prefix";
// Act
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
[Fact]
public void LabelHelpers_ReturnExpectedElementForModel_IfDisplayNameEmpty_WithLabelText()
{
// Arrange
var expectedLabel = "<label for=\"\">HtmlEncode[[a label]]</label>";
var provider = new TestModelMetadataProvider();
provider
.ForType<DefaultTemplatesUtilities.ObjectTemplateModel>()
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label(expression: string.Empty, labelText: "a label");
var labelNullResult = helper.Label(expression: null, labelText: "a label");
var labelForResult = helper.LabelFor(m => m, labelText: "a label");
var labelForModelResult = helper.LabelForModel(labelText: "a label");
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
// Prior to aspnet/Mvc#6638 fix, helpers generated nothing with this setup.
[Fact]
public void LabelHelpers_ReturnExpectedElementForModel_IfDisplayNameEmpty_WithEmptyLabelText()
{
// Arrange
var expectedLabel = "<label for=\"\"></label>";
var provider = new TestModelMetadataProvider();
provider
.ForType<DefaultTemplatesUtilities.ObjectTemplateModel>()
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label(expression: string.Empty, labelText: string.Empty);
var labelNullResult = helper.Label(expression: null, labelText: string.Empty);
var labelForResult = helper.LabelFor(m => m, labelText: string.Empty);
var labelForModelResult = helper.LabelForModel(labelText: string.Empty);
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
[Theory]
[InlineData("DisplayName")]
[InlineData("Custom display name from metadata")]
public void LabelHelpers_DisplayDisplayName_IfNonNull(string displayName)
{
// Arrange
var provider = new TestModelMetadataProvider();
provider
.ForType<DefaultTemplatesUtilities.ObjectTemplateModel>()
.DisplayDetails(dd => dd.DisplayName = () => displayName);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label(expression: string.Empty);
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
// Assert
Assert.Equal("<label for=\"\">HtmlEncode[[" + displayName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal("<label for=\"\">HtmlEncode[[" + displayName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal("<label for=\"\">HtmlEncode[[" + displayName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
// Prior to aspnet/Mvc#6638 fix, helpers generated nothing with this setup.
// Following test mimics use of an identity expression in an editor template if invoked for a property. See
// also LabelHelpers_ReturnExpectedElementForModel_IfDisplayNameEmptyAndNotTopLevel().
[Fact]
public void LabelHelpers_ReturnExpectedElementForProperty_IfDisplayNameEmptyAndNotTopLevel()
{
// Arrange
var expectedLabel = "<label for=\"HtmlEncode[[Property1]]\"></label>";
var provider = new TestModelMetadataProvider();
provider
.ForProperty<DefaultTemplatesUtilities.ObjectTemplateModel>("Property1")
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper<string>(provider: provider);
helper.ViewData.ModelExplorer = provider
.GetModelExplorerForType(typeof(DefaultTemplatesUtilities.ObjectTemplateModel), model: null)
.GetExplorerForProperty(nameof(DefaultTemplatesUtilities.ObjectTemplateModel.Property1));
helper.ViewData.TemplateInfo.HtmlFieldPrefix = nameof(DefaultTemplatesUtilities.ObjectTemplateModel.Property1);
// Act
var labelResult = helper.Label(expression: string.Empty);
var labelNullResult = helper.Label(expression: null); // null is another alias for current model
var labelForResult = helper.LabelFor(m => m);
var labelForModelResult = helper.LabelForModel();
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelNullResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
// Prior to aspnet/Mvc#6638 fix, helpers generated nothing with this setup.
[Fact]
public void LabelHelpers_ReturnExpectedElementForProperty_IfDisplayNameEmpty()
{
// Arrange
var expectedLabel = "<label for=\"HtmlEncode[[Property1]]\"></label>";
var provider = new TestModelMetadataProvider();
provider
.ForProperty<DefaultTemplatesUtilities.ObjectTemplateModel>("Property1")
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label(expression: nameof(DefaultTemplatesUtilities.ObjectTemplateModel.Property1));
var labelForResult = helper.LabelFor(m => m.Property1);
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
}
[Fact]
public void LabelHelpers_ReturnExpectedElementForProperty_IfDisplayNameEmpty_WithLabelText()
{
// Arrange
var expectedLabel = "<label for=\"HtmlEncode[[Property1]]\">HtmlEncode[[a label]]</label>";
var provider = new TestModelMetadataProvider();
provider
.ForProperty<DefaultTemplatesUtilities.ObjectTemplateModel>("Property1")
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label(
expression: nameof(DefaultTemplatesUtilities.ObjectTemplateModel.Property1),
labelText: "a label");
var labelForResult = helper.LabelFor(m => m.Property1, labelText: "a label");
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
}
// Prior to aspnet/Mvc#6638 fix, helpers generated nothing with this setup.
[Fact]
public void LabelHelpers_ReturnExpectedElementForProperty_IfDisplayNameEmpty_WithEmptyLabelText()
{
// Arrange
var expectedLabel = "<label for=\"HtmlEncode[[Property1]]\"></label>";
var provider = new TestModelMetadataProvider();
provider
.ForProperty<DefaultTemplatesUtilities.ObjectTemplateModel>("Property1")
.DisplayDetails(dd => dd.DisplayName = () => string.Empty);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label(
expression: nameof(DefaultTemplatesUtilities.ObjectTemplateModel.Property1),
labelText: string.Empty);
var labelForResult = helper.LabelFor(m => m.Property1, labelText: string.Empty);
// Assert
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal(expectedLabel, HtmlContentUtilities.HtmlContentToString(labelForResult));
}
[Theory]
[InlineData("DisplayName")]
[InlineData("Custom display name from metadata")]
public void LabelHelpers_DisplayDisplayNameForProperty_IfNonNull(string displayName)
{
// Arrange
var provider = new TestModelMetadataProvider();
provider
.ForProperty<DefaultTemplatesUtilities.ObjectTemplateModel>("Property1")
.DisplayDetails(dd => dd.DisplayName = () => displayName);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(provider: provider);
// Act
var labelResult = helper.Label("Property1");
var labelForResult = helper.LabelFor(m => m.Property1);
// Assert
Assert.Equal("<label for=\"HtmlEncode[[Property1]]\">HtmlEncode[[" + displayName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelResult));
Assert.Equal("<label for=\"HtmlEncode[[Property1]]\">HtmlEncode[[" + displayName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelForResult));
}
[Theory]
[InlineData("A", "A", "A")]
[InlineData("A[23]", "A[23]", "A_23_")]
[InlineData("A[0].B", "B", "A_0__B")]
[InlineData("A.B.C.D", "D", "A_B_C_D")]
public void Label_DisplaysRightmostExpressionSegment_IfPropertiesNotFound(
string expression,
string expectedText,
string expectedId)
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var result = helper.Label(expression);
// Assert
// Label() falls back to expression name when DisplayName and PropertyName are null.
Assert.Equal("<label for=\"HtmlEncode[[" + expectedId + "]]\">HtmlEncode[[" + expectedText + "]]</label>", HtmlContentUtilities.HtmlContentToString(result));
}
[Fact]
public void LabelFor_ThrowsInvalidOperation_IfExpressionUnsupported()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act & Assert
var exception = Assert.Throws<InvalidOperationException>(
() => helper.LabelFor(model => new { foo = "Bar" }));
Assert.Equal(
"Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.",
exception.Message);
}
[Fact]
public void LabelFor_DisplaysVariableName()
{
// Arrange
var unknownKey = "this is a dummy parameter value";
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var result = helper.LabelFor(model => unknownKey);
// Assert
Assert.Equal("<label for=\"HtmlEncode[[unknownKey]]\">HtmlEncode[[unknownKey]]</label>", HtmlContentUtilities.HtmlContentToString(result));
}
[Fact]
public void Label_UsesSpecifiedLabelText()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelResult = helper.Label("Property1", labelText: "Hello");
// Assert
Assert.Equal("<label for=\"HtmlEncode[[Property1]]\">HtmlEncode[[Hello]]</label>", HtmlContentUtilities.HtmlContentToString(labelResult));
}
[Fact]
public void LabelFor_UsesSpecifiedLabelText()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelForResult = helper.LabelFor(m => m.Property1, labelText: "Hello");
// Assert
Assert.Equal("<label for=\"HtmlEncode[[Property1]]\">HtmlEncode[[Hello]]</label>", HtmlContentUtilities.HtmlContentToString(labelForResult));
}
[Fact]
public void LabelForModel_UsesSpecifiedLabelText()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelForModelResult = helper.LabelForModel(labelText: "Hello");
// Assert
Assert.Equal("<label for=\"\">HtmlEncode[[Hello]]</label>", HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
[Fact]
public void LabelFor_DisplaysSpecifiedHtmlAttributes()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelForResult = helper.LabelFor(m => m.Property1, htmlAttributes: new { attr = "value" });
// Assert
Assert.Equal("<label attr=\"HtmlEncode[[value]]\" for=\"HtmlEncode[[Property1]]\">HtmlEncode[[Property1]]</label>", HtmlContentUtilities.HtmlContentToString(labelForResult));
}
[Fact]
public void LabelForModel_DisplaysSpecifiedHtmlAttributes()
{
// Arrange
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
// Act
var labelForModelResult = helper.LabelForModel(labelText: "Hello", htmlAttributes: new { attr = "value" });
// Assert
Assert.Equal("<label attr=\"HtmlEncode[[value]]\" for=\"\">HtmlEncode[[Hello]]</label>", HtmlContentUtilities.HtmlContentToString(labelForModelResult));
}
private sealed class InnerClass
{
public int Id { get; set; }
}
private sealed class OuterClass
{
public InnerClass Inner { get; set; }
}
}
|