(model);
html.ViewContext.ViewBag.htmlAttributes = new { @class = "form-control", foo = "bar" };
// Act
string result = RunWithoutViewEngine(() =>
DefaultEditorTemplates.ObjectTemplate(html));
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void ObjectTemplateWithModelError()
{
string expected =
"Property1
" + Environment.NewLine
+ "Model = p1, ModelType = System.String, PropertyName = Property1, HtmlFieldName = Property1, TemplateName = (null), Mode = Edit, AdditionalViewData = (null) Error Message
" + Environment.NewLine
+ "Property2
" + Environment.NewLine
+ "Model = (null), ModelType = System.String, PropertyName = Property2, HtmlFieldName = Property2, TemplateName = (null), Mode = Edit, AdditionalViewData = (null)
" + Environment.NewLine;
// Arrange
ObjectTemplateModel model = new ObjectTemplateModel { Property1 = "p1", Property2 = null };
HtmlHelper html = MakeHtmlHelper(model);
html.ViewData.ModelState.AddModelError("FieldPrefix.Property1", "Error Message");
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void ObjectTemplateWithDisplayNameMetadata()
{
string expected =
"Model = (null), ModelType = System.String, PropertyName = Property1, HtmlFieldName = Property1, TemplateName = (null), Mode = Edit, AdditionalViewData = (null)
" + Environment.NewLine
+ "Custom display name
" + Environment.NewLine
+ "Model = (null), ModelType = System.String, PropertyName = Property2, HtmlFieldName = Property2, TemplateName = (null), Mode = Edit, AdditionalViewData = (null)
" + Environment.NewLine;
// Arrange
ObjectTemplateModel model = new ObjectTemplateModel();
HtmlHelper html = MakeHtmlHelper(model);
Mock provider = new Mock();
Func accessor = () => model;
Mock metadata = new Mock(provider.Object, null, accessor, typeof(ObjectTemplateModel), null);
ModelMetadata prop1Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), null, typeof(string), "Property1") { DisplayName = String.Empty };
ModelMetadata prop2Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), null, typeof(string), "Property2") { DisplayName = "Custom display name" };
html.ViewData.ModelMetadata = metadata.Object;
metadata.Setup(p => p.Properties).Returns(() => new[] { prop1Metadata, prop2Metadata });
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void ObjectTemplateWithShowForEditorMetadata()
{
string expected =
"Property1
" + Environment.NewLine
+ "Model = (null), ModelType = System.String, PropertyName = Property1, HtmlFieldName = Property1, TemplateName = (null), Mode = Edit, AdditionalViewData = (null)
" + Environment.NewLine;
// Arrange
ObjectTemplateModel model = new ObjectTemplateModel();
HtmlHelper html = MakeHtmlHelper(model);
Mock provider = new Mock();
Func accessor = () => model;
Mock metadata = new Mock(provider.Object, null, accessor, typeof(ObjectTemplateModel), null);
ModelMetadata prop1Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), null, typeof(string), "Property1") { ShowForEdit = true };
ModelMetadata prop2Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), null, typeof(string), "Property2") { ShowForEdit = false };
html.ViewData.ModelMetadata = metadata.Object;
metadata.Setup(p => p.Properties).Returns(() => new[] { prop1Metadata, prop2Metadata });
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void ObjectTemplatePreventsRecursionOnModelValue()
{
string expected =
"Property2
" + Environment.NewLine
+ "Model = propValue2, ModelType = System.String, PropertyName = Property2, HtmlFieldName = Property2, TemplateName = (null), Mode = Edit, AdditionalViewData = (null)
" + Environment.NewLine;
// Arrange
ObjectTemplateModel model = new ObjectTemplateModel();
HtmlHelper html = MakeHtmlHelper(model);
Mock provider = new Mock();
Func accessor = () => model;
Mock metadata = new Mock(provider.Object, null, accessor, typeof(ObjectTemplateModel), null);
ModelMetadata prop1Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), () => "propValue1", typeof(string), "Property1");
ModelMetadata prop2Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), () => "propValue2", typeof(string), "Property2");
html.ViewData.ModelMetadata = metadata.Object;
metadata.Setup(p => p.Properties).Returns(() => new[] { prop1Metadata, prop2Metadata });
html.ViewData.TemplateInfo.VisitedObjects.Add("propValue1");
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void ObjectTemplatePreventsRecursionOnModelTypeForNullModelValues()
{
string expected =
"Property2
" + Environment.NewLine
+ "Model = propValue2, ModelType = System.String, PropertyName = Property2, HtmlFieldName = Property2, TemplateName = (null), Mode = Edit, AdditionalViewData = (null)
" + Environment.NewLine;
// Arrange
ObjectTemplateModel model = new ObjectTemplateModel();
HtmlHelper html = MakeHtmlHelper(model);
Mock provider = new Mock();
Func accessor = () => model;
Mock metadata = new Mock(provider.Object, null, accessor, typeof(ObjectTemplateModel), null);
ModelMetadata prop1Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), null, typeof(string), "Property1");
ModelMetadata prop2Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), () => "propValue2", typeof(string), "Property2");
html.ViewData.ModelMetadata = metadata.Object;
metadata.Setup(p => p.Properties).Returns(() => new[] { prop1Metadata, prop2Metadata });
html.ViewData.TemplateInfo.VisitedObjects.Add(typeof(string));
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void ObjectTemplateDisplaysNullDisplayTextWithNullModelAndTemplateDepthGreaterThanOne()
{
// Arrange
HtmlHelper html = MakeHtmlHelper(null);
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(ObjectTemplateModel));
metadata.NullDisplayText = "Null Display Text";
metadata.SimpleDisplayText = "Simple Display Text";
html.ViewData.ModelMetadata = metadata;
html.ViewData.TemplateInfo.VisitedObjects.Add("foo");
html.ViewData.TemplateInfo.VisitedObjects.Add("bar");
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(metadata.NullDisplayText, result);
}
[Theory]
[PropertyData("ConditionallyHtmlEncodedData", PropertyType = typeof(EncodedDataSets))]
public void ObjectTemplateDisplaysSimpleDisplayTextWithNonNullModelTemplateDepthGreaterThanOne(
string simpleDisplayText,
bool htmlEncode,
string expectedResult)
{
// Arrange
ObjectTemplateModel model = new ObjectTemplateModel();
HtmlHelper html = MakeHtmlHelper(model);
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(ObjectTemplateModel));
html.ViewData.ModelMetadata = metadata;
metadata.NullDisplayText = "Null Display Text";
metadata.SimpleDisplayText = simpleDisplayText;
metadata.HtmlEncode = htmlEncode;
html.ViewData.TemplateInfo.VisitedObjects.Add("foo");
html.ViewData.TemplateInfo.VisitedObjects.Add("bar");
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(expectedResult, result);
}
// PasswordTemplate
[Fact]
public void PasswordTemplateTests()
{
Assert.Equal(
" ",
DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
" ",
DefaultEditorTemplates.PasswordTemplate(MakeHtmlHelper("")));
}
[Fact]
public void PasswordTemplate_ReturnsInputElement_IgnoresValues()
{
// Arrange
var expected = " ";
// Template ignores Model and FormattedModelValue.
var helper = MakeHtmlHelper(model: "Model string", formattedModelValue: "Formatted string");
var viewData = helper.ViewData;
var templateInfo = viewData.TemplateInfo;
templateInfo.HtmlFieldPrefix = "FieldPrefix";
// Template ignores ModelState and ViewData.
var valueProviderResult = new ValueProviderResult(
"Raw model string",
"Attempted model string",
CultureInfo.InvariantCulture);
viewData.ModelState.SetModelValue("FieldPrefix", valueProviderResult);
viewData["FieldPrefix"] = "ViewData string";
// Act
var result = DefaultEditorTemplates.PasswordTemplate(helper);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void PasswordTemplate_ReturnsInputElement_UsesHtmlAttributes()
{
// Arrange
var expected = " ";
var helper = MakeHtmlHelper(model: null);
var viewData = helper.ViewData;
var templateInfo = viewData.TemplateInfo;
templateInfo.HtmlFieldPrefix = "FieldPrefix";
viewData["htmlAttributes"] = new { @class = "super", value = "Html attributes string" };
// Act
var result = DefaultEditorTemplates.PasswordTemplate(helper);
// Assert
Assert.Equal(expected, result);
}
public static TheoryDataSet PasswordTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("PasswordTemplateHtmlAttributeData")]
public void PasswordTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.PasswordTemplate(htmlHelper));
}
[Theory]
[PropertyData("PasswordTemplateHtmlAttributeData")]
public void PasswordTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.PasswordTemplate(htmlHelper));
}
[Fact]
public void ObjectTemplateWithHiddenHtml()
{
string expected = "Model = propValue1, ModelType = System.String, PropertyName = Property1, HtmlFieldName = Property1, TemplateName = (null), Mode = Edit, AdditionalViewData = (null)";
// Arrange
ObjectTemplateModel model = new ObjectTemplateModel();
HtmlHelper html = MakeHtmlHelper(model);
Mock provider = new Mock();
Func accessor = () => model;
Mock metadata = new Mock(provider.Object, null, accessor, typeof(ObjectTemplateModel), null);
ModelMetadata prop1Metadata = new ModelMetadata(provider.Object, typeof(ObjectTemplateModel), () => "propValue1", typeof(string), "Property1") { HideSurroundingHtml = true };
html.ViewData.ModelMetadata = metadata.Object;
metadata.Setup(p => p.Properties).Returns(() => new[] { prop1Metadata });
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(expected, result);
}
[Fact]
public void ObjectTemplateAllPropertiesFromEntityObjectAreHidden()
{
// Arrange
HtmlHelper html = MakeHtmlHelper(new MyEntityObject());
// Act
string result = DefaultEditorTemplates.ObjectTemplate(html, SpyCallback);
// Assert
Assert.Equal(String.Empty, result);
}
private class MyEntityObject : EntityObject
{
}
// StringTemplate
[Fact]
public void StringTemplateTests()
{
Assert.Equal(
" ",
DefaultEditorTemplates.StringTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
" alert('XSS!')</script>\" />",
DefaultEditorTemplates.StringTemplate(MakeHtmlHelper("")));
}
public static TheoryDataSet StringTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("StringTemplateHtmlAttributeData")]
public void StringTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.StringTemplate(htmlHelper));
}
[Theory]
[PropertyData("StringTemplateHtmlAttributeData")]
public void StringTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.StringTemplate(htmlHelper));
}
// PhoneNumberInputTemplate
[Fact]
public void PhoneNumberInputTemplateTests()
{
Assert.Equal(
" ",
DefaultEditorTemplates.PhoneNumberInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
" alert('XSS!')</script>\" />",
DefaultEditorTemplates.PhoneNumberInputTemplate(MakeHtmlHelper("")));
}
public static TheoryDataSet PhoneNumberInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("PhoneNumberInputTemplateHtmlAttributeData")]
public void PhoneNumberInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.PhoneNumberInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("PhoneNumberInputTemplateHtmlAttributeData")]
public void PhoneNumberInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.PhoneNumberInputTemplate(htmlHelper));
}
// UrlInputTemplate
[Fact]
public void UrlInputTemplateTests()
{
Assert.Equal(
" ",
DefaultEditorTemplates.UrlInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
" alert('XSS!')</script>\" />",
DefaultEditorTemplates.UrlInputTemplate(MakeHtmlHelper("")));
}
public static TheoryDataSet UrlInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("UrlInputTemplateHtmlAttributeData")]
public void UrlInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.UrlInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("UrlInputTemplateHtmlAttributeData")]
public void UrlInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.UrlInputTemplate(htmlHelper));
}
// EmailAddressInputTemplate
[Fact]
public void EmailAddressTemplateTests()
{
Assert.Equal(
" ",
DefaultEditorTemplates.EmailAddressInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
" alert('XSS!')</script>\" />",
DefaultEditorTemplates.EmailAddressInputTemplate(MakeHtmlHelper("")));
}
public static TheoryDataSet EmailAddressInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("EmailAddressInputTemplateHtmlAttributeData")]
public void EmailAddressInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.EmailAddressInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("EmailAddressInputTemplateHtmlAttributeData")]
public void EmailAddressInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.EmailAddressInputTemplate(htmlHelper));
}
[Fact]
public void DateTimeInputTemplateTests()
{
var type = "datetime";
Assert.Equal(
GetExpectedInputTag(type, "Value"),
DefaultEditorTemplates.DateTimeInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
GetExpectedInputTag(type, "<script>alert('XSS!')</script>"),
DefaultEditorTemplates.DateTimeInputTemplate(MakeHtmlHelper("")));
var epocInLocalTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime();
var helper = MakeHtmlHelper(epocInLocalTime);
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString(CultureInfo.CurrentCulture)),
DefaultEditorTemplates.DateTimeInputTemplate(helper));
helper.Html5DateRenderingMode = Html5DateRenderingMode.Rfc3339;
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("yyyy-MM-ddTHH:mm:ss.fffK")),
DefaultEditorTemplates.DateTimeInputTemplate(helper));
// Override FormattedModelValue and let helper think this string came from a default [DataType] attribute.
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("yyyy-MM-ddTHH:mm:ss.fffK")),
DefaultEditorTemplates.DateTimeInputTemplate(helper));
// Override again but tell helper this string was explicitly user-provided.
helper.ViewData.ModelMetadata.HasNonDefaultEditFormat = true;
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, "Another string"),
DefaultEditorTemplates.DateTimeInputTemplate(helper));
}
public static TheoryDataSet DateTimeInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("DateTimeInputTemplateHtmlAttributeData")]
public void DateTimeInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.DateTimeInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("DateTimeInputTemplateHtmlAttributeData")]
public void DateTimeInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.DateTimeInputTemplate(htmlHelper));
}
[Fact]
public void DateTimeLocalInputTemplateTests()
{
var type = "datetime-local";
Assert.Equal(
GetExpectedInputTag(type, "Value"),
DefaultEditorTemplates.DateTimeLocalInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
GetExpectedInputTag(type, "<script>alert('XSS!')</script>"),
DefaultEditorTemplates.DateTimeLocalInputTemplate(MakeHtmlHelper("")));
var epocInLocalTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime();
var helper = MakeHtmlHelper(epocInLocalTime);
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString(CultureInfo.CurrentCulture)),
DefaultEditorTemplates.DateTimeLocalInputTemplate(helper));
helper.Html5DateRenderingMode = Html5DateRenderingMode.Rfc3339;
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("yyyy-MM-ddTHH:mm:ss.fff")),
DefaultEditorTemplates.DateTimeLocalInputTemplate(helper));
// Override FormattedModelValue and let helper think this string came from a default [DataType] attribute.
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("yyyy-MM-ddTHH:mm:ss.fff")),
DefaultEditorTemplates.DateTimeLocalInputTemplate(helper));
// Override again but tell helper this string was explicitly user-provided.
helper.ViewData.ModelMetadata.HasNonDefaultEditFormat = true;
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, "Another string"),
DefaultEditorTemplates.DateTimeLocalInputTemplate(helper));
}
public static TheoryDataSet DateTimeLocalInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("DateTimeLocalInputTemplateHtmlAttributeData")]
public void DateTimeLocalInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.DateTimeLocalInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("DateTimeLocalInputTemplateHtmlAttributeData")]
public void DateTimeLocalInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.DateTimeLocalInputTemplate(htmlHelper));
}
[Fact]
public void DateInputTemplateTests()
{
var type = "date";
Assert.Equal(
GetExpectedInputTag(type, "Value"),
DefaultEditorTemplates.DateInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
GetExpectedInputTag(type, "<script>alert('XSS!')</script>"),
DefaultEditorTemplates.DateInputTemplate(MakeHtmlHelper("")));
var epocInLocalTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime();
var helper = MakeHtmlHelper(epocInLocalTime);
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString(CultureInfo.CurrentCulture)),
DefaultEditorTemplates.DateInputTemplate(helper));
helper.Html5DateRenderingMode = Html5DateRenderingMode.Rfc3339;
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("yyyy-MM-dd")),
DefaultEditorTemplates.DateInputTemplate(helper));
// Override FormattedModelValue and let helper think this string came from a default [DataType] attribute.
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("yyyy-MM-dd")),
DefaultEditorTemplates.DateInputTemplate(helper));
// Override again but tell helper this string was explicitly user-provided.
helper.ViewData.ModelMetadata.HasNonDefaultEditFormat = true;
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, "Another string"),
DefaultEditorTemplates.DateInputTemplate(helper));
}
public static TheoryDataSet DateInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("DateInputTemplateHtmlAttributeData")]
public void DateInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.DateInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("DateInputTemplateHtmlAttributeData")]
public void DateInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.DateInputTemplate(htmlHelper));
}
[Fact]
public void TimeInputTemplateTests()
{
var type = "time";
Assert.Equal(
GetExpectedInputTag(type, "Value"),
DefaultEditorTemplates.TimeInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
GetExpectedInputTag(type, "<script>alert('XSS!')</script>"),
DefaultEditorTemplates.TimeInputTemplate(MakeHtmlHelper("")));
var epocInLocalTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime();
var helper = MakeHtmlHelper(epocInLocalTime);
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString(CultureInfo.CurrentCulture)),
DefaultEditorTemplates.TimeInputTemplate(helper));
helper.Html5DateRenderingMode = Html5DateRenderingMode.Rfc3339;
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("HH:mm:ss.fff")),
DefaultEditorTemplates.TimeInputTemplate(helper));
// Override FormattedModelValue and let helper think this string came from a default [DataType] attribute.
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, epocInLocalTime.ToString("HH:mm:ss.fff")),
DefaultEditorTemplates.TimeInputTemplate(helper));
// Override again but tell helper this string was explicitly user-provided.
helper.ViewData.ModelMetadata.HasNonDefaultEditFormat = true;
helper.ViewData.TemplateInfo.FormattedModelValue = "Another string";
Assert.Equal(
GetExpectedInputTag(type, "Another string"),
DefaultEditorTemplates.TimeInputTemplate(helper));
}
public static TheoryDataSet TimeInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("TimeInputTemplateHtmlAttributeData")]
public void TimeInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.TimeInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("TimeInputTemplateHtmlAttributeData")]
public void TimeInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper("Value");
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.TimeInputTemplate(htmlHelper));
}
// NumberInputTemplate
[Fact]
public void NumberInputTemplateTests()
{
Assert.Equal(
" ",
DefaultEditorTemplates.NumberInputTemplate(MakeHtmlHelper("Value")));
Assert.Equal(
" alert('XSS!')</script>\" />",
DefaultEditorTemplates.NumberInputTemplate(MakeHtmlHelper("")));
}
public static TheoryDataSet NumberInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("NumberInputTemplateHtmlAttributeData")]
public void NumberInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper(10);
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.NumberInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("NumberInputTemplateHtmlAttributeData")]
public void NumberInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var htmlHelper = MakeHtmlHelper(10);
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.NumberInputTemplate(htmlHelper));
}
// ColorInputTemplate
[Fact]
public void ColorInputTemplateTests()
{
Assert.Equal(
" ",
DefaultEditorTemplates.ColorInputTemplate(MakeHtmlHelper("#33F4CC")));
var color = Color.FromArgb(0x33, 0xf4, 0xcc);
Assert.Equal(
" ",
DefaultEditorTemplates.ColorInputTemplate(MakeHtmlHelper(color)));
Assert.Equal(
" alert('XSS!')</script>\" />",
DefaultEditorTemplates.ColorInputTemplate(MakeHtmlHelper("")));
}
public static TheoryDataSet ColorInputTemplateHtmlAttributeData
{
get
{
return new TheoryDataSet
{
{
new { @class = "form-control" },
" "
},
{
new { @class = "form-control", custom = "foo" },
" "
}
};
}
}
[Theory]
[PropertyData("ColorInputTemplateHtmlAttributeData")]
public void ColorInputTemplate_AddsHtmlAttributes(object htmlAttributes, string expectedHtml)
{
var color = Color.FromArgb(0x33, 0xf4, 0xcc);
var htmlHelper = MakeHtmlHelper(color);
htmlHelper.ViewContext.ViewBag.htmlAttributes = htmlAttributes;
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.ColorInputTemplate(htmlHelper));
}
[Theory]
[PropertyData("ColorInputTemplateHtmlAttributeData")]
public void ColorInputTemplate_AddsHtmlAttributesDictionary(object htmlAttributes, string expectedHtml)
{
var color = Color.FromArgb(0x33, 0xf4, 0xcc);
var htmlHelper = MakeHtmlHelper(color);
htmlHelper.ViewContext.ViewBag.htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
Assert.Equal(
expectedHtml,
DefaultEditorTemplates.ColorInputTemplate(htmlHelper));
}
// Helpers
private static string GetExpectedInputTag(string type, string value)
{
return string.Format(" ", type, value);
}
private HtmlHelper MakeHtmlHelper(object model)
{
return MakeHtmlHelper(model, model);
}
private HtmlHelper MakeHtmlHelper(object model, object formattedModelValue)
{
ViewDataDictionary viewData = new ViewDataDictionary(model);
viewData.TemplateInfo.HtmlFieldPrefix = "FieldPrefix";
viewData.TemplateInfo.FormattedModelValue = formattedModelValue;
viewData.ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => model, typeof(TModel));
Mock mockHttpContext = new Mock();
mockHttpContext.Setup(o => o.Items).Returns(new Hashtable());
ViewContext viewContext = new ViewContext(new ControllerContext { HttpContext = mockHttpContext.Object }, new DummyView(), viewData, new TempDataDictionary(), new StringWriter())
{
HttpContext = mockHttpContext.Object
};
// A new helper instance, is executing within a new scope, so it needs to be reset.
ScopeStorage.CurrentProvider.CurrentScope = new ScopeStorageDictionary();
return new HtmlHelper(viewContext, new SimpleViewDataContainer(viewData));
}
private class DummyView : IView
{
public void Render(ViewContext viewContext, TextWriter writer)
{
throw new NotImplementedException();
}
}
private string RunWithoutViewEngine(Func testCode)
{
lock (ViewEngines.Engines)
{
List viewEngines = new List(ViewEngines.Engines);
ViewEngines.Engines.Clear();
try
{
return testCode();
}
finally
{
foreach (var engine in viewEngines)
{
ViewEngines.Engines.Add(engine);
}
}
}
}
public void Dispose()
{
// Reset ScopeStorage (written via e.g. ScopeStorage.CurrentProvider.CurrentScope) between tests to avoid unexpected interactions.
ScopeStorage.CurrentProvider = new StaticScopeStorageProvider();
ScopeStorage.GlobalScope.Clear();
}
}
}