Unit Testing a custom TagHelper where HTML conditionally rendered based on the presence of a ValidationAttribute on the model Property
Asked Answered
S

0

8

I have a custom TagHelper which extends the OOTB InputTagHelper. I am conditionally adding attributes to it based on the presence of a custom ValidationAttribute on the model property associated with it. The code for this in the TagHelper .Process method works fine:

if (this.For.Metadata.ValidatorMetadata.OfType<NumericValidationAttribute>().Any())
{
   output?.Attributes.SetAttribute(new TagHelperAttribute("inputmode", "numeric"));
   output?.Attributes.SetAttribute(new TagHelperAttribute("pattern", "[0-9]*"));
}

My issue is in Unit Testing this. I have other Unit Tests written using the code available in the Net Core MVC Test repo: https://github.com/aspnet/Mvc/blob/master/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/

... but there's no real steer on how to create the For i.e ModelExpression for the property I want to test which has this Validation attribute associated with it: e.g.

    public class TestModel
    {
        [NumericValidation(ErrorMessage = "Error message")]
        public string Field1 { get; set; }
    }

I want to be able to populate the For.Metadata.ValidatorMetadata list for this ModelExpression and I don't know how.

The full Unit Test which doesnt work is:

[Fact]
        public void CustomInputTagHelperProcess_NumericValidationAttributeOnModelProperty_GeneratesCorrectHtml()
        {
            // Arrange
            var metadataProvider = new EmptyModelMetadataProvider();
            var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
            var model = new TestModel
            {
                Field1 = "cc",
            };
            var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(TestModel), model);
            var modelExpression = new ModelExpression(name: "Field1", modelExplorer: modelExplorer);
            var viewContext = TestableHtmlGenerator.GetViewContext(model, metadataProvider);

            var attributes = new TagHelperAttributeList
            {
                { "name", PropertyName },
                { "type", InputTypeName },
            };

            var tagHelperContext = new TagHelperContext(attributes, new Dictionary<object, object>(), nameof(CustomInputTagHelperTest));

            var output = new TagHelperOutput(
                Input,
                new TagHelperAttributeList(),
                getChildContentAsync: (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(result: null))
            {
                TagMode = TagMode.SelfClosing,
            };

            var customInputTagHelper = new CustomInputTagHelper(this.htmlGenerator)
            {
                For = this.modelExpression,
                InputTypeName = InputTypeName,
                Name = PropertyName,
                ViewContext = this.viewContext,
            };

            // Act
            customInputTagHelper.Process(this.tagHelperContext, output);

            // Assert - ensure we have an inputmode attribute on the input.
            Assert.Contains(output.Attributes, x => x.Name == "inputmode" && x.Value.ToString() == "numeric");
        }

Any thoughts?

Scottiescottish answered 10/12, 2020 at 18:1 Comment(2)
Can this link solve it?Finely
No @user1986237, I already have all that in my sample Unit Test above. I need to be able to inject ValidatorMetadata into the ModelExpression object. Thanks for the reply though.Scottiescottish

© 2022 - 2024 — McMap. All rights reserved.