// 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.ComponentModel.DataAnnotations;
using System.Linq;
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
///
/// Test the class.
///
public class CachedDataAnnotationsModelMetadataTest
{
[Fact]
public void Constructor_DefersDefaultsToBaseModelMetadata()
{
// Arrange
var attributes = Enumerable.Empty();
var provider = new DataAnnotationsModelMetadataProvider();
// Act
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: attributes);
// Assert
Assert.True(metadata.ConvertEmptyStringToNull);
Assert.False(metadata.HasNonDefaultEditFormat);
Assert.False(metadata.HideSurroundingHtml);
Assert.True(metadata.HtmlEncode);
Assert.True(metadata.IsComplexType);
Assert.False(metadata.IsReadOnly);
Assert.False(metadata.IsRequired);
Assert.True(metadata.ShowForDisplay);
Assert.True(metadata.ShowForEdit);
Assert.Null(metadata.DataTypeName);
Assert.Null(metadata.Description);
Assert.Null(metadata.DisplayFormatString);
Assert.Null(metadata.DisplayName);
Assert.Null(metadata.EditFormatString);
Assert.Null(metadata.NullDisplayText);
Assert.Null(metadata.SimpleDisplayText);
Assert.Null(metadata.TemplateHint);
Assert.Equal(ModelMetadata.DefaultOrder, metadata.Order);
}
public static TheoryData> ExpectedAttributeDataStrings
{
get
{
return new TheoryData>
{
{
new DataTypeAttribute("value"), metadata => metadata.DataTypeName
},
{
new DataTypeWithCustomDisplayFormat(), metadata => metadata.DisplayFormatString
},
{
new DataTypeWithCustomEditFormat(), metadata => metadata.EditFormatString
},
{
new DisplayAttribute { Description = "value" }, metadata => metadata.Description
},
{
new DisplayAttribute { Name = "value" }, metadata => metadata.DisplayName
},
{
new DisplayColumnAttribute("Property"), metadata => metadata.SimpleDisplayText
},
{
new DisplayFormatAttribute { DataFormatString = "value" },
metadata => metadata.DisplayFormatString
},
{
// DisplayFormatString does not ignore [DisplayFormat] if ApplyFormatInEditMode==true.
new DisplayFormatAttribute { ApplyFormatInEditMode = true, DataFormatString = "value" },
metadata => metadata.DisplayFormatString
},
{
new DisplayFormatAttribute { ApplyFormatInEditMode = true, DataFormatString = "value" },
metadata => metadata.EditFormatString
},
{
new DisplayFormatAttribute { NullDisplayText = "value" }, metadata => metadata.NullDisplayText
},
};
}
}
[Theory]
[MemberData(nameof(ExpectedAttributeDataStrings))]
public void AttributesOverrideMetadataStrings(Attribute attribute, Func accessor)
{
// Arrange
var attributes = new[] { attribute };
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(ClassWithDisplayableColumn),
propertyName: null,
attributes: attributes)
{
Model = new ClassWithDisplayableColumn { Property = "value" },
};
// Act
var result = accessor(metadata);
// Assert
Assert.Equal("value", result);
}
public static TheoryData, bool> ExpectedAttributeDataBooleans
{
get
{
return new TheoryData, bool>
{
{
// Edit formats from [DataType] subclass affect HasNonDefaultEditFormat.
new DataTypeWithCustomEditFormat(),
metadata => metadata.HasNonDefaultEditFormat,
true
},
{
// Edit formats from [DataType] do not affect HasNonDefaultEditFormat.
new DataTypeAttribute(DataType.Date),
metadata => metadata.HasNonDefaultEditFormat,
false
},
{
new DisplayFormatAttribute { ConvertEmptyStringToNull = false },
metadata => metadata.ConvertEmptyStringToNull,
false
},
{
new DisplayFormatAttribute { ConvertEmptyStringToNull = true },
metadata => metadata.ConvertEmptyStringToNull,
true
},
{
// Changes only to DisplayFormatString do not affect HasNonDefaultEditFormat.
new DisplayFormatAttribute { DataFormatString = "value" },
metadata => metadata.HasNonDefaultEditFormat,
false
},
{
new DisplayFormatAttribute { ApplyFormatInEditMode = true, DataFormatString = "value" },
metadata => metadata.HasNonDefaultEditFormat,
true
},
{
new DisplayFormatAttribute { HtmlEncode = false },
metadata => metadata.HtmlEncode,
false
},
{
new DisplayFormatAttribute { HtmlEncode = true },
metadata => metadata.HtmlEncode,
true
},
{
new EditableAttribute(allowEdit: false),
metadata => metadata.IsReadOnly,
true
},
{
new EditableAttribute(allowEdit: true),
metadata => metadata.IsReadOnly,
false
},
{
new HiddenInputAttribute { DisplayValue = false },
metadata => metadata.HideSurroundingHtml,
true
},
{
new HiddenInputAttribute { DisplayValue = true },
metadata => metadata.HideSurroundingHtml,
false
},
{
new RequiredAttribute(),
metadata => metadata.IsRequired,
true
},
};
}
}
[Theory]
[MemberData(nameof(ExpectedAttributeDataBooleans))]
public void AttributesOverrideMetadataBooleans(
Attribute attribute,
Func accessor,
bool expectedResult)
{
// Arrange
var attributes = new[] { attribute };
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: attributes);
// Act
var result = accessor(metadata);
// Assert
Assert.Equal(expectedResult, result);
}
[Fact]
public void DataTypeName_Null_IfHtmlEncodeTrue()
{
// Arrange
var displayFormat = new DisplayFormatAttribute { HtmlEncode = true, };
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: new Attribute[] { displayFormat });
// Act
var result = metadata.DataTypeName;
// Assert
Assert.Null(result);
}
[Fact]
public void DataTypeName_Html_IfHtmlEncodeFalse()
{
// Arrange
var expected = "Html";
var displayFormat = new DisplayFormatAttribute { HtmlEncode = false, };
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: new Attribute[] { displayFormat });
// Act
var result = metadata.DataTypeName;
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void DataTypeName_AttributesHaveExpectedPrecedence()
{
// Arrange
var expected = "MultilineText";
var dataType = new DataTypeAttribute(DataType.MultilineText);
var displayFormat = new DisplayFormatAttribute { HtmlEncode = false, };
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: new Attribute[] { dataType, displayFormat });
// Act
var result = metadata.DataTypeName;
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void DisplayFormatString_AttributesHaveExpectedPrecedence()
{
// Arrange
var expected = "custom format";
var dataType = new DataTypeAttribute(DataType.Currency);
var displayFormat = new DisplayFormatAttribute { DataFormatString = expected, };
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: new Attribute[] { dataType, displayFormat });
// Act
var result = metadata.DisplayFormatString;
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void EditFormatString_AttributesHaveExpectedPrecedence()
{
// Arrange
var expected = "custom format";
var dataType = new DataTypeAttribute(DataType.Currency);
var displayFormat = new DisplayFormatAttribute
{
ApplyFormatInEditMode = true,
DataFormatString = expected,
};
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: new Attribute[] { dataType, displayFormat });
// Act
var result = metadata.EditFormatString;
// Assert
Assert.Equal(expected, result);
}
[Fact]
private void EditFormatString_DoesNotAffectDisplayFormat()
{
// Arrange
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: Enumerable.Empty());
// Act
metadata.EditFormatString = "custom format";
// Assert
Assert.Null(metadata.DisplayFormatString);
}
[Fact]
private void DisplayFormatString_DoesNotAffectEditFormat()
{
// Arrange
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new CachedDataAnnotationsModelMetadata(
provider,
containerType: null,
modelType: typeof(object),
propertyName: null,
attributes: Enumerable.Empty());
// Act
metadata.DisplayFormatString = "custom format";
// Assert
Assert.Null(metadata.EditFormatString);
}
private class DataTypeWithCustomDisplayFormat : DataTypeAttribute
{
public DataTypeWithCustomDisplayFormat() : base("Custom datatype")
{
DisplayFormat = new DisplayFormatAttribute
{
DataFormatString = "value",
};
}
}
private class DataTypeWithCustomEditFormat : DataTypeAttribute
{
public DataTypeWithCustomEditFormat() : base("Custom datatype")
{
DisplayFormat = new DisplayFormatAttribute
{
ApplyFormatInEditMode = true,
DataFormatString = "value",
};
}
}
private class ClassWithDisplayableColumn
{
public string Property { get; set; }
}
}
}