예제 #1
0
    public void CopyConstructorInitializesModelAndModelMetadataBasedOnSource()
    {
        // Arrange
        var metadataProvider = new EmptyModelMetadataProvider();
        var model            = new TestModel();
        var source           = new ViewDataDictionary(metadataProvider)
        {
            ModelExplorer = metadataProvider.GetModelExplorerForType(typeof(TestModel), model),
        };

        source["foo"] = "bar";
        source.TemplateInfo.HtmlFieldPrefix = "prefix";

        // Act
        var viewData = new ViewDataDictionary(source);

        // Assert
        Assert.NotNull(viewData.ModelState);
        Assert.NotNull(viewData.TemplateInfo);
        Assert.Equal("prefix", viewData.TemplateInfo.HtmlFieldPrefix);
        Assert.NotSame(source.TemplateInfo, viewData.TemplateInfo);
        Assert.Same(model, viewData.Model);
        Assert.NotNull(viewData.ModelMetadata);
        Assert.Equal(typeof(TestModel), viewData.ModelMetadata.ModelType);
        Assert.Same(source.ModelMetadata, viewData.ModelMetadata);
        Assert.Equal(source.Count, viewData.Count);
        Assert.Equal("bar", viewData["foo"]);
        Assert.IsType <CopyOnWriteDictionary <string, object> >(viewData.Data);
    }
예제 #2
0
    public void Process_WithEmptyForName_Throws()
    {
        // Arrange
        var expectedMessage = "The name of an HTML field cannot be null or empty. Instead use methods " +
                              "Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper.Editor or Microsoft.AspNetCore.Mvc.Rendering." +
                              "IHtmlHelper`1.EditorFor with a non-empty htmlFieldName argument value.";
        var expectedTagName = "textarea";

        var metadataProvider = new EmptyModelMetadataProvider();
        var htmlGenerator    = new TestableHtmlGenerator(metadataProvider);
        var model            = "model-value";
        var modelExplorer    = metadataProvider.GetModelExplorerForType(typeof(string), model);
        var modelExpression  = new ModelExpression(name: string.Empty, modelExplorer: modelExplorer);
        var viewContext      = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
        var tagHelper        = new TextAreaTagHelper(htmlGenerator)
        {
            For         = modelExpression,
            ViewContext = viewContext,
        };

        var context = new TagHelperContext(new TagHelperAttributeList(), new Dictionary <object, object>(), "test");
        var output  = new TagHelperOutput(
            expectedTagName,
            new TagHelperAttributeList(),
            (_, __) => Task.FromResult <TagHelperContent>(new DefaultTagHelperContent()));

        // Act & Assert
        ExceptionAssert.ThrowsArgument(
            () => tagHelper.Process(context, output),
            paramName: "expression",
            exceptionMessage: expectedMessage);
    }
    public void LabelHelpers_DisplayMetadataPropertyNameForProperty()
    {
        // Arrange
        var propertyName = "Property1";

        var provider = new EmptyModelMetadataProvider();

        var modelExplorer = provider
                            .GetModelExplorerForType(typeof(DefaultTemplatesUtilities.ObjectTemplateModel), model: null)
                            .GetExplorerForProperty(propertyName);

        var helper = DefaultTemplatesUtilities.GetHtmlHelper();

        helper.ViewData.ModelExplorer = modelExplorer;

        // Act
        var labelResult         = helper.Label(expression: string.Empty);
        var labelForResult      = helper.LabelFor(m => m);
        var labelForModelResult = helper.LabelForModel();

        // Assert
        Assert.Equal("<label for=\"\">HtmlEncode[[" + propertyName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelResult));
        Assert.Equal("<label for=\"\">HtmlEncode[[" + propertyName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelForResult));
        Assert.Equal("<label for=\"\">HtmlEncode[[" + propertyName + "]]</label>", HtmlContentUtilities.HtmlContentToString(labelForModelResult));
    }
        public void AddAndTrackValidationAttributes_AddsAttributes()
        {
            // Arrange
            var expectedMessage   = $"The field {nameof(Model.HasValidatorsProperty)} must be a number.";
            var metadataProvider  = new EmptyModelMetadataProvider();
            var attributeProvider = GetAttributeProvider(metadataProvider);
            var viewContext       = GetViewContext <Model>(model: null, metadataProvider: metadataProvider);
            var attributes        = new SortedDictionary <string, string>(StringComparer.Ordinal);
            var modelExplorer     = metadataProvider
                                    .GetModelExplorerForType(typeof(Model), model: null)
                                    .GetExplorerForProperty(nameof(Model.HasValidatorsProperty));

            // Act
            attributeProvider.AddAndTrackValidationAttributes(
                viewContext,
                modelExplorer,
                nameof(Model.HasValidatorsProperty),
                attributes);

            // Assert
            Assert.Collection(
                attributes,
                kvp =>
            {
                Assert.Equal("data-val", kvp.Key);
                Assert.Equal("true", kvp.Value);
            },
                kvp =>
            {
                Assert.Equal("data-val-number", kvp.Key);
                Assert.Equal(expectedMessage, kvp.Value);
            });
        }
예제 #5
0
        private static ModelExpression CreateModelExpression(string name)
        {
            var modelMetadataProvider = new EmptyModelMetadataProvider();

            return(new ModelExpression(
                       name,
                       modelMetadataProvider.GetModelExplorerForType(typeof(object), model: null)));
        }
        static ModelExpression CreateModelExpression(string name)
        {
            var modelMetadataProvider = new EmptyModelMetadataProvider();

            var me = new ModelExpression(name, modelMetadataProvider
                                         .GetModelExplorerForType(typeof(Model), null)
                                         .GetExplorerForProperty(name));

            var dn = me.ModelExplorer.Metadata.GetDisplayName();

            return(me);
        }
예제 #7
0
    public void ModelType_UsesRuntimeType()
    {
        // Arrange
        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(typeof(BaseClass), new DerivedClass());

        // Act
        var modelType = modelExplorer.ModelType;

        // Assert
        Assert.Equal(typeof(DerivedClass), modelType);
    }
예제 #8
0
    public void ModelType_UsesDeclaredType_WhenModelIsNull()
    {
        // Arrange
        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(typeof(BaseClass), model: null);

        // Act
        var modelType = modelExplorer.ModelType;

        // Assert
        Assert.Equal(typeof(BaseClass), modelType);
    }
예제 #9
0
    public void GetPropertyExplorer_DeferredModelAccess_ContainerModelIsNull()
    {
        // Arrange
        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(typeof(BaseClass), model: null);

        var propertyExplorer = modelExplorer.GetExplorerForProperty("Base1");

        // Act
        var propertyValue = propertyExplorer.Model;

        // Assert
        Assert.Null(propertyValue);
    }
    public void GetSimpleDisplayText_WithoutSimpleDisplayProperty(
        object model,
        Type modelType,
        string expectedResult)
    {
        // Arrange
        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(modelType, model);

        // Act
        var result = modelExplorer.GetSimpleDisplayText();

        // Assert
        Assert.Equal(expectedResult, result);
    }
예제 #11
0
    public void GetPropertyExplorer_ReturnsNull_ForPropertyNotFound()
    {
        // Arrange
        var model = new DerivedClass()
        {
            Base1 = 5,
        };

        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(typeof(BaseClass), model);

        // Act
        var propertyExplorer = modelExplorer.GetExplorerForProperty("BadName");

        // Assert
        Assert.Null(propertyExplorer);
    }
예제 #12
0
    public void ModelSetter_PreservesSourceMetadata_IfModelCompatible(Type sourceType, object model)
    {
        // Arrange
        var metadataProvider = new EmptyModelMetadataProvider();
        var source           = new ViewDataDictionary(metadataProvider)
        {
            ModelExplorer = metadataProvider.GetModelExplorerForType(sourceType, model: null),
        };
        var viewData = new ViewDataDictionary(source);

        // Act
        viewData.Model = model;

        // Assert
        Assert.NotSame(source.ModelExplorer, viewData.ModelExplorer);
        Assert.Same(source.ModelMetadata, viewData.ModelMetadata);
    }
예제 #13
0
    public void Properties_UsesDeclaredType_WhenModelIsNull()
    {
        // Arrange
        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(typeof(BaseClass), model: null);

        // Act
        var properties = modelExplorer.Properties.ToArray();

        // Assert
        Assert.Single(properties);

        var baseProperty = Assert.Single(properties, p => p.Metadata.PropertyName == "Base1");

        Assert.Equal(typeof(int), baseProperty.Metadata.ModelType);
        Assert.Equal(typeof(BaseClass), baseProperty.Metadata.ContainerType);
        Assert.Same(modelExplorer, baseProperty.Container);
    }
예제 #14
0
    public void Process_WithEmptyForName_DoesNotThrow_WithName()
    {
        // Arrange
        var expectedAttributeValue = "-expression-";
        var expectedContent        = Environment.NewLine + "HtmlEncode[[model-value]]";
        var expectedTagName        = "textarea";

        var metadataProvider = new EmptyModelMetadataProvider();
        var htmlGenerator    = new TestableHtmlGenerator(metadataProvider);
        var model            = "model-value";
        var modelExplorer    = metadataProvider.GetModelExplorerForType(typeof(string), model);
        var modelExpression  = new ModelExpression(name: string.Empty, modelExplorer: modelExplorer);
        var viewContext      = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
        var tagHelper        = new TextAreaTagHelper(htmlGenerator)
        {
            For         = modelExpression,
            Name        = expectedAttributeValue,
            ViewContext = viewContext,
        };

        var attributes = new TagHelperAttributeList
        {
            { "name", expectedAttributeValue },
        };

        var context = new TagHelperContext(attributes, new Dictionary <object, object>(), "test");
        var output  = new TagHelperOutput(
            expectedTagName,
            new TagHelperAttributeList(),
            (_, __) => Task.FromResult <TagHelperContent>(new DefaultTagHelperContent()));

        // Act
        tagHelper.Process(context, output);

        // Assert
        Assert.Equal(expectedTagName, output.TagName);
        Assert.Equal(expectedContent, HtmlContentUtilities.HtmlContentToString(output.Content));

        var attribute = Assert.Single(output.Attributes);

        Assert.Equal("name", attribute.Name);
        Assert.Equal(expectedAttributeValue, attribute.Value);
    }
        public void AddAndTrackValidationAttributes_DoesNotCallAddMethod_IfPropertyAlreadyRendered()
        {
            // Arrange
            var metadataProvider = new EmptyModelMetadataProvider();
            var viewContext      = GetViewContext <Model>(model: null, metadataProvider: metadataProvider);

            viewContext.FormContext.RenderedField(nameof(Model.HasValidatorsProperty), value: true);

            var attributes    = new SortedDictionary <string, string>(StringComparer.Ordinal);
            var modelExplorer = metadataProvider
                                .GetModelExplorerForType(typeof(Model), model: null)
                                .GetExplorerForProperty(nameof(Model.HasValidatorsProperty));

            var attributeProviderMock = new Mock <ValidationHtmlAttributeProvider>()
            {
                CallBase = true
            };

            attributeProviderMock
            .Setup(p => p.AddValidationAttributes(
                       It.IsAny <ViewContext>(),
                       It.IsAny <ModelExplorer>(),
                       It.IsAny <IDictionary <string, string> >()))
            .Verifiable();
            var attributeProvider = attributeProviderMock.Object;

            // Act
            attributeProvider.AddAndTrackValidationAttributes(
                viewContext,
                modelExplorer,
                nameof(Model.HasValidatorsProperty),
                attributes);

            // Assert
            Assert.Empty(attributes);
            attributeProviderMock.Verify(
                p => p.AddValidationAttributes(
                    It.IsAny <ViewContext>(),
                    It.IsAny <ModelExplorer>(),
                    It.IsAny <IDictionary <string, string> >()),
                Times.Never);
        }
        public void AddValidationAttributes_AddsNothing_IfPropertyHasNoValidators()
        {
            // Arrange
            var metadataProvider  = new EmptyModelMetadataProvider();
            var attributeProvider = GetAttributeProvider(metadataProvider);
            var viewContext       = GetViewContext <Model>(model: null, metadataProvider: metadataProvider);
            var attributes        = new SortedDictionary <string, string>(StringComparer.Ordinal);
            var modelExplorer     = metadataProvider
                                    .GetModelExplorerForType(typeof(Model), model: null)
                                    .GetExplorerForProperty(nameof(Model.Property));

            // Act
            attributeProvider.AddValidationAttributes(
                viewContext,
                modelExplorer,
                attributes);

            // Assert
            Assert.Empty(attributes);
        }
예제 #17
0
        public ValidationClassTagHelperTestsFixture()
        {
            Model            = "Foobar";
            ValidationClass  = "govuk-input--error";
            MetadataProvider = new EmptyModelMetadataProvider();
            ModelExplorer    = MetadataProvider.GetModelExplorerForType(typeof(string), Model);
            ModelExpression  = new ModelExpression("", ModelExplorer);
            ViewContext      = new ViewContext();

            TagHelper = new ValidationClassTagHelper
            {
                For             = ModelExpression,
                ValidationClass = ValidationClass,
                ViewContext     = ViewContext
            };

            TagHelperOutput = new TagHelperOutput(
                "input",
                new TagHelperAttributeList(),
                (useCachedResult, encoder) => Task.FromResult <TagHelperContent>(null));
        }
예제 #18
0
    public void ModelSetter_UpdatesModelMetadata_IfModelIncompatibleWithSourceMetadata(
        Type sourceType,
        object model,
        Type expectedType)
    {
        // Arrange
        var metadataProvider = new EmptyModelMetadataProvider();
        var source           = new ViewDataDictionary(metadataProvider)
        {
            ModelExplorer = metadataProvider.GetModelExplorerForType(sourceType, model: null),
        };
        var sourceMetadata = source.ModelMetadata;
        var viewData       = new ViewDataDictionary(source);

        // Act
        viewData.Model = model;

        // Assert
        Assert.NotSame(source.ModelExplorer, viewData.ModelExplorer);
        Assert.NotSame(source.ModelMetadata, viewData.ModelMetadata);
        Assert.Equal(expectedType, viewData.ModelMetadata.ModelType);
    }
예제 #19
0
    public void GetPropertyExplorer_DeferredModelAccess()
    {
        // Arrange
        var model = new DerivedClass()
        {
            Base1 = 5,
        };

        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(typeof(BaseClass), model);

        // Change the model value after creating the explorer
        var propertyExplorer = modelExplorer.GetExplorerForProperty("Base1");

        model.Base1 = 17;

        // Act
        var propertyValue = propertyExplorer.Model;

        // Assert
        Assert.Equal(17, propertyValue);
    }
예제 #20
0
    public void Properties_UsesRuntimeType()
    {
        // Arrange
        var provider      = new EmptyModelMetadataProvider();
        var modelExplorer = provider.GetModelExplorerForType(typeof(BaseClass), new DerivedClass());

        // Act
        var properties = modelExplorer.Properties.ToArray();

        // Assert
        Assert.Equal(2, properties.Length);

        var baseProperty = Assert.Single(properties, p => p.Metadata.PropertyName == "Base1");

        Assert.Equal(typeof(int), baseProperty.Metadata.ModelType);
        Assert.Equal(typeof(DerivedClass), baseProperty.Metadata.ContainerType);
        Assert.Same(modelExplorer, baseProperty.Container);

        var derivedProperty = Assert.Single(properties, p => p.Metadata.PropertyName == "Derived1");

        Assert.Equal(typeof(string), derivedProperty.Metadata.ModelType);
        Assert.Equal(typeof(DerivedClass), derivedProperty.Metadata.ContainerType);
        Assert.Same(modelExplorer, derivedProperty.Container);
    }
예제 #21
0
        /// <summary>
        /// Gets the display name of a model member, typically provided by an appropriate annotation of <see cref="DisplayNameAttribute"/>.
        /// </summary>
        /// <param name="model">The model containing the member whose display name is sought.</param>
        /// <param name="expression">An expression that selects the subject member from the provided <paramref name="model"/>.</param>
        /// <typeparam name="TModel">The type of model containing the member whose display name is sought.</typeparam>
        /// <typeparam name="TProperty">The type of the member whose display name is sought.</typeparam>
        /// <returns>The display name of the indicated model member.</returns>
        public static string GetDisplayName <TModel, TProperty>(TModel model, Expression <Func <TModel, TProperty> > expression)
        {
            var modelMetadataProvider = new EmptyModelMetadataProvider();

            return(modelMetadataProvider.GetModelExplorerForType(typeof(TModel), model).GetExplorerForExpression(typeof(TProperty), expression).GetSimpleDisplayText());
        }
예제 #22
0
        public async Task ProcessAsync_CallsGeneratorWithExpectedValues_ItemsAndAttribute(
            IEnumerable <SelectListItem> inputItems,
            string attributeName,
            string attributeValue,
            IEnumerable <SelectListItem> expectedItems)
        {
            // Arrange
            var contextAttributes = new TagHelperAttributeList
            {
                // Provided for completeness. Select tag helper does not confirm AllAttributes set is consistent.
                { attributeName, attributeValue },
            };
            var originalAttributes = new TagHelperAttributeList
            {
                { attributeName, attributeValue },
            };
            var propertyName    = "Property1";
            var expectedTagName = "select";

            var tagHelperContext = new TagHelperContext(
                tagName: "select",
                allAttributes: contextAttributes,
                items: new Dictionary <object, object>(),
                uniqueId: "test");

            var output = new TagHelperOutput(
                expectedTagName,
                originalAttributes,
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            });
            var    metadataProvider = new EmptyModelMetadataProvider();
            string model            = null;
            var    modelExplorer    = metadataProvider.GetModelExplorerForType(typeof(string), model);

            var htmlGenerator = new Mock <IHtmlGenerator>(MockBehavior.Strict);
            var viewContext   = TestableHtmlGenerator.GetViewContext(model, htmlGenerator.Object, metadataProvider);

            // Simulate a (model => model) scenario. E.g. the calling helper may appear in a low-level template.
            var modelExpression = new ModelExpression(string.Empty, modelExplorer);

            viewContext.ViewData.TemplateInfo.HtmlFieldPrefix = propertyName;

            var currentValues = new string[0];

            htmlGenerator
            .Setup(real => real.GetCurrentValues(
                       viewContext,
                       modelExplorer,
                       string.Empty, // expression
                       false))       // allowMultiple
            .Returns(currentValues)
            .Verifiable();
            htmlGenerator
            .Setup(real => real.GenerateSelect(
                       viewContext,
                       modelExplorer,
                       null,         // optionLabel
                       string.Empty, // expression
                       expectedItems,
                       currentValues,
                       false,       // allowMultiple
                       null))       // htmlAttributes
            .Returns((TagBuilder)null)
            .Verifiable();

            var tagHelper = new SelectTagHelper(htmlGenerator.Object)
            {
                For         = modelExpression,
                Items       = inputItems,
                ViewContext = viewContext,
            };

            // Act
            tagHelper.Init(tagHelperContext);
            await tagHelper.ProcessAsync(tagHelperContext, output);

            // Assert
            htmlGenerator.Verify();

            var keyValuePair = Assert.Single(
                tagHelperContext.Items,
                entry => (Type)entry.Key == typeof(SelectTagHelper));
            var actualCurrentValues = Assert.IsType <CurrentValues>(keyValuePair.Value);

            Assert.Same(currentValues, actualCurrentValues.Values);
        }
예제 #23
0
        public async Task TagHelper_CallsGeneratorWithExpectedValues_RealModelType(
            Type modelType,
            object model,
            bool allowMultiple)
        {
            // Arrange
            var contextAttributes = new TagHelperAttributeList(
                Enumerable.Empty <TagHelperAttribute>());
            var originalAttributes = new TagHelperAttributeList();
            var propertyName       = "Property1";
            var tagName            = "select";

            var tagHelperContext = new TagHelperContext(
                tagName: "select",
                allAttributes: contextAttributes,
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var output = new TagHelperOutput(
                tagName,
                originalAttributes,
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            });
            var metadataProvider = new EmptyModelMetadataProvider();
            var modelExplorer    = metadataProvider.GetModelExplorerForType(modelType, model);
            var modelExpression  = new ModelExpression(propertyName, modelExplorer);

            var htmlGenerator = new Mock <IHtmlGenerator>(MockBehavior.Strict);
            var viewContext   = TestableHtmlGenerator.GetViewContext(model, htmlGenerator.Object, metadataProvider);
            var currentValues = new string[0];

            htmlGenerator
            .Setup(real => real.GetCurrentValues(
                       viewContext,
                       modelExplorer,
                       propertyName, // expression
                       allowMultiple))
            .Returns(currentValues)
            .Verifiable();
            htmlGenerator
            .Setup(real => real.GenerateSelect(
                       viewContext,
                       modelExplorer,
                       null,         // optionLabel
                       propertyName, // expression
                       It.IsAny <IEnumerable <SelectListItem> >(),
                       currentValues,
                       allowMultiple,
                       null))       // htmlAttributes
            .Returns((TagBuilder)null)
            .Verifiable();

            var tagHelper = new SelectTagHelper(htmlGenerator.Object)
            {
                For         = modelExpression,
                ViewContext = viewContext,
            };

            // Act
            tagHelper.Init(tagHelperContext);
            await tagHelper.ProcessAsync(tagHelperContext, output);

            // Assert
            htmlGenerator.Verify();

            var keyValuePair = Assert.Single(
                tagHelperContext.Items,
                entry => (Type)entry.Key == typeof(SelectTagHelper));
            var actualCurrentValues = Assert.IsType <CurrentValues>(keyValuePair.Value);

            Assert.Same(currentValues, actualCurrentValues.Values);
        }