Example #1
0
        public void Reinitialize_AllowsContextToBeReused()
        {
            // Arrange
            var initialUniqueId = "123";
            var expectedUniqueId = "456";
            var initialItems = new Dictionary<object, object>
            {
                { "test-entry", 1234 }
            };
            var expectedItems = new Dictionary<object, object>
            {
                { "something", "new" }
            };
            var initialAttributes = new TagHelperAttributeList
            {
                { "name", "value" }
            };
            var context = new TagHelperContext(initialAttributes, initialItems, initialUniqueId);

            // Act
            context.Reinitialize(expectedItems, expectedUniqueId);

            // Assert
            Assert.Same(expectedItems, context.Items);
            Assert.Equal(expectedUniqueId, context.UniqueId);
            Assert.Empty(context.AllAttributes);
        }
Example #2
0
 /// <summary>
 /// Instantiates a new instance of <see cref="TagHelperOutput"/>.
 /// </summary>
 /// <param name="tagName">The HTML element's tag name.</param>
 /// <param name="attributes">The HTML attributes.</param>
 public TagHelperOutput(
     string tagName,
     [NotNull] TagHelperAttributeList attributes)
 {
     TagName = tagName;
     Attributes = new TagHelperAttributeList(attributes);
 }
Example #3
0
        public void DetermineMode_SetsModeWithHigestValue()
        {
            // Arrange
            var modeInfos = new[]
            {
                new ModeAttributes<Mode>(Mode.A, new[] { "first-attr" }),
                new ModeAttributes<Mode>(Mode.B, new[] { "first-attr", "second-attr" }),
                new ModeAttributes<Mode>(Mode.D, new[] { "second-attr", "third-attr" }),
                new ModeAttributes<Mode>(Mode.C, new[] { "first-attr", "second-attr", "third-attr" }),
            };
            var attributes = new TagHelperAttributeList
            {
                new TagHelperAttribute("first-attr", "value"),
                new TagHelperAttribute("second-attr", "value"),
                new TagHelperAttribute("third-attr", "value"),
                new TagHelperAttribute("not-in-any-mode", "value")
            };
            var context = MakeTagHelperContext(attributes);

            // Act
            Mode result;
            var modeMatch = AttributeMatcher.TryDetermineMode(context, modeInfos, Compare, out result);

            // Assert
            Assert.True(modeMatch);
            Assert.Equal(Mode.D, result);
        }
        /// <summary>
        /// Instantiates a new <see cref="TagHelperExecutionContext"/>.
        /// </summary>
        /// <param name="tagName">The HTML tag name in the Razor source.</param>
        /// <param name="tagMode">HTML syntax of the element in the Razor source.</param>
        /// <param name="items">The collection of items used to communicate with other
        /// <see cref="ITagHelper"/>s</param>
        /// <param name="uniqueId">An identifier unique to the HTML element this context is for.</param>
        /// <param name="executeChildContentAsync">A delegate used to execute the child content asynchronously.</param>
        /// <param name="startTagHelperWritingScope">
        /// A delegate used to start a writing scope in a Razor page and optionally override the page's
        /// <see cref="HtmlEncoder"/> within that scope.
        /// </param>
        /// <param name="endTagHelperWritingScope">A delegate used to end a writing scope in a Razor page.</param>
        public TagHelperExecutionContext(
            string tagName,
            TagMode tagMode,
            IDictionary<object, object> items,
            string uniqueId,
            Func<Task> executeChildContentAsync,
            Action<HtmlEncoder> startTagHelperWritingScope,
            Func<TagHelperContent> endTagHelperWritingScope)
        {
            if (startTagHelperWritingScope == null)
            {
                throw new ArgumentNullException(nameof(startTagHelperWritingScope));
            }

            if (endTagHelperWritingScope == null)
            {
                throw new ArgumentNullException(nameof(endTagHelperWritingScope));
            }

            _tagHelpers = new List<ITagHelper>();
            _allAttributes = new TagHelperAttributeList();

            Context = new TagHelperContext(_allAttributes, items, uniqueId);
            Output = new TagHelperOutput(tagName, new TagHelperAttributeList(), GetChildContentAsync)
            {
                TagMode = tagMode
            };

            Reinitialize(tagName, tagMode, items, uniqueId, executeChildContentAsync);

            _startTagHelperWritingScope = startTagHelperWritingScope;
            _endTagHelperWritingScope = endTagHelperWritingScope;
        }
        public void DetermineMode_FindsFullModeMatchWithMultipleAttributes()
        {
            // Arrange
            var modeInfo = new[]
            {
                ModeAttributes.Create("mode0", new [] { "first-attr", "second-attr" })
            };
            var attributes = new TagHelperAttributeList
            {
                ["first-attr"] = "value",
                ["second-attr"] = "value",
                ["not-in-any-mode"] = "value"
            };
            var context = MakeTagHelperContext(attributes);

            // Act
            var modeMatch = AttributeMatcher.DetermineMode(context, modeInfo);

            // Assert
            Assert.Collection(modeMatch.FullMatches, match =>
            {
                Assert.Equal("mode0", match.Mode);
                Assert.Collection(match.PresentAttributes,
                    attribute => Assert.Equal("first-attr", attribute),
                    attribute => Assert.Equal("second-attr", attribute)
                );
            });
            Assert.Empty(modeMatch.PartialMatches);
            Assert.Empty(modeMatch.PartiallyMatchedAttributes);
        }
        public async Task CheckBoxHandlesMultipleAttributesSameNameCorrectly(
            TagHelperAttributeList outputAttributes,
            string expectedAttributeString)
        {
            // Arrange
            var originalContent = "original content";
            var originalTagName = "not-input";
            var expectedContent = $"{originalContent}<input {expectedAttributeString} id=\"HtmlEncode[[IsACar]]\" " +
                "name=\"HtmlEncode[[IsACar]]\" type=\"HtmlEncode[[checkbox]]\" value=\"HtmlEncode[[true]]\" />" +
                "<input name=\"HtmlEncode[[IsACar]]\" type=\"HtmlEncode[[hidden]]\" value=\"HtmlEncode[[false]]\" />";

            var context = new TagHelperContext(
                allAttributes: new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
                    Enumerable.Empty<IReadOnlyTagHelperAttribute>()),
                items: new Dictionary<object, object>(),
                uniqueId: "test",
                getChildContentAsync: useCachedResult => Task.FromResult<TagHelperContent>(result: null));
            var output = new TagHelperOutput(originalTagName, outputAttributes)
            {
                TagMode = TagMode.SelfClosing,
            };
            output.Content.SetContent(originalContent);
            var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider());
            var tagHelper = GetTagHelper(htmlGenerator, model: false, propertyName: nameof(Model.IsACar));

            // Act
            await tagHelper.ProcessAsync(context, output);

            // Assert
            Assert.Empty(output.Attributes); // Moved to Content and cleared
            Assert.Equal(expectedContent, HtmlContentUtilities.HtmlContentToString(output.Content));
            Assert.Equal(TagMode.SelfClosing, output.TagMode);
            Assert.Null(output.TagName); // Cleared
        }
        public void DetermineMode_SetsModeIfAllAttributesMatch()
        {
            // Arrange
            var modeInfos = new[]
            {
                new ModeAttributes<Mode>(Mode.A, new[] { "a-required-attributes" }),
                new ModeAttributes<Mode>(Mode.B, new[] { "first-attr", "second-attr" }),
                new ModeAttributes<Mode>(Mode.C, new[] { "first-attr", "third-attr" }),
            };
            var attributes = new TagHelperAttributeList
            {
                ["first-attr"] = "value",
                ["second-attr"] = "value",
                ["not-in-any-mode"] = "value"
            };
            var context = MakeTagHelperContext(attributes);

            // Act
            Mode result;
            var modeMatch = AttributeMatcher.TryDetermineMode(context, modeInfos, Compare, out result);

            // Assert
            Assert.True(modeMatch);
            Assert.Equal(Mode.B, result);
        }
Example #8
0
        public void Process_SrcDefaultsToTagHelperOutputSrcAttributeAddedByOtherTagHelper(
            string src,
            string srcOutput,
            string expectedSrcPrefix)
        {
            // Arrange
            var allAttributes = new TagHelperAttributeList(
                new TagHelperAttributeList
                {
                    { "alt", new HtmlString("Testing") },
                    { "asp-append-version", true },
                });
            var context = MakeTagHelperContext(allAttributes);
            var outputAttributes = new TagHelperAttributeList
                {
                    { "alt", new HtmlString("Testing") },
                    { "src", srcOutput },
                };
            var output = new TagHelperOutput(
                "img",
                outputAttributes,
                getChildContentAsync: (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(
                    new DefaultTagHelperContent()));
            var hostingEnvironment = MakeHostingEnvironment();
            var viewContext = MakeViewContext();
            var urlHelper = new Mock<IUrlHelper>();

            // Ensure expanded path does not look like an absolute path on Linux, avoiding
            // https://github.com/aspnet/External/issues/21
            urlHelper
                .Setup(urlhelper => urlhelper.Content(It.IsAny<string>()))
                .Returns(new Func<string, string>(url => url.Replace("~/", "virtualRoot/")));
            var urlHelperFactory = new Mock<IUrlHelperFactory>();
            urlHelperFactory
                .Setup(f => f.GetUrlHelper(It.IsAny<ActionContext>()))
                .Returns(urlHelper.Object);

            var helper = new ImageTagHelper(
                hostingEnvironment,
                MakeCache(),
                new HtmlTestEncoder(),
                urlHelperFactory.Object)
            {
                ViewContext = viewContext,
                AppendVersion = true,
                Src = src,
            };

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

            // Assert
            Assert.Equal(
                expectedSrcPrefix + "?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk",
                (string)output.Attributes["src"].Value,
                StringComparer.Ordinal);
        }
Example #9
0
        public void Process_HrefDefaultsToTagHelperOutputHrefAttributeAddedByOtherTagHelper(
            string href,
            string hrefOutput,
            string expectedHrefPrefix)
        {
            // Arrange
            var allAttributes = new TagHelperAttributeList(
                new TagHelperAttributeList
                {
                    { "rel", new HtmlString("stylesheet") },
                    { "asp-append-version", true },
                });
            var context = MakeTagHelperContext(allAttributes);
            var outputAttributes = new TagHelperAttributeList
                {
                    { "rel", new HtmlString("stylesheet") },
                    { "href", hrefOutput },
                };
            var output = MakeTagHelperOutput("link", outputAttributes);
            var hostingEnvironment = MakeHostingEnvironment();
            var viewContext = MakeViewContext();
            var urlHelper = new Mock<IUrlHelper>();

            // Ensure expanded path does not look like an absolute path on Linux, avoiding
            // https://github.com/aspnet/External/issues/21
            urlHelper
                .Setup(urlhelper => urlhelper.Content(It.IsAny<string>()))
                .Returns(new Func<string, string>(url => url.Replace("~/", "virtualRoot/")));
            var urlHelperFactory = new Mock<IUrlHelperFactory>();
            urlHelperFactory
                .Setup(f => f.GetUrlHelper(It.IsAny<ActionContext>()))
                .Returns(urlHelper.Object);

            var helper = new LinkTagHelper(
                hostingEnvironment,
                MakeCache(),
                new HtmlTestEncoder(),
                new JavaScriptTestEncoder(),
                urlHelperFactory.Object)
            {
                ViewContext = viewContext,
                AppendVersion = true,
                Href = href,
            };

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

            // Assert
            Assert.Equal(
                expectedHrefPrefix + "?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk",
                (string)output.Attributes["href"].Value,
                StringComparer.Ordinal);
        }
Example #10
0
        /// <summary>
        /// Instantiates a new instance of <see cref="TagHelperOutput"/>.
        /// </summary>
        /// <param name="tagName">The HTML element's tag name.</param>
        /// <param name="attributes">The HTML attributes.</param>
        public TagHelperOutput(
            string tagName,
            TagHelperAttributeList attributes)
        {
            if (attributes == null)
            {
                throw new ArgumentNullException(nameof(attributes));
            }

            TagName = tagName;
            Attributes = new TagHelperAttributeList(attributes);
        }
        public void IntIndexer_Getter_ThrowsIfIndexInvalid(int index)
        {
            // Arrange
            var attributes = new TagHelperAttributeList(new[]
                {
                    new TagHelperAttribute("A", "AV"),
                    new TagHelperAttribute("B", "BV")
                });

            // Act & Assert
            var exception = Assert.Throws<ArgumentOutOfRangeException>("index", () => attributes[index]);
        }
Example #12
0
        public void Process_SrcDefaultsToTagHelperOutputSrcAttributeAddedByOtherTagHelper(
            string src,
            string srcOutput,
            string expectedSrcPrefix)
        {
            // Arrange
            var allAttributes = new TagHelperAttributeList(
                new TagHelperAttributeList
                {
                    { "type", new HtmlString("text/javascript") },
                    { "asp-append-version", true },
                });
            var context = MakeTagHelperContext(allAttributes);
            var outputAttributes = new TagHelperAttributeList
                {
                    { "type", new HtmlString("text/javascript") },
                    { "src", srcOutput },
                };
            var output = MakeTagHelperOutput("script", outputAttributes);
            var logger = new Mock<ILogger<ScriptTagHelper>>();
            var hostingEnvironment = MakeHostingEnvironment();
            var viewContext = MakeViewContext();
            var urlHelper = new Mock<IUrlHelper>();

            // Ensure expanded path does not look like an absolute path on Linux, avoiding
            // https://github.com/aspnet/External/issues/21
            urlHelper
                .Setup(urlhelper => urlhelper.Content(It.IsAny<string>()))
                .Returns(new Func<string, string>(url => url.Replace("~/", "virtualRoot/")));

            var helper = new ScriptTagHelper(
                logger.Object,
                hostingEnvironment,
                MakeCache(),
                new CommonTestEncoder(),
                new CommonTestEncoder(),
                urlHelper.Object)
            {
                ViewContext = viewContext,
                AppendVersion = true,
                Src = src,
            };

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

            // Assert
            Assert.Equal(
                expectedSrcPrefix + "?v=f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk",
                (string)output.Attributes["src"].Value,
                StringComparer.Ordinal);
        }
Example #13
0
        public void HandlesMultipleAttributesSameNameCorrectly(TagHelperAttributeList outputAttributes)
        {
            // Arrange
            var allAttributes = new TagHelperAttributeList(
                outputAttributes.Concat(
                    new TagHelperAttributeList
                    {
                        { "rel", new HtmlString("stylesheet") },
                        { "href", "test.css" },
                        { "asp-fallback-href", "test.css" },
                        { "asp-fallback-test-class", "hidden" },
                        { "asp-fallback-test-property", "visibility" },
                        { "asp-fallback-test-value", "hidden" },
                    }));
            var context = MakeTagHelperContext(allAttributes);
            var combinedOutputAttributes = new TagHelperAttributeList(
                outputAttributes.Concat(
                    new[]
                    {
                        new TagHelperAttribute("rel", new HtmlString("stylesheet"))
                    }));
            var output = MakeTagHelperOutput("link", combinedOutputAttributes);
            var logger = new Mock<ILogger<LinkTagHelper>>();
            var hostingEnvironment = MakeHostingEnvironment();
            var viewContext = MakeViewContext();

            var helper = new LinkTagHelper(
                logger.Object,
                hostingEnvironment,
                MakeCache(),
                new CommonTestEncoder(),
                new CommonTestEncoder(),
                MakeUrlHelper())
            {
                ViewContext = viewContext,
                FallbackHref = "test.css",
                FallbackTestClass = "hidden",
                FallbackTestProperty = "visibility",
                FallbackTestValue = "hidden",
                Href = "test.css",
            };
            var expectedAttributes = new TagHelperAttributeList(output.Attributes);
            expectedAttributes.Add(new TagHelperAttribute("href", "test.css"));

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

            // Assert
            Assert.Equal(expectedAttributes, output.Attributes);
        }
        public void IntIndexer_GetsExpectedAttribute(
            IEnumerable<TagHelperAttribute> initialAttributes,
            int indexToLookup,
            TagHelperAttribute expectedAttribute)
        {
            // Arrange
            var attributes = new TagHelperAttributeList(initialAttributes);

            // Act
            var attribute = attributes[indexToLookup];

            // Assert
            Assert.Equal(expectedAttribute, attribute, CaseSensitiveTagHelperAttributeComparer.Default);
        }
        public void IntIndexer_SetsAttributeAtExpectedIndex(
            IEnumerable<TagHelperAttribute> initialAttributes,
            int indexToSet,
            TagHelperAttribute setValue,
            IEnumerable<TagHelperAttribute> expectedAttributes)
        {
            // Arrange
            var attributes = new TagHelperAttributeList(initialAttributes);

            // Act
            attributes[indexToSet] = setValue;

            // Assert
            Assert.Equal(expectedAttributes, attributes, CaseSensitiveTagHelperAttributeComparer.Default);
        }
Example #16
0
        public async Task HandlesMultipleAttributesSameNameCorrectly(
            TagHelperAttributeList outputAttributes,
            string expectedAttributeString)
        {
            // Arrange
            var allAttributes = new TagHelperAttributeList(
                outputAttributes.Concat(
                    new TagHelperAttributeList
                    {
                        ["data-extra"] = "something",
                        ["src"] = "/blank.js",
                        ["asp-fallback-src"] = "http://www.example.com/blank.js",
                        ["asp-fallback-test"] = "isavailable()",
                    }));
            var tagHelperContext = MakeTagHelperContext(allAttributes);
            var viewContext = MakeViewContext();
            var combinedOutputAttributes = new TagHelperAttributeList(
                outputAttributes.Concat(
                    new[]
                    {
                        new TagHelperAttribute("data-extra", new HtmlString("something"))
                    }));
            var output = MakeTagHelperOutput("script", combinedOutputAttributes);
            var hostingEnvironment = MakeHostingEnvironment();

            var helper = new ScriptTagHelper(
                CreateLogger(),
                hostingEnvironment,
                MakeCache(),
                new CommonTestEncoder(),
                new CommonTestEncoder())
            {
                ViewContext = viewContext,
                FallbackSrc = "~/blank.js",
                FallbackTestExpression = "http://www.example.com/blank.js",
                Src = "/blank.js",
            };

            // Act
            await helper.ProcessAsync(tagHelperContext, output);

            // Assert
            Assert.StartsWith(
                "<script " + expectedAttributeString + " data-extra=\"something\" " +
                "src=\"HtmlEncode[[/blank.js]]\"",
                output.Content.GetContent());
        }
Example #17
0
        public async Task Reinitialize_AllowsOutputToBeReused()
        {
            // Arrange
            var initialOutputChildContent = new DefaultTagHelperContent();
            initialOutputChildContent.SetContent("Initial output content.");
            var expectedGetChildContentContent = "Initial get child content content";
            var initialGetChildContent = new DefaultTagHelperContent();
            initialGetChildContent.SetContent(expectedGetChildContentContent);
            Func<bool, HtmlEncoder, Task<TagHelperContent>> initialGetChildContentAsync =
                (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(initialGetChildContent);
            var initialTagMode = TagMode.StartTagOnly;
            var initialAttributes = new TagHelperAttributeList
            {
                { "name", "value" }
            };
            var initialTagName = "initialTagName";
            var output = new TagHelperOutput(initialTagName, initialAttributes, initialGetChildContentAsync)
            {
                TagMode = initialTagMode,
                Content = initialOutputChildContent,
            };
            output.PreContent.SetContent("something");
            output.PostContent.SetContent("something");
            output.PreElement.SetContent("something");
            output.PostElement.SetContent("something");
            var expectedTagName = "newTagName";
            var expectedTagMode = TagMode.SelfClosing;

            // Act
            output.Reinitialize(expectedTagName, expectedTagMode);

            // Assert
            Assert.Equal(expectedTagName, output.TagName);
            Assert.Equal(expectedTagMode, output.TagMode);
            Assert.Empty(output.Attributes);

            var getChildContent = await output.GetChildContentAsync();
            var content = getChildContent.GetContent();

            // We're expecting the initial child content here because normally the TagHelper infrastructure would
            // swap out the inner workings of GetChildContentAsync to work with its reinitialized state.
            Assert.Equal(expectedGetChildContentContent, content);
            Assert.False(output.PreContent.IsModified);
            Assert.False(output.PostContent.IsModified);
            Assert.False(output.PreElement.IsModified);
            Assert.False(output.PostElement.IsModified);
        }
Example #18
0
        /// <summary>
        /// Instantiates a new instance of <see cref="TagHelperOutput"/>.
        /// </summary>
        /// <param name="tagName">The HTML element's tag name.</param>
        /// <param name="attributes">The HTML attributes.</param>
        /// <param name="getChildContentAsync">A delegate used to execute and retrieve the rendered child content
        /// asynchronously.</param>
        public TagHelperOutput(
            string tagName,
            TagHelperAttributeList attributes,
            Func<bool, Task<TagHelperContent>> getChildContentAsync)
        {
            if (attributes == null)
            {
                throw new ArgumentNullException(nameof(attributes));
            }

            if (getChildContentAsync == null)
            {
                throw new ArgumentNullException(nameof(getChildContentAsync));
            }

            TagName = tagName;
            Attributes = new TagHelperAttributeList(attributes);
            _getChildContentAsync = getChildContentAsync;
        }
        public void TryDetermineMode_ReturnsFalseIfNoAttributeMatchesAllRequiredAttributes(string[] modeAttributes)
        {
            // Arrange
            var modeInfos = new[]
            {
                new ModeAttributes<Mode>(Mode.A, modeAttributes)
            };
            var attributes = new TagHelperAttributeList
            {
                ["first-attr"] = "value",
                ["not-in-any-mode"] = "value"
            };
            var context = MakeTagHelperContext(attributes);

            // Act
            Mode result;
            var modeMatch = AttributeMatcher.TryDetermineMode(context, modeInfos, Compare, out result);

            // Assert
            Assert.False(modeMatch);
        }
        /// <summary>
        /// Instantiates a new <see cref="TagHelperExecutionContext"/>.
        /// </summary>
        /// <param name="tagName">The HTML tag name in the Razor source.</param>
        /// <param name="selfClosing">
        /// <see cref="bool"/> indicating whether or not the tag in the Razor source was self-closing.</param>
        /// <param name="items">The collection of items used to communicate with other
        /// <see cref="ITagHelper"/>s</param>
        /// <param name="uniqueId">An identifier unique to the HTML element this context is for.</param>
        /// <param name="executeChildContentAsync">A delegate used to execute the child content asynchronously.</param>
        /// <param name="startTagHelperWritingScope">A delegate used to start a writing scope in a Razor page.</param>
        /// <param name="endTagHelperWritingScope">A delegate used to end a writing scope in a Razor page.</param>
        public TagHelperExecutionContext(
            [NotNull] string tagName,
            bool selfClosing,
            [NotNull] IDictionary<object, object> items,
            [NotNull] string uniqueId,
            [NotNull] Func<Task> executeChildContentAsync,
            [NotNull] Action startTagHelperWritingScope,
            [NotNull] Func<TagHelperContent> endTagHelperWritingScope)
        {
            _tagHelpers = new List<ITagHelper>();
            _executeChildContentAsync = executeChildContentAsync;
            _startTagHelperWritingScope = startTagHelperWritingScope;
            _endTagHelperWritingScope = endTagHelperWritingScope;

            SelfClosing = selfClosing;
            HTMLAttributes = new TagHelperAttributeList();
            AllAttributes = new TagHelperAttributeList();
            TagName = tagName;
            Items = items;
            UniqueId = uniqueId;
        }
Example #21
0
        /// <summary>
        /// Instantiates a new <see cref="TagHelperContext"/>.
        /// </summary>
        /// <param name="allAttributes">Every attribute associated with the current HTML element.</param>
        /// <param name="items">Collection of items used to communicate with other <see cref="ITagHelper"/>s.</param>
        /// <param name="uniqueId">The unique identifier for the source element this <see cref="TagHelperContext" />
        /// applies to.</param>
        public TagHelperContext(
            TagHelperAttributeList allAttributes,
            IDictionary<object, object> items,
            string uniqueId)
        {
            if (items == null)
            {
                throw new ArgumentNullException(nameof(items));
            }

            if (uniqueId == null)
            {
                throw new ArgumentNullException(nameof(uniqueId));
            }

            if (allAttributes == null)
            {
                throw new ArgumentNullException(nameof(allAttributes));
            }

            _allAttributes = allAttributes;
            Items = items;
            UniqueId = uniqueId;
        }
Example #22
0
 /// <summary>
 /// 获取结果
 /// </summary>
 private string GetResult(TagHelperAttributeList contextAttributes = null, TagHelperAttributeList outputAttributes = null,
                          TagHelperContent content = null, IDictionary <object, object> items = null)
 {
     return(Helper.GetResult(_output, _component, contextAttributes, outputAttributes, content, items));
 }
 protected virtual bool IsInputCheckbox(TagHelperContext context, TagHelperOutput output, TagHelperAttributeList attributes)
 {
     return(attributes.Any(a => a.Value != null && a.Name == "type" && a.Value.ToString() == "checkbox"));
 }
Example #24
0
        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 TagHelperAttributeList
            {
                { "class", "form-control" },
                { "value", value },
            };

            if (!string.IsNullOrEmpty(inputTypeName))
            {
                contextAttributes.SetAttribute("type", inputTypeName);  // Support restoration of type attribute, if any.
            }

            var expectedAttributes = new TagHelperAttributeList
            {
                { "class", "form-control radio-control" },
                { "value", value },
                { "type", inputTypeName ?? "radio" },       // Generator restores type attribute; adds "radio" if none.
            };
            var expectedPreContent  = "original pre-content";
            var expectedContent     = "original content";
            var expectedPostContent = "original post-content";
            var expectedTagName     = "not-input";

            var context = new TagHelperContext(
                allAttributes: contextAttributes,
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var originalAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };
            var output = new TagHelperOutput(
                expectedTagName,
                originalAttributes,
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            })
            {
                TagMode = TagMode.StartTagOnly,
            };

            output.PreContent.SetContent(expectedPreContent);
            output.Content.SetContent(expectedContent);
            output.PostContent.SetContent(expectedPostContent);

            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.ModelExplorer,
                       tagHelper.For.Name,
                       value,
                       null,    // isChecked
                       null))   // htmlAttributes
            .Returns(tagBuilder)
            .Verifiable();

            // Act
            await tagHelper.ProcessAsync(context, output);

            // Assert
            htmlGenerator.Verify();

            Assert.Equal(TagMode.StartTagOnly, output.TagMode);
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Equal(expectedPreContent, output.PreContent.GetContent());
            Assert.Equal(expectedContent, output.Content.GetContent());
            Assert.Equal(expectedPostContent, output.PostContent.GetContent());
            Assert.Equal(expectedTagName, output.TagName);
        }
Example #25
0
        public async Task Process_GeneratesExpectedOutput(
            object container,
            Type containerType,
            object model,
            NameAndId nameAndId,
            string expectedContent)
        {
            // Arrange
            var expectedAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
                { "id", nameAndId.Id },
                { "name", nameAndId.Name },
                { "valid", "from validation attributes" },
            };
            var expectedTagName = "not-textarea";

            var metadataProvider = new TestModelMetadataProvider();

            var containerMetadata = metadataProvider.GetMetadataForType(containerType);
            var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, container);

            var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text");
            var modelExplorer    = containerExplorer.GetExplorerForExpression(propertyMetadata, model);

            var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
            {
                ValidationAttributes =
                {
                    { "valid", "from validation attributes" },
                }
            };

            // Property name is either nameof(Model.Text) or nameof(NestedModel.Text).
            var modelExpression = new ModelExpression(nameAndId.Name, modelExplorer);
            var tagHelper       = new TextAreaTagHelper(htmlGenerator)
            {
                For = modelExpression,
            };

            var tagHelperContext = new TagHelperContext(
                allAttributes: new ReadOnlyTagHelperAttributeList <IReadOnlyTagHelperAttribute>(
                    Enumerable.Empty <IReadOnlyTagHelperAttribute>()),
                items: new Dictionary <object, object>(),
                uniqueId: "test",
                getChildContentAsync: useCachedResult =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            });
            var htmlAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };
            var output = new TagHelperOutput(expectedTagName, htmlAttributes)
            {
                TagMode = TagMode.SelfClosing,
            };

            output.Content.SetContent("original content");

            var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);

            tagHelper.ViewContext = viewContext;

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

            // Assert
            Assert.Equal(TagMode.SelfClosing, output.TagMode);
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Equal(expectedContent, HtmlContentUtilities.HtmlContentToString(output.Content));
            Assert.Equal(expectedTagName, output.TagName);
        }
        public static IHtmlContent LocalizedEditor <TModel, TLocalizedModelLocal>(this IHtmlHelper <TModel> helper,
                                                                                  string name,
                                                                                  Func <int, HelperResult> localizedTemplate,
                                                                                  Func <TModel, HelperResult> masterTemplate)
            where TModel : ILocalizedModel <TLocalizedModelLocal>
            where TLocalizedModelLocal : ILocalizedLocaleModel
        {
            var locales           = helper.ViewData.Model.Locales;
            var hasMasterTemplate = masterTemplate != null;

            if (locales.Count > 1)
            {
                var services            = helper.ViewContext.HttpContext.RequestServices;
                var db                  = services.GetRequiredService <SmartDbContext>();
                var languageService     = services.GetRequiredService <ILanguageService>();
                var localizationService = services.GetRequiredService <ILocalizationService>();
                var tabs                = new List <TabItem>(locales.Count + 1);
                var languages           = new List <Language>(locales.Count + 1);

                // Create the parent tabstrip
                var strip = new TabStripTagHelper
                {
                    ViewContext       = helper.ViewContext,
                    Id                = name,
                    SmartTabSelection = false,
                    Style             = TabsStyle.Tabs,
                    PublishEvent      = false
                };

                if (hasMasterTemplate)
                {
                    var masterLanguage = db.Languages.FindById(languageService.GetMasterLanguageId(), false);
                    languages.Add(masterLanguage);

                    // Add the first default tab for the master template
                    tabs.Add(new TabItem
                    {
                        Selected = true,
                        Text     = localizationService.GetResource("Admin.Common.Standard")
                    });
                }

                // Add all language specific tabs
                for (var i = 0; i < locales.Count; i++)
                {
                    var locale   = locales[i];
                    var language = db.Languages.FindById(locale.LanguageId, false);
                    languages.Add(language);

                    tabs.Add(new TabItem
                    {
                        Selected = !hasMasterTemplate && i == 0,
                        Text     = language.Name,
                        ImageUrl = "~/images/flags/" + language.FlagImageFileName
                    });
                }

                // Create TagHelperContext for tabstrip.
                var stripContext = new TagHelperContext("tabstrip", new TagHelperAttributeList(), new Dictionary <object, object>(), CommonHelper.GenerateRandomDigitCode(10));

                // Must init tabstrip, otherwise "Parent" is null inside tab helpers.
                strip.Init(stripContext);

                // Create tab factory
                var tabFactory = new TabFactory(strip, stripContext);

                // Create AttributeList for tabstrip
                var stripOutputAttrList = new TagHelperAttributeList {
                    new TagHelperAttribute("class", "nav-locales")
                };

                // Emulate tabstrip output
                var stripOutput = new TagHelperOutput("tabstrip", stripOutputAttrList, (_, _) =>
                {
                    // getChildContentAsync for tabstrip
                    for (var i = 0; i < tabs.Count; i++)
                    {
                        var isMaster = hasMasterTemplate && i == 0;
                        var language = languages[i];

                        tabFactory.AddAsync(builder =>
                        {
                            builder.Item = tabs[i];
                            builder
                            .Content(isMaster ? masterTemplate(helper.ViewData.Model) : localizedTemplate(hasMasterTemplate ? i - 1 : i))
                            .HtmlAttributes("title", language.Name, !isMaster)
                            .ContentHtmlAttributes(new
                            {
                                @class    = "locale-editor-content",
                                data_lang = language.LanguageCulture,
                                data_rtl  = language.Rtl.ToString().ToLower()
                            });
                        }).GetAwaiter().GetResult();
                    }

                    // We don't need the child content for tabstrip. It builds everything without any child content.
                    return(Task.FromResult <TagHelperContent>(new DefaultTagHelperContent()));
                });

                // Process parent tabstrip
                strip.ProcessAsync(stripContext, stripOutput).GetAwaiter().GetResult();

                var wrapper = new TagBuilder("div");
                wrapper.Attributes.Add("class", "locale-editor");

                return(stripOutput.WrapElementWith(wrapper));
            }
            else if (hasMasterTemplate)
            {
                return(masterTemplate(helper.ViewData.Model));
            }

            return(HtmlString.Empty);
        }
Example #27
0
        public async Task ProcessAsync_CallsGenerateTextBox_AddsExpectedAttributesForRfc3339(
            string propertyName,
            Html5DateRenderingMode dateRenderingMode,
            string expectedFormat,
            string expectedType)
        {
            // Arrange
            var expectedAttributes = new TagHelperAttributeList
            {
                { "type", expectedType },                   // Calculated; not passed to HtmlGenerator.
            };
            var expectedTagName = "not-input";

            var context = new TagHelperContext(
                allAttributes: new TagHelperAttributeList(
                    Enumerable.Empty <TagHelperAttribute>()),
                items: new Dictionary <object, object>(),
                uniqueId: "test");

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

            var htmlAttributes = new Dictionary <string, object>
            {
                { "type", expectedType }
            };
            var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
            var htmlGenerator    = new Mock <IHtmlGenerator>(MockBehavior.Strict);
            var tagHelper        = GetTagHelper(
                htmlGenerator.Object,
                model: null,
                propertyName: propertyName,
                metadataProvider: metadataProvider);

            tagHelper.ViewContext.Html5DateRenderingMode = dateRenderingMode;

            var tagBuilder = new TagBuilder("input");

            htmlGenerator
            .Setup(mock => mock.GenerateTextBox(
                       tagHelper.ViewContext,
                       tagHelper.For.ModelExplorer,
                       tagHelper.For.Name,
                       null,                            // value
                       expectedFormat,
                       htmlAttributes))                 // htmlAttributes
            .Returns(tagBuilder)
            .Verifiable();

            // Act
            await tagHelper.ProcessAsync(context, output);

            // Assert
            htmlGenerator.Verify();

            Assert.Equal(TagMode.SelfClosing, output.TagMode);
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Empty(output.PreContent.GetContent());
            Assert.Equal(string.Empty, output.Content.GetContent());
            Assert.Empty(output.PostContent.GetContent());
            Assert.Equal(expectedTagName, output.TagName);
        }
        public void AddMinimizedHtmlAttribute_MaintainsHTMLAttributes_SomeMinimized()
        {
            // Arrange
            var executionContext = new TagHelperExecutionContext("input", tagMode: TagMode.SelfClosing);
            var expectedAttributes = new TagHelperAttributeList
            {
                { "class", "btn" },
                { "foo", "bar" }
            };
            expectedAttributes.Add(new TagHelperAttribute { Name = "checked", Minimized = true });
            expectedAttributes.Add(new TagHelperAttribute { Name = "visible", Minimized = true });

            // Act
            executionContext.AddHtmlAttribute("class", "btn");
            executionContext.AddHtmlAttribute("foo", "bar");
            executionContext.AddMinimizedHtmlAttribute("checked");
            executionContext.AddMinimizedHtmlAttribute("visible");

            // Assert
            Assert.Equal(
                expectedAttributes,
                executionContext.HTMLAttributes,
                CaseSensitiveTagHelperAttributeComparer.Default);
        }
Example #29
0
        private void BuildFallbackBlock(TagHelperAttributeList attributes, TagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();
            var fallbackHrefs = GlobbingUrlBuilder.BuildUrlList(
                FallbackHref,
                FallbackHrefInclude,
                FallbackHrefExclude);

            if (fallbackHrefs.Count == 0)
            {
                return;
            }

            builder.AppendHtml(HtmlString.NewLine);

            // Build the <meta /> tag that's used to test for the presence of the stylesheet
            builder
            .AppendHtml("<meta name=\"x-stylesheet-fallback-test\" content=\"\" class=\"")
            .Append(FallbackTestClass)
            .AppendHtml("\" />");

            // Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra
            // <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false,
            // indicating that the primary stylesheet failed to load.
            // GetEmbeddedJavaScript returns JavaScript to which we add '"{0}","{1}",{2});'
            builder
            .AppendHtml("<script>")
            .AppendHtml(JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName))
            .AppendHtml("\"")
            .AppendHtml(JavaScriptEncoder.Encode(FallbackTestProperty))
            .AppendHtml("\",\"")
            .AppendHtml(JavaScriptEncoder.Encode(FallbackTestValue))
            .AppendHtml("\",");

            AppendFallbackHrefs(builder, fallbackHrefs);

            builder.AppendHtml(", \"");

            // Perf: Avoid allocating enumerator
            for (var i = 0; i < attributes.Count; i++)
            {
                var attribute = attributes[i];
                if (string.Equals(attribute.Name, HrefAttributeName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                if (SuppressFallbackIntegrity && string.Equals(attribute.Name, IntegrityAttributeName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                attribute.WriteTo(StringWriter, HtmlEncoder);
                StringWriter.Write(' ');
            }

            var stringBuilder = StringWriter.GetStringBuilder();
            var scriptTags    = stringBuilder.ToString();

            stringBuilder.Clear();
            var encodedScriptTags = JavaScriptEncoder.Encode(scriptTags);

            builder.AppendHtml(encodedScriptTags);

            builder.AppendHtml("\");</script>");
        }
Example #30
0
        private void BuildFallbackBlock(TagHelperAttributeList attributes, TagHelperContent builder)
        {
            EnsureGlobbingUrlBuilder();

            var fallbackSrcs = GlobbingUrlBuilder.BuildUrlList(FallbackSrc, FallbackSrcInclude, FallbackSrcExclude);

            if (fallbackSrcs.Count > 0)
            {
                // Build the <script> tag that checks the test method and if it fails, renders the extra script.
                builder.AppendHtml(Environment.NewLine)
                .AppendHtml("<script>(")
                .AppendHtml(FallbackTestExpression)
                .AppendHtml("||document.write(\"");

                foreach (var src in fallbackSrcs)
                {
                    // Fallback "src" values come from bound attributes and globbing. Must always be non-null.
                    Debug.Assert(src != null);

                    StringWriter.Write("<script");

                    var addSrc = true;

                    // Perf: Avoid allocating enumerator
                    for (var i = 0; i < attributes.Count; i++)
                    {
                        var attribute = attributes[i];
                        if (!attribute.Name.Equals(SrcAttributeName, StringComparison.OrdinalIgnoreCase))
                        {
                            if (SuppressFallbackIntegrity && string.Equals(IntegrityAttributeName, attribute.Name, StringComparison.OrdinalIgnoreCase))
                            {
                                continue;
                            }

                            StringWriter.Write(' ');
                            attribute.WriteTo(StringWriter, HtmlEncoder);
                        }
                        else
                        {
                            addSrc = false;
                            WriteVersionedSrc(attribute.Name, src, attribute.ValueStyle, StringWriter);
                        }
                    }

                    if (addSrc)
                    {
                        WriteVersionedSrc(SrcAttributeName, src, HtmlAttributeValueStyle.DoubleQuotes, StringWriter);
                    }

                    StringWriter.Write("></script>");
                }

                var stringBuilder = StringWriter.GetStringBuilder();
                var scriptTags    = stringBuilder.ToString();
                stringBuilder.Clear();
                var encodedScriptTags = JavaScriptEncoder.Encode(scriptTags);
                builder.AppendHtml(encodedScriptTags);

                builder.AppendHtml("\"));</script>");
            }
        }
 public MarkdownHelperToTheTagHelpers()
 {
     _inputAttributes  = new List <IReadOnlyTagHelperAttribute>();
     _outputAttributes = new TagHelperAttributeList();
 }
        public async Task ProcessAsync_GeneratesExpectedOutput_WithDisplayName(
            string displayName,
            string originalChildContent,
            string htmlFieldPrefix,
            string expectedContent,
            string expectedId)
        {
            // Arrange
            var expectedAttributes = new TagHelperAttributeList
            {
                { "for", expectedId }
            };

            var name             = nameof(NestedModel.Text);
            var metadataProvider = new TestModelMetadataProvider();

            metadataProvider
            .ForProperty <NestedModel>(name)
            .DisplayDetails(metadata => metadata.DisplayName = () => displayName);

            var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
            var viewContext   = TestableHtmlGenerator.GetViewContext(
                model: null,
                htmlGenerator: htmlGenerator,
                metadataProvider: metadataProvider);

            var viewData = new ViewDataDictionary <NestedModel>(metadataProvider, viewContext.ModelState);

            viewData.TemplateInfo.HtmlFieldPrefix = htmlFieldPrefix;
            viewContext.ViewData = viewData;

            var containerExplorer = metadataProvider.GetModelExplorerForType(typeof(NestedModel), model: null);
            var modelExplorer     = containerExplorer.GetExplorerForProperty(name);
            var modelExpression   = new ModelExpression(name, modelExplorer);
            var tagHelper         = new LabelTagHelper(htmlGenerator)
            {
                For         = modelExpression,
                ViewContext = viewContext,
            };

            var tagHelperContext = new TagHelperContext(
                tagName: "label",
                allAttributes: new TagHelperAttributeList(),
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var output = new TagHelperOutput(
                "label",
                new TagHelperAttributeList(),
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.AppendHtml(originalChildContent);
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            });

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

            // Assert
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Equal(expectedContent, HtmlContentUtilities.HtmlContentToString(output.Content));
        }
Example #33
0
        public async Task ProcessAsync_GeneratesExpectedOutput(
            object container,
            Type containerType,
            object model,
            NameAndId nameAndId,
            string expectedValue)
        {
            // Arrange
            var expectedAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
                { "type", "text" },
                { "id", nameAndId.Id },
                { "name", nameAndId.Name },
                { "valid", "from validation attributes" },
                { "value", expectedValue },
            };
            var expectedPreContent  = "original pre-content";
            var expectedContent     = "original content";
            var expectedPostContent = "original post-content";
            var expectedTagName     = "not-input";

            var context = new TagHelperContext(
                allAttributes: new TagHelperAttributeList(
                    Enumerable.Empty <TagHelperAttribute>()),
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var originalAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };
            var output = new TagHelperOutput(
                expectedTagName,
                originalAttributes,
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            })
            {
                TagMode = TagMode.StartTagOnly,
            };

            output.PreContent.SetContent(expectedPreContent);
            output.Content.SetContent(expectedContent);
            output.PostContent.SetContent(expectedPostContent);

            var htmlGenerator = new TestableHtmlGenerator(new EmptyModelMetadataProvider())
            {
                ValidationAttributes =
                {
                    { "valid", "from validation attributes" },
                }
            };

            // Property name is either nameof(Model.Text) or nameof(NestedModel.Text).
            var tagHelper = GetTagHelper(
                htmlGenerator,
                container,
                containerType,
                model,
                propertyName: nameof(Model.Text),
                expressionName: nameAndId.Name);

            // Act
            await tagHelper.ProcessAsync(context, output);

            // Assert
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Equal(expectedPreContent, output.PreContent.GetContent());
            Assert.Equal(expectedContent, output.Content.GetContent());
            Assert.Equal(expectedPostContent, output.PostContent.GetContent());
            Assert.Equal(TagMode.StartTagOnly, output.TagMode);
            Assert.Equal(expectedTagName, output.TagName);
        }
Example #34
0
        public ITagHelper Create(ITagHelperFactory factory, ViewContext context, FilterArguments arguments,
                                 out TagHelperAttributeList contextAttributes, out TagHelperAttributeList outputAttributes)
        {
            contextAttributes = new TagHelperAttributeList();
            outputAttributes  = new TagHelperAttributeList();

            ITagHelper tagHelper;

            if (_activatorByService != null)
            {
                tagHelper = _activatorByService(context);
            }
            else
            {
                tagHelper = _activatorByFactory(factory, context);
            }

            var expresionProvider = context.HttpContext.RequestServices.GetRequiredService <ModelExpressionProvider>();

            var viewData = context.ViewData as ViewDataDictionary <object>;

            if (viewData == null)
            {
                viewData = new ViewDataDictionary <object>(context.ViewData);
            }

            foreach (var name in arguments.Names)
            {
                var propertyName   = name.ToPascalCaseUnderscore();
                var dictionaryName = String.Empty;
                var dictionaryKey  = String.Empty;

                if (!_setters.TryGetValue(propertyName, out var setter))
                {
                    var index = name.LastIndexOf('_');

                    if (index > -1)
                    {
                        dictionaryName = name.Substring(0, index + 1);
                        dictionaryKey  = name.Substring(index + 1);

                        if (dictionaryName.Length > 0 && dictionaryKey.Length > 0)
                        {
                            _setters.TryGetValue(dictionaryName, out setter);
                        }
                    }
                }

                var found = false;

                if (setter != null)
                {
                    try
                    {
                        setter(tagHelper, expresionProvider, viewData, dictionaryKey, arguments[name]);
                        found = true;
                    }
                    catch (ArgumentException e)
                    {
                        throw new ArgumentException("Incorrect value type assigned to a tag.", name, e);
                    }
                }

                var attribute = new TagHelperAttribute(name.Replace('_', '-'), arguments[name].ToObjectValue());

                contextAttributes.Add(attribute);

                if (!found)
                {
                    outputAttributes.Add(attribute);
                }
            }

            return(tagHelper);
        }
Example #35
0
 /// <summary>
 /// 获取结果
 /// </summary>
 private string GetResult(TagHelperAttributeList contextAttributes = null, TagHelperAttributeList outputAttributes = null, TagHelperContent content = null)
 {
     contextAttributes = contextAttributes ?? new TagHelperAttributeList();
     contextAttributes.Add(UiConst.Type, TextBoxType.Number);
     return(Helper.GetResult(_output, _component, contextAttributes, outputAttributes, content));
 }
Example #36
0
        public async Task ProcessAsync_CallsGenerateTextBox_WithExpectedParameters(
            string dataTypeName,
            string inputTypeName,
            string model)
        {
            // Arrange
            var contextAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };

            if (!string.IsNullOrEmpty(inputTypeName))
            {
                contextAttributes.SetAttribute("type", inputTypeName);  // Support restoration of type attribute, if any.
            }

            var expectedAttributes = new TagHelperAttributeList
            {
                { "class", "form-control text-control" },
                { "type", inputTypeName ?? "text" },        // Generator restores type attribute; adds "text" if none.
            };
            var expectedPreContent  = "original pre-content";
            var expectedContent     = "original content";
            var expectedPostContent = "original post-content";
            var expectedTagName     = "not-input";

            var context = new TagHelperContext(
                allAttributes: contextAttributes,
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var originalAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };
            var output = new TagHelperOutput(
                expectedTagName,
                originalAttributes,
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            })
            {
                TagMode = TagMode.StartTagOnly,
            };

            output.PreContent.SetContent(expectedPreContent);
            output.Content.SetContent(expectedContent);
            output.PostContent.SetContent(expectedPostContent);

            var metadataProvider = new TestModelMetadataProvider();

            metadataProvider.ForProperty <Model>("Text").DisplayDetails(dd => dd.DataTypeName = dataTypeName);

            var htmlGenerator = new Mock <IHtmlGenerator>(MockBehavior.Strict);
            var tagHelper     = GetTagHelper(
                htmlGenerator.Object,
                model,
                nameof(Model.Text),
                metadataProvider: metadataProvider);

            tagHelper.InputTypeName = inputTypeName;

            var tagBuilder = new TagBuilder("input")
            {
                Attributes =
                {
                    { "class", "text-control" },
                },
            };

            htmlGenerator
            .Setup(mock => mock.GenerateTextBox(
                       tagHelper.ViewContext,
                       tagHelper.For.ModelExplorer,
                       tagHelper.For.Name,
                       model,                                                             // value
                       null,                                                              // format
                       It.Is <Dictionary <string, object> >(m => m.ContainsKey("type")))) // htmlAttributes
            .Returns(tagBuilder)
            .Verifiable();

            // Act
            await tagHelper.ProcessAsync(context, output);

            // Assert
            htmlGenerator.Verify();

            Assert.Equal(TagMode.StartTagOnly, output.TagMode);
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Equal(expectedPreContent, output.PreContent.GetContent());
            Assert.Equal(expectedContent, output.Content.GetContent());
            Assert.Equal(expectedPostContent, output.PostContent.GetContent());
            Assert.Equal(expectedTagName, output.TagName);
        }
 private bool CanBeActive(TagHelperAttributeList attributes)
 => ActiveClass != null && attributes.ContainsName("href") && attributes["href"].Value != null;
Example #38
0
        /// <summary>
        /// 获取结果
        /// </summary>
        /// <typeparam name="TTagHelper">TagHelper组件类型</typeparam>
        /// <param name="outputHelper">输出工具</param>
        /// <param name="component">TagHelper组件</param>
        /// <param name="contextAttributes">上下文属性集合</param>
        /// <param name="outputAttributes">输出属性集合</param>
        /// <param name="content">内容</param>
        /// <param name="items">项集合</param>
        public static string GetResult <TTagHelper>(ITestOutputHelper outputHelper, TTagHelper component, TagHelperAttributeList contextAttributes = null,
                                                    TagHelperAttributeList outputAttributes = null, TagHelperContent content = null, IDictionary <object, object> items = null) where TTagHelper : TagHelper
        {
            var context = new TagHelperContext("", contextAttributes ?? new TagHelperAttributeList(), items ?? new Dictionary <object, object>(), Id.Guid());
            var output  = new TagHelperOutput("", outputAttributes ?? new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult(content));

            component.ProcessAsync(context, output);
            var writer = new StringWriter();

            output.WriteTo(writer, HtmlEncoder.Default);
            var result = writer.ToString();

            outputHelper.WriteLine(result);
            return(result);
        }
        public async Task ProcessAsync_DoesNotUseGenerator_IfSelectedNullOrNoSelectedValues(
            string originalContent,
            string selected,
            string value,
            IEnumerable<string> selectedValues,
            TagHelperOutput ignored)
        {
            // Arrange
            var originalAttributes = new TagHelperAttributeList
            {
                { "label", "my-label" },
                { "selected", selected },
            };
            var originalTagName = "not-option";

            var contextAttributes = new TagHelperAttributeList
            {
                { "label", "my-label" },
                { "selected", selected },
                { "value", value },
            };
            var originalPreContent = "original pre-content";
            var originalPostContent = "original post-content";
            var tagHelperContext = new TagHelperContext(
                contextAttributes,
                items: new Dictionary<object, object>(),
                uniqueId: "test",
                getChildContentAsync: useCachedResult =>
                {
                    var tagHelperContent = new DefaultTagHelperContent();
                    tagHelperContent.SetContent(originalContent);
                    return Task.FromResult<TagHelperContent>(tagHelperContent);
                });
            var output = new TagHelperOutput(originalTagName, originalAttributes)
            {
                TagMode = TagMode.StartTagAndEndTag,
            };
            output.PreContent.SetContent(originalPreContent);
            output.Content.SetContent(originalContent);
            output.PostContent.SetContent(originalPostContent);

            var metadataProvider = new EmptyModelMetadataProvider();
            var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
            var viewContext = TestableHtmlGenerator.GetViewContext(
                model: null,
                htmlGenerator: htmlGenerator,
                metadataProvider: metadataProvider);
            viewContext.FormContext.FormData[SelectTagHelper.SelectedValuesFormDataKey] = selectedValues;
            var tagHelper = new OptionTagHelper(htmlGenerator)
            {
                Value = value,
                ViewContext = viewContext,
            };

            // Act & Assert (does not throw)
            // Tag helper would throw an NRE if it used Generator value.
            await tagHelper.ProcessAsync(tagHelperContext, output);
        }
Example #40
0
        public TagBuilder GenerateTextArea(ViewContext viewContext, ModelExpression modelExpression, TagHelperAttributeList attributes, Localization localization = null, string additionalCssClass = null)
        {
            TagBuilder tb = new TagBuilder("textarea");

            if (!string.IsNullOrEmpty(additionalCssClass))
            {
                tb.AddCssClass(additionalCssClass);
            }

            tb.AddCssClass("text-area");

            if (!this.IsValid(viewContext, modelExpression, localization))
            {
                tb.AddCssClass("input-validation-error");
            }

            tb.MergeAttribute("id", this.GetIdentity(modelExpression, localization));
            tb.MergeAttribute("name", this.GetIdentity(modelExpression, localization));

            if (localization != null)
            {
                tb.MergeAttribute("data-culture", localization.Culture.Code);
            }

            this.MergeRequiredAttribute(tb, modelExpression, "text-area--required");
            this.MergeStringLengthAttribute(tb, modelExpression);
            this.MergeOtherAttribute(tb, attributes);

            string value = this.GetValue(viewContext, modelExpression, localization);

            if (!string.IsNullOrEmpty(value))
            {
                tb.InnerHtml.Clear();
                tb.InnerHtml.Append(value);
            }

            return(tb);
        }
        public async Task ProcessAsync_GeneratesExpectedOutput_WithPropertyErrors()
        {
            // Arrange
            var expectedError0     = "I am an error.";
            var expectedError2     = "I am also an error.";
            var expectedTagName    = "not-div";
            var expectedAttributes = new TagHelperAttributeList
            {
                new TagHelperAttribute("class", "form-control validation-summary-errors"),
                new TagHelperAttribute("data-valmsg-summary", "true"),
            };

            var metadataProvider           = new TestModelMetadataProvider();
            var htmlGenerator              = new TestableHtmlGenerator(metadataProvider);
            var validationSummaryTagHelper = new ValidationSummaryTagHelper(htmlGenerator)
            {
                ValidationSummary = ValidationSummary.All,
            };

            var expectedPreContent = "original pre-content";
            var expectedContent    = "original content";
            var tagHelperContext   = new TagHelperContext(
                tagName: "not-div",
                allAttributes: new TagHelperAttributeList(),
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var output = new TagHelperOutput(
                expectedTagName,
                attributes: new TagHelperAttributeList
            {
                { "class", "form-control" }
            },
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            });

            output.PreContent.SetContent(expectedPreContent);
            output.Content.SetContent(expectedContent);
            output.PostContent.SetContent("Custom Content");

            var model       = new Model();
            var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);

            validationSummaryTagHelper.ViewContext = viewContext;

            var modelState = viewContext.ModelState;

            SetValidModelState(modelState);
            modelState.AddModelError(key: $"{nameof(Model.Strings)}[0]", errorMessage: expectedError0);
            modelState.AddModelError(key: $"{nameof(Model.Strings)}[2]", errorMessage: expectedError2);

            // Act
            await validationSummaryTagHelper.ProcessAsync(tagHelperContext, output);

            // Assert
            Assert.Equal(expectedAttributes, output.Attributes, CaseSensitiveTagHelperAttributeComparer.Default);
            Assert.Equal(expectedPreContent, output.PreContent.GetContent());
            Assert.Equal(expectedContent, output.Content.GetContent());
            Assert.Equal(
                $"Custom Content<ul><li>{expectedError0}</li>{Environment.NewLine}" +
                $"<li>{expectedError2}</li>{Environment.NewLine}</ul>",
                output.PostContent.GetContent());
            Assert.Equal(expectedTagName, output.TagName);
        }
Example #42
0
        private static TagHelperOutput MakeImageTagHelperOutput(TagHelperAttributeList attributes)
        {
            attributes = attributes ?? new TagHelperAttributeList();

            return new TagHelperOutput("img", attributes);
        }
Example #43
0
        protected virtual string RenderTagHelper(TagHelperAttributeList attributeList, TagHelperContext context, TagHelper tagHelper, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing, bool runAsync = false)
        {
            var innerOutput = GetInnerTagHelper(attributeList, context, tagHelper, tagName, tagMode, runAsync);

            return(RenderTagHelperOutput(innerOutput, htmlEncoder));
        }
        public async Task ProcessAsync_DoesNotUseViewContext_IfSelectedNotNull(
            string originalContent,
            string selected,
            string value,
            IEnumerable<string> ignoredValues,
            TagHelperOutput ignoredOutput)
        {
            // Arrange
            var originalAttributes = new TagHelperAttributeList
            {
                { "label", "my-label" },
                { "selected", selected },
            };
            var originalTagName = "not-option";

            var contextAttributes = new TagHelperAttributeList
            {
                { "label", "my-label" },
                { "selected", selected },
                { "value", value },
            };
            var originalPreContent = "original pre-content";
            var originalPostContent = "original post-content";
            var tagHelperContext = new TagHelperContext(
                contextAttributes,
                items: new Dictionary<object, object>(),
                uniqueId: "test",
                getChildContentAsync: () =>
                {
                    var tagHelperContent = new DefaultTagHelperContent();
                    tagHelperContent.SetContent(originalContent);
                    return Task.FromResult<TagHelperContent>(tagHelperContent);
                });

            var output = new TagHelperOutput(originalTagName, originalAttributes)
            {
                SelfClosing = false,
            };
            output.PreContent.SetContent(originalPreContent);
            output.Content.SetContent(originalContent);
            output.PostContent.SetContent(originalPostContent);

            var metadataProvider = new EmptyModelMetadataProvider();
            var htmlGenerator = new TestableHtmlGenerator(metadataProvider);

            var tagHelper = new OptionTagHelper(htmlGenerator)
            {
                Value = value,
            };

            // Act & Assert (does not throw)
            // Tag helper would throw an NRE if it used ViewContext or Generator values.
            await tagHelper.ProcessAsync(tagHelperContext, output);
        }
Example #45
0
    public static async Task <string> RenderAsync(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing)
    {
        var innerOutput = await tagHelper.ProcessAndGetOutputAsync(attributeList, context, tagName, tagMode);

        return(innerOutput.Render(htmlEncoder));
    }
Example #46
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);
        }
Example #47
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);
        }
Example #48
0
 /// <summary>
 /// 获取结果
 /// </summary>
 private string GetResult(TagHelperAttributeList contextAttributes = null, TagHelperAttributeList outputAttributes = null, TagHelperContent content = null)
 {
     return(Helper.GetResult(_output, _component, contextAttributes, outputAttributes, content));
 }
Example #49
0
 private List <TagHelperAttribute> GetTabAttributesByPrefix(TagHelperAttributeList attributes, string prefix)
 {
     return(attributes.Where(a => a.Name.StartsWith(prefix))
            .Select(a => new TagHelperAttribute(a.Name.Substring(prefix.Length), a.Value)).ToList());
 }
Example #50
0
        public async Task ProcessAsync_CallsGenerateCheckBox_WithExpectedParameters()
        {
            // Arrange
            var originalContent     = "original content";
            var originalTagName     = "not-input";
            var expectedPreContent  = "original pre-content";
            var expectedContent     = originalContent + "<input class=\"HtmlEncode[[form-control]]\" /><hidden />";
            var expectedPostContent = "original post-content";

            var context = new TagHelperContext(
                allAttributes: new TagHelperAttributeList(
                    Enumerable.Empty <TagHelperAttribute>()),
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var originalAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };
            var output = new TagHelperOutput(
                originalTagName,
                originalAttributes,
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            })
            {
                TagMode = TagMode.SelfClosing,
            };

            output.PreContent.AppendHtml(expectedPreContent);
            output.Content.AppendHtml(originalContent);
            output.PostContent.AppendHtml(expectedPostContent);

            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" },
                },
                TagRenderMode = TagRenderMode.SelfClosing
            };

            htmlGenerator
            .Setup(mock => mock.GenerateCheckBox(
                       tagHelper.ViewContext,
                       tagHelper.For.ModelExplorer,
                       tagHelper.For.Name,
                       null,                 // isChecked
                       It.IsAny <object>())) // htmlAttributes
            .Returns(tagBuilder)
            .Verifiable();
            htmlGenerator
            .Setup(mock => mock.GenerateHiddenForCheckbox(
                       tagHelper.ViewContext,
                       tagHelper.For.ModelExplorer,
                       tagHelper.For.Name))
            .Returns(new TagBuilder("hidden")
            {
                TagRenderMode = TagRenderMode.SelfClosing
            })
            .Verifiable();

            // Act
            await tagHelper.ProcessAsync(context, output);

            // Assert
            htmlGenerator.Verify();

            Assert.Empty(output.Attributes);    // Moved to Content and cleared
            Assert.Equal(expectedPreContent, output.PreContent.GetContent());
            Assert.Equal(expectedContent, HtmlContentUtilities.HtmlContentToString(output.Content));
            Assert.Equal(expectedPostContent, output.PostContent.GetContent());
            Assert.Equal(TagMode.SelfClosing, output.TagMode);
            Assert.Null(output.TagName);       // Cleared
        }
        public void TagHelperExecutionContext_MaintainsAllAttributes()
        {
            // Arrange
            var executionContext = new TagHelperExecutionContext("p", TagMode.StartTagAndEndTag);
            var expectedAttributes = new TagHelperAttributeList
            {
                { "class", "btn" },
                { "something", true },
                { "foo", "bar" }
            };

            // Act
            executionContext.AddHtmlAttribute("class", "btn");
            executionContext.AddTagHelperAttribute("something", true);
            executionContext.AddHtmlAttribute("foo", "bar");

            // Assert
            Assert.Equal(
                expectedAttributes,
                executionContext.AllAttributes,
                CaseSensitiveTagHelperAttributeComparer.Default);
        }
Example #52
0
        public async Task ProcessAsync_GeneratesExpectedOutput(
            object model,
            Type containerType,
            Func <object> modelAccessor,
            string propertyPath,
            TagHelperOutputContent tagHelperOutputContent)
        {
            // Arrange
            var expectedTagName    = "not-label";
            var expectedAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
                { "for", tagHelperOutputContent.ExpectedId }
            };
            var metadataProvider = new TestModelMetadataProvider();

            var containerMetadata = metadataProvider.GetMetadataForType(containerType);
            var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model);

            var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text");
            var modelExplorer    = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor());
            var htmlGenerator    = new TestableHtmlGenerator(metadataProvider);

            var modelExpression = new ModelExpression(propertyPath, modelExplorer);
            var tagHelper       = new LabelTagHelper(htmlGenerator)
            {
                For = modelExpression,
            };
            var expectedPreContent  = "original pre-content";
            var expectedPostContent = "original post-content";

            var tagHelperContext = new TagHelperContext(
                allAttributes: new ReadOnlyTagHelperAttributeList <IReadOnlyTagHelperAttribute>(
                    Enumerable.Empty <IReadOnlyTagHelperAttribute>()),
                items: new Dictionary <object, object>(),
                uniqueId: "test",
                getChildContentAsync: useCachedResult =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.SetContent(tagHelperOutputContent.OriginalChildContent);
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            });
            var htmlAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };
            var output = new TagHelperOutput(expectedTagName, htmlAttributes);

            output.PreContent.SetContent(expectedPreContent);
            output.PostContent.SetContent(expectedPostContent);

            // LabelTagHelper checks IsContentModified so we don't want to forcibly set it if
            // tagHelperOutputContent.OriginalContent is going to be null or empty.
            if (!string.IsNullOrEmpty(tagHelperOutputContent.OriginalContent))
            {
                output.Content.SetContent(tagHelperOutputContent.OriginalContent);
            }

            var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);

            tagHelper.ViewContext = viewContext;

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

            // Assert
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Equal(expectedPreContent, output.PreContent.GetContent());
            Assert.Equal(
                tagHelperOutputContent.ExpectedContent,
                HtmlContentUtilities.HtmlContentToString(output.Content));
            Assert.Equal(expectedPostContent, output.PostContent.GetContent());
            Assert.Equal(TagMode.StartTagAndEndTag, output.TagMode);
            Assert.Equal(expectedTagName, output.TagName);
        }
Example #53
0
        private static int IndexOfFirstMatch(string name, TagHelperAttributeList attributes)
        {
            for (var i = 0; i < attributes.Count; i++)
            {
                if (string.Equals(name, attributes[i].Name, StringComparison.OrdinalIgnoreCase))
                {
                    return i;
                }
            }

            return -1;
        }
Example #54
0
    public async Task ProcessAsync_GeneratesExpectedOutput(
        string originalContent,
        string selected,
        string value,
        ICollection <string> currentValues,
        TagHelperOutput expectedTagHelperOutput)
    {
        // Arrange
        var originalAttributes = new TagHelperAttributeList
        {
            { "label", "my-label" },
        };

        if (selected != null)
        {
            originalAttributes.Add("selected", selected);
        }

        var contextAttributes = new TagHelperAttributeList(originalAttributes);

        if (value != null)
        {
            contextAttributes.Add("value", value);
        }

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

        var output = new TagHelperOutput(
            expectedTagHelperOutput.TagName,
            originalAttributes,
            getChildContentAsync: (useCachedResult, encoder) =>
        {
            // GetChildContentAsync should not be invoked since we are setting the content below.
            Assert.True(false);
            return(Task.FromResult <TagHelperContent>(null));
        })
        {
            TagMode = TagMode.StartTagAndEndTag
        };

        output.Content.SetContent(originalContent);

        var metadataProvider = new EmptyModelMetadataProvider();
        var htmlGenerator    = new TestableHtmlGenerator(metadataProvider);
        var viewContext      = TestableHtmlGenerator.GetViewContext(
            model: null,
            htmlGenerator: htmlGenerator,
            metadataProvider: metadataProvider);

        tagHelperContext.Items[typeof(SelectTagHelper)] = currentValues == null ? null : new CurrentValues(currentValues);
        var tagHelper = new OptionTagHelper(htmlGenerator)
        {
            Value       = value,
            ViewContext = viewContext,
        };

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

        // Assert
        Assert.Equal(expectedTagHelperOutput.TagName, output.TagName);
        Assert.Equal(expectedTagHelperOutput.Content.GetContent(), output.Content.GetContent());
        Assert.Equal(expectedTagHelperOutput.Attributes.Count, output.Attributes.Count);
        foreach (var attribute in output.Attributes)
        {
            Assert.Contains(attribute, expectedTagHelperOutput.Attributes);
        }
    }
Example #55
0
 private static TagHelperContext MakeTagHelperContext(
     TagHelperAttributeList attributes)
 {
     return new TagHelperContext(
         attributes,
         items: new Dictionary<object, object>(),
         uniqueId: Guid.NewGuid().ToString("N"),
         getChildContentAsync: () =>
         {
             var tagHelperContent = new DefaultTagHelperContent();
             tagHelperContent.SetContent(default(string));
             return Task.FromResult<TagHelperContent>(tagHelperContent);
         });
 }
Example #56
0
    public async Task ProcessAsync_DoesNotUseGenerator_IfSelectedNullOrNoSelectedValues(
        string originalContent,
        string selected,
        string value,
        ICollection <string> currentValues,
        TagHelperOutput _)
    {
        // Arrange
        var originalAttributes = new TagHelperAttributeList
        {
            { "label", "my-label" },
            { "selected", selected },
        };
        var originalTagName = "not-option";

        var contextAttributes = new TagHelperAttributeList
        {
            { "label", "my-label" },
            { "selected", selected },
            { "value", value },
        };
        var originalPreContent  = "original pre-content";
        var originalPostContent = "original post-content";
        var tagHelperContext    = new TagHelperContext(
            tagName: "option",
            allAttributes: contextAttributes,
            items: new Dictionary <object, object>(),
            uniqueId: "test");
        var output = new TagHelperOutput(
            originalTagName,
            originalAttributes,
            getChildContentAsync: (useCachedResult, encoder) =>
        {
            var tagHelperContent = new DefaultTagHelperContent();
            tagHelperContent.SetContent(originalContent);
            return(Task.FromResult <TagHelperContent>(tagHelperContent));
        })
        {
            TagMode = TagMode.StartTagAndEndTag,
        };

        output.PreContent.SetContent(originalPreContent);
        output.Content.SetContent(originalContent);
        output.PostContent.SetContent(originalPostContent);

        var metadataProvider = new EmptyModelMetadataProvider();
        var htmlGenerator    = new TestableHtmlGenerator(metadataProvider);
        var viewContext      = TestableHtmlGenerator.GetViewContext(
            model: null,
            htmlGenerator: htmlGenerator,
            metadataProvider: metadataProvider);

        tagHelperContext.Items[typeof(SelectTagHelper)] = currentValues == null ? null : new CurrentValues(currentValues);
        var tagHelper = new OptionTagHelper(htmlGenerator)
        {
            Value       = value,
            ViewContext = viewContext,
        };

        // Act & Assert (does not throw)
        // Tag helper would throw an NRE if it used Generator value.
        await tagHelper.ProcessAsync(tagHelperContext, output);
    }
        public async Task ProcessAsync_GeneratesExpectedOutput(
            string originalContent,
            string selected,
            string value,
            IEnumerable<string> selectedValues,
            TagHelperOutput expectedTagHelperOutput)
        {
            // Arrange
            var originalAttributes = new TagHelperAttributeList
            {
                { "label", "my-label" },
            };
            if (selected != null)
            {
                originalAttributes.Add("selected", selected);
            }

            var contextAttributes = new TagHelperAttributeList(originalAttributes);
            if (value != null)
            {
                contextAttributes.Add("value", value);
            }

            var tagHelperContext = new TagHelperContext(
                contextAttributes,
                items: new Dictionary<object, object>(),
                uniqueId: "test",
                getChildContentAsync: () =>
                {
                    // GetChildContentAsync should not be invoked since we are setting the content below.
                    Assert.True(false);
                    return Task.FromResult<TagHelperContent>(null);
                });

            var output = new TagHelperOutput(expectedTagHelperOutput.TagName, originalAttributes)
            {
                SelfClosing = false,
            };

            output.Content.SetContent(originalContent);

            var metadataProvider = new EmptyModelMetadataProvider();
            var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
            var viewContext = TestableHtmlGenerator.GetViewContext(
                model: null,
                htmlGenerator: htmlGenerator,
                metadataProvider: metadataProvider);
            viewContext.FormContext.FormData[SelectTagHelper.SelectedValuesFormDataKey] = selectedValues;
            var tagHelper = new OptionTagHelper(htmlGenerator)
            {
                Value = value,
                ViewContext = viewContext,
            };

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

            // Assert
            Assert.Equal(expectedTagHelperOutput.TagName, output.TagName);
            Assert.Equal(expectedTagHelperOutput.Content.GetContent(), output.Content.GetContent());
            Assert.Equal(expectedTagHelperOutput.Attributes.Count, output.Attributes.Count);
            foreach (var attribute in output.Attributes)
            {
                Assert.Contains(attribute, expectedTagHelperOutput.Attributes);
            }
        }
Example #58
0
        private TagHelperOutput MakeTagHelperOutput(string tagName, TagHelperAttributeList attributes = null)
        {
            attributes = attributes ?? new TagHelperAttributeList();

            return(new TagHelperOutput(tagName, attributes));
        }
        private static TagHelperOutput GetTagHelperOutput(
            string tagName, TagHelperAttributeList attributes, string content)
        {
            var tagHelperOutput = new TagHelperOutput(tagName, attributes);
            tagHelperOutput.Content.SetContent(content);

            return tagHelperOutput;
        }
Example #60
0
        public async Task ProcessAsyncInTemplate_WithItems_GeneratesExpectedOutput_DoesNotChangeSelectList(
            object model,
            Type containerType,
            Func <object> modelAccessor,
            NameAndId nameAndId,
            string expectedOptions)
        {
            // Arrange
            var originalAttributes = new TagHelperAttributeList
            {
                { "class", "form-control" },
            };
            var originalPostContent = "original content";

            var expectedAttributes = new TagHelperAttributeList(originalAttributes)
            {
                { "id", nameAndId.Id },
                { "name", nameAndId.Name },
                { "valid", "from validation attributes" },
            };
            var expectedPreContent  = "original pre-content";
            var expectedContent     = "original content";
            var expectedPostContent = originalPostContent + expectedOptions;
            var expectedTagName     = "select";

            var metadataProvider = new TestModelMetadataProvider();

            var containerMetadata = metadataProvider.GetMetadataForType(containerType);
            var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model);

            var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text");
            var modelExplorer    = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor());

            var modelExpression = new ModelExpression(name: string.Empty, modelExplorer: modelExplorer);

            var tagHelperContext = new TagHelperContext(
                tagName: "select",
                allAttributes: new TagHelperAttributeList(
                    Enumerable.Empty <TagHelperAttribute>()),
                items: new Dictionary <object, object>(),
                uniqueId: "test");
            var output = new TagHelperOutput(
                expectedTagName,
                originalAttributes,
                getChildContentAsync: (useCachedResult, encoder) =>
            {
                var tagHelperContent = new DefaultTagHelperContent();
                tagHelperContent.AppendHtml("Something");
                return(Task.FromResult <TagHelperContent>(tagHelperContent));
            })
            {
                TagMode = TagMode.SelfClosing,
            };

            output.PreContent.AppendHtml(expectedPreContent);
            output.Content.AppendHtml(expectedContent);
            output.PostContent.AppendHtml(originalPostContent);

            var htmlGenerator = new TestableHtmlGenerator(metadataProvider)
            {
                ValidationAttributes =
                {
                    { "valid", "from validation attributes" },
                }
            };
            var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);

            viewContext.ViewData.TemplateInfo.HtmlFieldPrefix = nameAndId.Name;

            var items         = new SelectList(new[] { "", "outer text", "inner text", "other text" });
            var savedDisabled = items.Select(item => item.Disabled).ToList();
            var savedGroup    = items.Select(item => item.Group).ToList();
            var savedSelected = items.Select(item => item.Selected).ToList();
            var savedText     = items.Select(item => item.Text).ToList();
            var savedValue    = items.Select(item => item.Value).ToList();
            var tagHelper     = new SelectTagHelper(htmlGenerator)
            {
                For         = modelExpression,
                Items       = items,
                ViewContext = viewContext,
            };

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

            // Assert
            Assert.Equal(TagMode.SelfClosing, output.TagMode);
            Assert.Equal(expectedAttributes, output.Attributes);
            Assert.Equal(expectedPreContent, output.PreContent.GetContent());
            Assert.Equal(expectedContent, output.Content.GetContent());
            Assert.Equal(expectedPostContent, HtmlContentUtilities.HtmlContentToString(output.PostContent));
            Assert.Equal(expectedTagName, output.TagName);

            Assert.Single(
                tagHelperContext.Items,
                entry => (Type)entry.Key == typeof(SelectTagHelper));

            Assert.Equal(savedDisabled, items.Select(item => item.Disabled));
            Assert.Equal(savedGroup, items.Select(item => item.Group));
            Assert.Equal(savedSelected, items.Select(item => item.Selected));
            Assert.Equal(savedText, items.Select(item => item.Text));
            Assert.Equal(savedValue, items.Select(item => item.Value));
        }