Add more tests of `<input/>` tag helper
- scenarios where helper takes different code paths were not well-explored nits: - improve a few comments and names - refactor some setup code into helper methods - use `EmptyModelMetadataProvider`, not `DataAnnotationsModelMetadataProvider` Test gap around `GenerateTextBox()`'s `format` argument is temporary.
This commit is contained in:
parent
6c4b1398b8
commit
10f7234c61
|
|
@ -7,14 +7,15 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TagHelpers
|
namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
{
|
{
|
||||||
public class InputTagHelperTest
|
public class InputTagHelperTest
|
||||||
{
|
{
|
||||||
// Model (List<Model> or Model instance), container type (Model or NestModel), model accessor,
|
// Top-level container (List<Model> or Model instance), immediate container type (Model or NestModel),
|
||||||
// property path / id, expected value.
|
// model accessor, expression path / id, expected value.
|
||||||
public static TheoryData<object, Type, Func<object>, NameAndId, string> TestDataSet
|
public static TheoryData<object, Type, Func<object>, NameAndId, string> TestDataSet
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -74,7 +75,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(TestDataSet))]
|
[MemberData(nameof(TestDataSet))]
|
||||||
public async Task ProcessAsync_GeneratesExpectedOutput(
|
public async Task ProcessAsync_GeneratesExpectedOutput(
|
||||||
object model,
|
object container,
|
||||||
Type containerType,
|
Type containerType,
|
||||||
Func<object> modelAccessor,
|
Func<object> modelAccessor,
|
||||||
NameAndId nameAndId,
|
NameAndId nameAndId,
|
||||||
|
|
@ -93,39 +94,35 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var expectedContent = "original content";
|
var expectedContent = "original content";
|
||||||
var expectedTagName = "not-input";
|
var expectedTagName = "not-input";
|
||||||
|
|
||||||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
var context = new TagHelperContext(new Dictionary<string, object>());
|
||||||
|
var originalAttributes = new Dictionary<string, string>
|
||||||
// Property name is either nameof(Model.Text) or nameof(NestedModel.Text).
|
|
||||||
var metadata = metadataProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName: "Text");
|
|
||||||
var modelExpression = new ModelExpression(nameAndId.Name, metadata);
|
|
||||||
|
|
||||||
var tagHelperContext = new TagHelperContext(new Dictionary<string, object>());
|
|
||||||
var htmlAttributes = new Dictionary<string, string>
|
|
||||||
{
|
{
|
||||||
{ "class", "form-control" },
|
{ "class", "form-control" },
|
||||||
};
|
};
|
||||||
var output = new TagHelperOutput(expectedTagName, htmlAttributes, expectedContent)
|
var output = new TagHelperOutput(expectedTagName, originalAttributes, expectedContent)
|
||||||
{
|
{
|
||||||
SelfClosing = false,
|
SelfClosing = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
|
var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider())
|
||||||
{
|
{
|
||||||
ValidationAttributes =
|
ValidationAttributes =
|
||||||
{
|
{
|
||||||
{ "valid", "from validation attributes" },
|
{ "valid", "from validation attributes" },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
|
|
||||||
var tagHelper = new InputTagHelper
|
// Property name is either nameof(Model.Text) or nameof(NestedModel.Text).
|
||||||
{
|
var tagHelper = GetTagHelper(
|
||||||
Generator = htmlGenerator,
|
htmlGenerator,
|
||||||
For = modelExpression,
|
container,
|
||||||
ViewContext = viewContext,
|
containerType,
|
||||||
};
|
modelAccessor,
|
||||||
|
propertyName: nameof(Model.Text),
|
||||||
|
expressionName: nameAndId.Name);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await tagHelper.ProcessAsync(tagHelperContext, output);
|
await tagHelper.ProcessAsync(context, output);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(expectedAttributes, output.Attributes);
|
Assert.Equal(expectedAttributes, output.Attributes);
|
||||||
|
|
@ -134,6 +131,379 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Assert.Equal(expectedTagName, output.TagName);
|
Assert.Equal(expectedTagName, output.TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ProcessAsync_CallsGenerateCheckBox_WithExpectedParameters()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var originalContent = "something";
|
||||||
|
var originalTagName = "not-input";
|
||||||
|
var expectedContent = originalContent + "<input class=\"form-control\" /><hidden />";
|
||||||
|
|
||||||
|
var context = new TagHelperContext(allAttributes: new Dictionary<string, object>());
|
||||||
|
var originalAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
var output = new TagHelperOutput(originalTagName, originalAttributes, content: originalContent)
|
||||||
|
{
|
||||||
|
SelfClosing = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
|
var tagHelper = GetTagHelper(htmlGenerator.Object, model: false, propertyName: nameof(Model.IsACar));
|
||||||
|
var tagBuilder = new TagBuilder("input")
|
||||||
|
{
|
||||||
|
Attributes =
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
htmlGenerator
|
||||||
|
.Setup(mock => mock.GenerateCheckBox(
|
||||||
|
tagHelper.ViewContext,
|
||||||
|
tagHelper.For.Metadata,
|
||||||
|
tagHelper.For.Name,
|
||||||
|
null, // isChecked
|
||||||
|
It.IsAny<object>())) // htmlAttributes
|
||||||
|
.Returns(tagBuilder)
|
||||||
|
.Verifiable();
|
||||||
|
htmlGenerator
|
||||||
|
.Setup(mock => mock.GenerateHiddenForCheckbox(
|
||||||
|
tagHelper.ViewContext,
|
||||||
|
tagHelper.For.Metadata,
|
||||||
|
tagHelper.For.Name))
|
||||||
|
.Returns(new TagBuilder("hidden"))
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await tagHelper.ProcessAsync(context, output);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
htmlGenerator.Verify();
|
||||||
|
|
||||||
|
Assert.Empty(output.Attributes); // Moved to Content and cleared
|
||||||
|
Assert.Equal(expectedContent, output.Content);
|
||||||
|
Assert.False(output.SelfClosing);
|
||||||
|
Assert.Empty(output.TagName); // Cleared
|
||||||
|
}
|
||||||
|
|
||||||
|
[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(
|
||||||
|
string dataTypeName,
|
||||||
|
string inputTypeName,
|
||||||
|
string model)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var contextAttributes = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
if (!string.IsNullOrEmpty(inputTypeName))
|
||||||
|
{
|
||||||
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control hidden-control" },
|
||||||
|
{ "type", inputTypeName ?? "hidden" }, // Generator restores type attribute; adds "hidden" if none.
|
||||||
|
};
|
||||||
|
var expectedContent = "something";
|
||||||
|
var expectedTagName = "not-input";
|
||||||
|
|
||||||
|
var context = new TagHelperContext(allAttributes: contextAttributes);
|
||||||
|
var originalAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent)
|
||||||
|
{
|
||||||
|
SelfClosing = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
|
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
|
||||||
|
tagHelper.For.Metadata.DataTypeName = dataTypeName;
|
||||||
|
tagHelper.InputTypeName = inputTypeName;
|
||||||
|
|
||||||
|
var tagBuilder = new TagBuilder("input")
|
||||||
|
{
|
||||||
|
Attributes =
|
||||||
|
{
|
||||||
|
{ "class", "hidden-control" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
htmlGenerator
|
||||||
|
.Setup(mock => mock.GenerateHidden(
|
||||||
|
tagHelper.ViewContext,
|
||||||
|
tagHelper.For.Metadata,
|
||||||
|
tagHelper.For.Name,
|
||||||
|
model, // value
|
||||||
|
false, // useViewData
|
||||||
|
null)) // htmlAttributes
|
||||||
|
.Returns(tagBuilder)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await tagHelper.ProcessAsync(context, output);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
htmlGenerator.Verify();
|
||||||
|
|
||||||
|
Assert.Equal(expectedAttributes, output.Attributes);
|
||||||
|
Assert.Equal(expectedContent, output.Content);
|
||||||
|
Assert.True(output.SelfClosing);
|
||||||
|
Assert.Equal(expectedTagName, output.TagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(null, "password", null)]
|
||||||
|
[InlineData(null, "Password", "not-null")]
|
||||||
|
[InlineData(null, "PASSword", null)]
|
||||||
|
[InlineData(null, "PASSWORD", "not-null")]
|
||||||
|
[InlineData("password", null, null)]
|
||||||
|
[InlineData("Password", null, "not-null")]
|
||||||
|
[InlineData("PASSword", null, null)]
|
||||||
|
[InlineData("PASSWORD", null, "not-null")]
|
||||||
|
public async Task ProcessAsync_CallsGeneratePassword_WithExpectedParameters(
|
||||||
|
string dataTypeName,
|
||||||
|
string inputTypeName,
|
||||||
|
string model)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var contextAttributes = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
if (!string.IsNullOrEmpty(inputTypeName))
|
||||||
|
{
|
||||||
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control password-control" },
|
||||||
|
{ "type", inputTypeName ?? "password" }, // Generator restores type attribute; adds "password" if none.
|
||||||
|
};
|
||||||
|
var expectedContent = "something";
|
||||||
|
var expectedTagName = "not-input";
|
||||||
|
|
||||||
|
var context = new TagHelperContext(allAttributes: contextAttributes);
|
||||||
|
var originalAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent)
|
||||||
|
{
|
||||||
|
SelfClosing = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
|
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
|
||||||
|
tagHelper.For.Metadata.DataTypeName = dataTypeName;
|
||||||
|
tagHelper.InputTypeName = inputTypeName;
|
||||||
|
|
||||||
|
var tagBuilder = new TagBuilder("input")
|
||||||
|
{
|
||||||
|
Attributes =
|
||||||
|
{
|
||||||
|
{ "class", "password-control" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
htmlGenerator
|
||||||
|
.Setup(mock => mock.GeneratePassword(
|
||||||
|
tagHelper.ViewContext,
|
||||||
|
tagHelper.For.Metadata,
|
||||||
|
tagHelper.For.Name,
|
||||||
|
null, // value
|
||||||
|
null)) // htmlAttributes
|
||||||
|
.Returns(tagBuilder)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await tagHelper.ProcessAsync(context, output);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
htmlGenerator.Verify();
|
||||||
|
|
||||||
|
Assert.Equal(expectedAttributes, output.Attributes);
|
||||||
|
Assert.Equal(expectedContent, output.Content);
|
||||||
|
Assert.True(output.SelfClosing);
|
||||||
|
Assert.Equal(expectedTagName, output.TagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("radio", null)]
|
||||||
|
[InlineData("Radio", "not-null")]
|
||||||
|
[InlineData("RADio", null)]
|
||||||
|
[InlineData("RADIO", "not-null")]
|
||||||
|
public async Task ProcessAsync_CallsGenerateRadioButton_WithExpectedParameters(
|
||||||
|
string inputTypeName,
|
||||||
|
string model)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var value = "match"; // Real generator would use this for comparison with For.Metadata.Model.
|
||||||
|
var contextAttributes = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
{ "value", value },
|
||||||
|
};
|
||||||
|
if (!string.IsNullOrEmpty(inputTypeName))
|
||||||
|
{
|
||||||
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control radio-control" },
|
||||||
|
{ "type", inputTypeName ?? "radio" }, // Generator restores type attribute; adds "radio" if none.
|
||||||
|
{ "value", value },
|
||||||
|
};
|
||||||
|
var expectedContent = "something";
|
||||||
|
var expectedTagName = "not-input";
|
||||||
|
|
||||||
|
var context = new TagHelperContext(allAttributes: contextAttributes);
|
||||||
|
var originalAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent)
|
||||||
|
{
|
||||||
|
SelfClosing = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
|
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
|
||||||
|
tagHelper.InputTypeName = inputTypeName;
|
||||||
|
tagHelper.Value = value;
|
||||||
|
|
||||||
|
var tagBuilder = new TagBuilder("input")
|
||||||
|
{
|
||||||
|
Attributes =
|
||||||
|
{
|
||||||
|
{ "class", "radio-control" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
htmlGenerator
|
||||||
|
.Setup(mock => mock.GenerateRadioButton(
|
||||||
|
tagHelper.ViewContext,
|
||||||
|
tagHelper.For.Metadata,
|
||||||
|
tagHelper.For.Name,
|
||||||
|
value,
|
||||||
|
null, // isChecked
|
||||||
|
null)) // htmlAttributes
|
||||||
|
.Returns(tagBuilder)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await tagHelper.ProcessAsync(context, output);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
htmlGenerator.Verify();
|
||||||
|
|
||||||
|
Assert.Equal(expectedAttributes, output.Attributes);
|
||||||
|
Assert.Equal(expectedContent, output.Content);
|
||||||
|
Assert.True(output.SelfClosing);
|
||||||
|
Assert.Equal(expectedTagName, output.TagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[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")]
|
||||||
|
public async Task ProcessAsync_CallsGenerateTextBox_WithExpectedParameters(
|
||||||
|
string dataTypeName,
|
||||||
|
string inputTypeName,
|
||||||
|
string model)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var contextAttributes = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
if (!string.IsNullOrEmpty(inputTypeName))
|
||||||
|
{
|
||||||
|
contextAttributes["type"] = inputTypeName; // Support restoration of type attribute, if any.
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control text-control" },
|
||||||
|
{ "type", inputTypeName ?? "text" }, // Generator restores type attribute; adds "text" if none.
|
||||||
|
};
|
||||||
|
var expectedContent = "something";
|
||||||
|
var expectedTagName = "not-input";
|
||||||
|
|
||||||
|
var context = new TagHelperContext(allAttributes: contextAttributes);
|
||||||
|
var originalAttributes = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "class", "form-control" },
|
||||||
|
};
|
||||||
|
var output = new TagHelperOutput(expectedTagName, originalAttributes, content: expectedContent)
|
||||||
|
{
|
||||||
|
SelfClosing = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var htmlGenerator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
|
||||||
|
var tagHelper = GetTagHelper(htmlGenerator.Object, model, nameof(Model.Text));
|
||||||
|
tagHelper.For.Metadata.DataTypeName = dataTypeName;
|
||||||
|
tagHelper.InputTypeName = inputTypeName;
|
||||||
|
|
||||||
|
var tagBuilder = new TagBuilder("input")
|
||||||
|
{
|
||||||
|
Attributes =
|
||||||
|
{
|
||||||
|
{ "class", "text-control" },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
htmlGenerator
|
||||||
|
.Setup(mock => mock.GenerateTextBox(
|
||||||
|
tagHelper.ViewContext,
|
||||||
|
tagHelper.For.Metadata,
|
||||||
|
tagHelper.For.Name,
|
||||||
|
model, // value
|
||||||
|
null, // format
|
||||||
|
null)) // htmlAttributes
|
||||||
|
.Returns(tagBuilder)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await tagHelper.ProcessAsync(context, output);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
htmlGenerator.Verify();
|
||||||
|
|
||||||
|
Assert.Equal(expectedAttributes, output.Attributes);
|
||||||
|
Assert.Equal(expectedContent, output.Content);
|
||||||
|
Assert.True(output.SelfClosing);
|
||||||
|
Assert.Equal(expectedTagName, output.TagName);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task TagHelper_RestoresTypeAndValue_IfForNotBound()
|
public async Task TagHelper_RestoresTypeAndValue_IfForNotBound()
|
||||||
{
|
{
|
||||||
|
|
@ -147,33 +517,21 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
var expectedContent = "original content";
|
var expectedContent = "original content";
|
||||||
var expectedTagName = "input";
|
var expectedTagName = "input";
|
||||||
|
|
||||||
var metadataProvider = new DataAnnotationsModelMetadataProvider();
|
|
||||||
var metadata = metadataProvider.GetMetadataForProperty(
|
|
||||||
modelAccessor: () => null,
|
|
||||||
containerType: typeof(Model),
|
|
||||||
propertyName: nameof(Model.Text));
|
|
||||||
var modelExpression = new ModelExpression(nameof(Model.Text), metadata);
|
|
||||||
|
|
||||||
var tagHelperContext = new TagHelperContext(new Dictionary<string, object>());
|
var tagHelperContext = new TagHelperContext(new Dictionary<string, object>());
|
||||||
var output = new TagHelperOutput(expectedTagName, expectedAttributes, expectedContent)
|
var output = new TagHelperOutput(expectedTagName, expectedAttributes, expectedContent)
|
||||||
{
|
{
|
||||||
SelfClosing = false,
|
SelfClosing = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
|
var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider())
|
||||||
{
|
{
|
||||||
ValidationAttributes =
|
ValidationAttributes =
|
||||||
{
|
{
|
||||||
{ "valid", "from validation attributes" },
|
{ "valid", "from validation attributes" },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Model model = null;
|
var tagHelper = GetTagHelper(htmlGenerator, model: null, propertyName: nameof(Model.Text));
|
||||||
var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
|
tagHelper.For = null;
|
||||||
var tagHelper = new InputTagHelper
|
|
||||||
{
|
|
||||||
Generator = htmlGenerator,
|
|
||||||
ViewContext = viewContext,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await tagHelper.ProcessAsync(tagHelperContext, output);
|
await tagHelper.ProcessAsync(tagHelperContext, output);
|
||||||
|
|
@ -185,6 +543,39 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
Assert.Equal(expectedTagName, output.TagName);
|
Assert.Equal(expectedTagName, output.TagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static InputTagHelper GetTagHelper(IHtmlGenerator htmlGenerator, object model, string propertyName)
|
||||||
|
{
|
||||||
|
return GetTagHelper(
|
||||||
|
htmlGenerator,
|
||||||
|
container: new Model(),
|
||||||
|
containerType: typeof(Model),
|
||||||
|
modelAccessor: () => model,
|
||||||
|
propertyName: propertyName,
|
||||||
|
expressionName: propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputTagHelper GetTagHelper(
|
||||||
|
IHtmlGenerator htmlGenerator,
|
||||||
|
object container,
|
||||||
|
Type containerType,
|
||||||
|
Func<object> modelAccessor,
|
||||||
|
string propertyName,
|
||||||
|
string expressionName)
|
||||||
|
{
|
||||||
|
var metadataProvider = new EmptyModelMetadataProvider();
|
||||||
|
var metadata = metadataProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName);
|
||||||
|
var modelExpression = new ModelExpression(expressionName, metadata);
|
||||||
|
var viewContext = TestableHtmlGenerator.GetViewContext(container, htmlGenerator, metadataProvider);
|
||||||
|
var inputTagHelper = new InputTagHelper
|
||||||
|
{
|
||||||
|
For = modelExpression,
|
||||||
|
Generator = htmlGenerator,
|
||||||
|
ViewContext = viewContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
return inputTagHelper;
|
||||||
|
}
|
||||||
|
|
||||||
public class NameAndId
|
public class NameAndId
|
||||||
{
|
{
|
||||||
public NameAndId(string name, string id)
|
public NameAndId(string name, string id)
|
||||||
|
|
@ -203,6 +594,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
|
||||||
public string Text { get; set; }
|
public string Text { get; set; }
|
||||||
|
|
||||||
public NestedModel NestedModel { get; set; }
|
public NestedModel NestedModel { get; set; }
|
||||||
|
|
||||||
|
public bool IsACar { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NestedModel
|
private class NestedModel
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue