public void LogDetails_LogsWhenPartiallyMatchedAttributesFound() { // Arrange var modeMatchResult = new ModeMatchResult <string>(); modeMatchResult.PartialMatches.Add( ModeMatchAttributes.Create("mode0", new[] { "first-attr" }, new[] { "second-attr" })); modeMatchResult.PartiallyMatchedAttributes.Add("first-attr"); var logger = MakeLogger(LogLevel.Verbose); var tagHelper = new Mock <ITagHelper>(); var uniqueId = "id"; var viewPath = "Views/Home/Index.cshtml"; // Act modeMatchResult.LogDetails(logger, tagHelper.Object, uniqueId, viewPath); // Assert Mock.Get(logger).Verify(l => l.Log( LogLevel.Warning, It.IsAny <int>(), It.IsAny <object>(), It.IsAny <Exception>(), It.IsAny <Func <object, Exception, string> >()), Times.Once); Mock.Get(logger).Verify(l => l.Log( LogLevel.Verbose, It.IsAny <int>(), It.IsAny <object>(), It.IsAny <Exception>(), It.IsAny <Func <object, Exception, string> >()), Times.Once); }
/// <summary> /// Determines the modes a <see cref="ITagHelper" /> can run in based on which modes have all their required /// attributes present, non null, non empty, and non whitepsace. /// </summary> /// <typeparam name="TMode">The type representing the <see cref="ITagHelper" />'s modes.</typeparam> /// <param name="context">The <see cref="TagHelperContext"/>.</param> /// <param name="modeInfos">The modes and their required attributes.</param> /// <returns>The <see cref="ModeMatchResult{TMode}"/>.</returns> public static ModeMatchResult <TMode> DetermineMode <TMode>( [NotNull] TagHelperContext context, [NotNull] IEnumerable <ModeAttributes <TMode> > modeInfos) { // true == full match, false == partial match var matchedAttributes = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase); var result = new ModeMatchResult <TMode>(); foreach (var modeInfo in modeInfos) { var modeAttributes = GetPresentMissingAttributes(context, modeInfo.Attributes); if (modeAttributes.Present.Any()) { if (!modeAttributes.Missing.Any()) { // A complete match, mark the attribute as fully matched foreach (var attribute in modeAttributes.Present) { matchedAttributes[attribute] = true; } result.FullMatches.Add(ModeMatchAttributes.Create(modeInfo.Mode, modeInfo.Attributes)); } else { // A partial match, mark the attribute as partially matched if not already fully matched foreach (var attribute in modeAttributes.Present) { bool attributeMatch; if (!matchedAttributes.TryGetValue(attribute, out attributeMatch)) { matchedAttributes[attribute] = false; } } result.PartialMatches.Add(ModeMatchAttributes.Create( modeInfo.Mode, modeAttributes.Present, modeAttributes.Missing)); } } } // Build the list of partially matched attributes (those with partial matches but no full matches) foreach (var attribute in matchedAttributes.Keys) { if (!matchedAttributes[attribute]) { result.PartiallyMatchedAttributes.Add(attribute); } } return(result); }