Add more tests covering `asp-format` use

- also add comments requested in PR #5109 and #5205
This commit is contained in:
Doug Bunting 2016-08-30 22:38:08 -07:00
parent 4bda1cbe6d
commit 34a4c8c191
2 changed files with 127 additions and 44 deletions

View File

@ -98,8 +98,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
/// attribute to that formatted <see cref="string"/>.
/// </summary>
/// <remarks>
/// Used only the calculated "type" attribute is "text" (the most common value) e.g.
/// <see cref="InputTypeName"/> is "String". That is, <see cref="Format"/> is used when calling
/// Not used if the provided (see <see cref="InputTypeName"/>) or calculated "type" attribute value is
/// <c>checkbox</c>, <c>password</c>, or <c>radio</c>. That is, <see cref="Format"/> is used when calling
/// <see cref="IHtmlGenerator.GenerateTextBox"/>.
/// </remarks>
[HtmlAttributeName(FormatAttributeName)]
@ -110,8 +110,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
/// </summary>
/// <remarks>
/// Passed through to the generated HTML in all cases. Also used to determine the <see cref="IHtmlGenerator"/>
/// helper to call and the default <see cref="Format"/> value (when calling
/// <see cref="IHtmlGenerator.GenerateTextBox"/>).
/// helper to call and the default <see cref="Format"/> value. A default <see cref="Format"/> is not calculated
/// if the provided (see <see cref="InputTypeName"/>) or calculated "type" attribute value is <c>checkbox</c>,
/// <c>hidden</c>, <c>password</c>, or <c>radio</c>.
/// </remarks>
[HtmlAttributeName("type")]
public string InputTypeName { get; set; }
@ -358,6 +359,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
htmlAttributes: htmlAttributes);
}
// Imitate Generator.GenerateHidden() using Generator.GenerateTextBox(). This adds support for asp-format that
// is not available in Generator.GenerateHidden().
private TagBuilder GenerateHidden(ModelExplorer modelExplorer)
{
var value = For.Model;
@ -367,6 +370,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
value = Convert.ToBase64String(byteArrayValue);
}
// In DefaultHtmlGenerator(), GenerateTextBox() calls GenerateInput() _almost_ identically to how
// GenerateHidden() does and the main switch inside GenerateInput() handles InputType.Text and
// InputType.Hidden identically. No behavior differences at all when a type HTML attribute already exists.
var htmlAttributes = new Dictionary<string, object>
{
{ "type", "hidden" }

View File

@ -246,6 +246,75 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
Assert.Equal(expectedTagName, output.TagName);
}
[Theory]
[InlineData(null, "datetime")]
[InlineData("hidden", "hidden")]
public void Process_GeneratesFormattedOutput(string specifiedType, string expectedType)
{
// Arrange
var expectedAttributes = new TagHelperAttributeList
{
{ "type", expectedType },
{ "id", "DateTimeOffset" },
{ "name", "DateTimeOffset" },
{ "valid", "from validation attributes" },
{ "value", "datetime: 2011-08-31T05:30:45.0000000+03:00" },
};
var expectedTagName = "not-input";
var container = new Model
{
DateTimeOffset = new DateTimeOffset(2011, 8, 31, hour: 5, minute: 30, second: 45, offset: TimeSpan.FromHours(3))
};
var allAttributes = new TagHelperAttributeList
{
{ "type", specifiedType },
};
var context = new TagHelperContext(
allAttributes: allAttributes,
items: new Dictionary<object, object>(),
uniqueId: "test");
var output = new TagHelperOutput(
expectedTagName,
new TagHelperAttributeList(),
getChildContentAsync: (useCachedResult, encoder) =>
{
throw new Exception("getChildContentAsync should not be called.");
})
{
TagMode = TagMode.StartTagOnly,
};
var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider())
{
ValidationAttributes =
{
{ "valid", "from validation attributes" },
}
};
var tagHelper = GetTagHelper(
htmlGenerator,
container,
typeof(Model),
model: container.DateTimeOffset,
propertyName: nameof(Model.DateTimeOffset),
expressionName: nameof(Model.DateTimeOffset));
tagHelper.Format = "datetime: {0:o}";
tagHelper.InputTypeName = specifiedType;
// Act
tagHelper.Process(context, output);
// Assert
Assert.Equal(expectedAttributes, output.Attributes);
Assert.Empty(output.PreContent.GetContent());
Assert.Empty(output.Content.GetContent());
Assert.Empty(output.PostContent.GetContent());
Assert.Equal(TagMode.StartTagOnly, output.TagMode);
Assert.Equal(expectedTagName, output.TagName);
}
[Fact]
public async Task ProcessAsync_CallsGenerateCheckBox_WithExpectedParameters()
{
@ -283,6 +352,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model: false, propertyName: nameof(Model.IsACar));
tagHelper.Format = "somewhat-less-null"; // ignored
var tagBuilder = new TagBuilder("input")
{
Attributes =
@ -323,18 +394,19 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
[Theory]
[InlineData(null, "hidden", null)]
[InlineData(null, "Hidden", "not-null")]
[InlineData(null, "HIDden", null)]
[InlineData(null, "HIDDEN", "not-null")]
[InlineData("hiddeninput", null, null)]
[InlineData("HiddenInput", null, "not-null")]
[InlineData("hidDENinPUT", null, null)]
[InlineData("HIDDENINPUT", null, "not-null")]
public async Task ProcessAsync_CallsGenerateHidden_WithExpectedParameters(
[InlineData(null, "hidden", null, null)]
[InlineData(null, "Hidden", "not-null", "somewhat-less-null")]
[InlineData(null, "HIDden", null, "somewhat-less-null")]
[InlineData(null, "HIDDEN", "not-null", null)]
[InlineData("hiddeninput", null, null, null)]
[InlineData("HiddenInput", null, "not-null", null)]
[InlineData("hidDENinPUT", null, null, "somewhat-less-null")]
[InlineData("HIDDENINPUT", null, "not-null", "somewhat-less-null")]
public async Task ProcessAsync_CallsGenerateTextBox_WithExpectedParametersForHidden(
string dataTypeName,
string inputTypeName,
string model)
string model,
string format)
{
// Arrange
var contextAttributes = new TagHelperAttributeList
@ -389,6 +461,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
model,
nameof(Model.Text),
metadataProvider: metadataProvider);
tagHelper.Format = format;
tagHelper.InputTypeName = inputTypeName;
var tagBuilder = new TagBuilder("input")
@ -399,13 +472,13 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
},
};
htmlGenerator
.Setup(mock => mock.GenerateHidden(
.Setup(mock => mock.GenerateTextBox(
tagHelper.ViewContext,
tagHelper.For.ModelExplorer,
tagHelper.For.Name,
model, // value
false, // useViewData
null)) // htmlAttributes
model, // value
format,
new Dictionary<string, object> { { "type", "hidden" } })) // htmlAttributes
.Returns(tagBuilder)
.Verifiable();
@ -490,6 +563,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
model,
nameof(Model.Text),
metadataProvider: metadataProvider);
tagHelper.Format = "somewhat-less-null"; // ignored
tagHelper.InputTypeName = inputTypeName;
var tagBuilder = new TagBuilder("input")
@ -581,6 +655,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
tagHelper.Format = "somewhat-less-null"; // ignored
tagHelper.InputTypeName = inputTypeName;
tagHelper.Value = value;
@ -617,32 +692,33 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
[Theory]
[InlineData(null, null, null)]
[InlineData(null, null, "not-null")]
[InlineData(null, "string", null)]
[InlineData(null, "String", "not-null")]
[InlineData(null, "STRing", null)]
[InlineData(null, "STRING", "not-null")]
[InlineData(null, "text", null)]
[InlineData(null, "Text", "not-null")]
[InlineData(null, "TExt", null)]
[InlineData(null, "TEXT", "not-null")]
[InlineData("string", null, null)]
[InlineData("String", null, "not-null")]
[InlineData("STRing", null, null)]
[InlineData("STRING", null, "not-null")]
[InlineData("text", null, null)]
[InlineData("Text", null, "not-null")]
[InlineData("TExt", null, null)]
[InlineData("TEXT", null, "not-null")]
[InlineData("custom-datatype", null, null)]
[InlineData(null, "unknown-input-type", "not-null")]
[InlineData("Image", null, "not-null")]
[InlineData(null, "image", "not-null")]
[InlineData(null, null, null, "somewhat-less-null")]
[InlineData(null, null, "not-null", null)]
[InlineData(null, "string", null, null)]
[InlineData(null, "String", "not-null", null)]
[InlineData(null, "STRing", null, "somewhat-less-null")]
[InlineData(null, "STRING", "not-null", null)]
[InlineData(null, "text", null, null)]
[InlineData(null, "Text", "not-null", "somewhat-less-null")]
[InlineData(null, "TExt", null, null)]
[InlineData(null, "TEXT", "not-null", null)]
[InlineData("string", null, null, null)]
[InlineData("String", null, "not-null", null)]
[InlineData("STRing", null, null, null)]
[InlineData("STRING", null, "not-null", null)]
[InlineData("text", null, null, null)]
[InlineData("Text", null, "not-null", null)]
[InlineData("TExt", null, null, null)]
[InlineData("TEXT", null, "not-null", null)]
[InlineData("custom-datatype", null, null, null)]
[InlineData(null, "unknown-input-type", "not-null", null)]
[InlineData("Image", null, "not-null", "somewhat-less-null")]
[InlineData(null, "image", "not-null", null)]
public async Task ProcessAsync_CallsGenerateTextBox_WithExpectedParameters(
string dataTypeName,
string inputTypeName,
string model)
string model,
string format)
{
// Arrange
var contextAttributes = new TagHelperAttributeList
@ -697,6 +773,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
model,
nameof(Model.Text),
metadataProvider: metadataProvider);
tagHelper.Format = format;
tagHelper.InputTypeName = inputTypeName;
var tagBuilder = new TagBuilder("input")
@ -711,9 +788,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
tagHelper.ViewContext,
tagHelper.For.ModelExplorer,
tagHelper.For.Name,
model, // value
null, // format
It.Is<Dictionary<string, object>>(m => m.ContainsKey("type")))) // htmlAttributes
model, // value
format,
It.Is<Dictionary<string, object>>(m => m.ContainsKey("type")))) // htmlAttributes
.Returns(tagBuilder)
.Verifiable();