Add tests to validate creation of TagHelperUsageDescriptors.

- Could not add tests to validate the full TagHelperDescriptorFactory.CreateDescriptors => TagHelperUsageDescriptors due to how the runtime loads assemblies (does it in memory without XML).
- Added serialization tests to include TagHelperUsageDescriptors.
- Updated existing tests to use new TagHelperDescriptor/TagHelperAttributeDescriptor constructors.

#352
This commit is contained in:
N. Taylor Mullen 2015-06-12 14:49:22 -07:00
parent ccf8433f27
commit 9055da1894
22 changed files with 1182 additions and 178 deletions

View File

@ -1,44 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class CaseSensitiveTagHelperAttributeDescriptorComparer : TagHelperAttributeDescriptorComparer
{
public new static readonly CaseSensitiveTagHelperAttributeDescriptorComparer Default =
new CaseSensitiveTagHelperAttributeDescriptorComparer();
private CaseSensitiveTagHelperAttributeDescriptorComparer()
: base()
{
}
public override bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
{
if (descriptorX == descriptorY)
{
return true;
}
// Base comparer does not care about Name case but in tests we do. Also double-check IsStringProperty
// though it is inferred from TypeName.
return base.Equals(descriptorX, descriptorY) &&
descriptorX.IsStringProperty == descriptorY.IsStringProperty &&
string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.Ordinal);
}
public override int GetHashCode(TagHelperAttributeDescriptor descriptor)
{
// Ignore IsStringProperty because it is directly inferred from TypeName and thus won't vary the hash
// bucket. Base comparer does not care about Name case in its hash code but in tests we do.
return HashCodeCombiner.Start()
.Add(base.GetHashCode(descriptor))
.Add(descriptor.Name, StringComparer.Ordinal)
.CombinedHash;
}
}
}

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
StringComparer.Ordinal) &&
descriptorX.Attributes.SequenceEqual(
descriptorY.Attributes,
CaseSensitiveTagHelperAttributeDescriptorComparer.Default);
TagHelperAttributeDescriptorComparer.Default);
}
public override int GetHashCode(TagHelperDescriptor descriptor)
@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
foreach (var attribute in descriptor.Attributes)
{
hashCodeCombiner.Add(CaseSensitiveTagHelperAttributeDescriptorComparer.Default.GetHashCode(attribute));
hashCodeCombiner.Add(TagHelperAttributeDescriptorComparer.Default.GetHashCode(attribute));
}
return hashCodeCombiner.CombinedHash;

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class Valid_PlainTagHelper : TagHelper
@ -32,4 +34,33 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
internal string InvalidInternalAttribute { get; set; }
protected internal string InvalidProtectedInternalAttribute { get; set; }
}
/// <summary>
/// The summary for <see cref="DocumentedTagHelper"/>.
/// </summary>
/// <remarks>
/// Inherits from <see cref="TagHelper"/>.
/// </remarks>
public class DocumentedTagHelper : TagHelper
{
/// <summary>
/// This <see cref="SummaryProperty"/> is of type <see cref="string"/>.
/// </summary>
public string SummaryProperty { get; set; }
/// <remarks>
/// The <see cref="SummaryProperty"/> may be <c>null</c>.
/// </remarks>
public int RemarksProperty { get; set; }
/// <summary>
/// This is a complex <see cref="IDictionary{string, bool}"/>.
/// </summary>
/// <remarks>
/// <see cref="SummaryProperty"/><see cref="RemarksProperty"/>
/// </remarks>
public IDictionary<string, bool> RemarksAndSummaryProperty { get; set; }
public bool UndocumentedProperty { get; set; }
}
}

View File

@ -0,0 +1,51 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class TagHelperAttributeDescriptorComparer : IEqualityComparer<TagHelperAttributeDescriptor>
{
public static readonly TagHelperAttributeDescriptorComparer Default =
new TagHelperAttributeDescriptorComparer();
private TagHelperAttributeDescriptorComparer()
{
}
public bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
{
if (descriptorX == descriptorY)
{
return true;
}
return descriptorX != null &&
descriptorY != null &&
descriptorX.IsIndexer == descriptorY.IsIndexer &&
string.Equals(descriptorX.Name, descriptorY.Name, StringComparison.Ordinal) &&
string.Equals(descriptorX.PropertyName, descriptorY.PropertyName, StringComparison.Ordinal) &&
string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) &&
TagHelperUsageDescriptorComparer.Default.Equals(
descriptorX.UsageDescriptor,
descriptorY.UsageDescriptor);
}
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
{
// Ignore IsStringProperty because it is directly inferred from TypeName and thus won't vary the hash
// bucket.
return HashCodeCombiner.Start()
.Add(descriptor.IsIndexer)
.Add(descriptor.Name, StringComparer.Ordinal)
.Add(descriptor.PropertyName, StringComparer.Ordinal)
.Add(descriptor.TypeName, StringComparer.Ordinal)
.Add(TagHelperUsageDescriptorComparer.Default.GetHashCode(descriptor.UsageDescriptor))
.CombinedHash;
}
}
}

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Razor.TagHelpers;
@ -210,7 +209,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
tagHelperType,
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -258,7 +258,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
tagHelperType,
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -294,7 +295,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(OverriddenAttributeTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -327,7 +329,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(InheritedOverriddenAttributeTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -360,7 +363,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(InheritedNotOverriddenAttributeTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -380,7 +384,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
objectAssemblyName,
typeof(object),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -406,14 +411,16 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
nameof(InheritedSingleAttributeTagHelper.IntAttribute),
typeof(int).FullName,
isIndexer: false,
isStringProperty: false)
isStringProperty: false,
usageDescriptor: null)
});
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(InheritedSingleAttributeTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -440,7 +447,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(SingleAttributeTagHelper),
new ErrorSink());
designTime: false,
errorSink: new ErrorSink());
// Assert
Assert.Empty(errorSink.Errors);
@ -468,7 +476,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(MissingAccessorTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -496,7 +505,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(NonPublicAccessorTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -522,14 +532,16 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
nameof(NotBoundAttributeTagHelper.BoundProperty),
typeof(object).FullName,
isIndexer: false,
isStringProperty: false)
isStringProperty: false,
usageDescriptor: null)
});
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(NotBoundAttributeTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -547,7 +559,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(DuplicateAttributeNameTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(descriptors);
@ -574,7 +587,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
nameof(MultiTagTagHelper.ValidAttribute),
typeof(string).FullName,
isIndexer: false,
isStringProperty: true)
isStringProperty: true,
usageDescriptor: null)
}),
new TagHelperDescriptor(
"p",
@ -587,7 +601,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
nameof(MultiTagTagHelper.ValidAttribute),
typeof(string).FullName,
isIndexer: false,
isStringProperty: true)
isStringProperty: true,
usageDescriptor: null)
})
};
@ -595,7 +610,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(MultiTagTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -626,7 +642,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(InheritedMultiTagTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -655,7 +672,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(DuplicateTagNameTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -683,7 +701,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
typeof(OverrideNameTagHelper),
errorSink);
designTime: false,
errorSink: errorSink);
// Assert
Assert.Empty(errorSink.Errors);
@ -867,7 +886,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var errorSink = new ErrorSink();
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(AssemblyName, type, errorSink);
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
type,
designTime: false,
errorSink: errorSink);
// Assert
var actualErrors = errorSink.Errors.ToArray();
@ -885,7 +908,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Assert.Equal(
expectedAttributeDescriptors,
actualDescriptor.Attributes,
CaseSensitiveTagHelperAttributeDescriptorComparer.Default);
TagHelperAttributeDescriptorComparer.Default);
}
// tagTelperType, expectedAttributeDescriptors, expectedErrorMessages
@ -911,13 +934,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: nameof(DefaultValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(IDictionary<string, string>).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "dictionary-property-",
propertyName: nameof(DefaultValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(string).FullName,
isIndexer: true,
isStringProperty: true),
isStringProperty: true,
usageDescriptor: null),
},
new string[0]
},
@ -930,13 +955,15 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: nameof(SingleValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(IDictionary<string, string>).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-prefix",
propertyName: nameof(SingleValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(string).FullName,
isIndexer: true,
isStringProperty: true),
isStringProperty: true,
usageDescriptor: null),
},
new string[0]
},
@ -949,67 +976,78 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(Dictionary<string, object>).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-name2",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty),
typeName: typeof(DictionarySubclass).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-name3",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty),
typeName: typeof(DictionaryWithoutParameterlessConstructor).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-name4",
propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty),
typeName: typeof(GenericDictionarySubclass<object>).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-name5",
propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty),
typeName: typeof(SortedDictionary<string, int>).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-name6",
propertyName: nameof(MultipleValidHtmlAttributePrefix.StringProperty),
typeName: typeof(string).FullName,
isIndexer: false,
isStringProperty: true),
isStringProperty: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-prefix1-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryProperty),
typeName: typeof(object).FullName,
isIndexer: true,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-prefix2-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty),
typeName: typeof(string).FullName,
isIndexer: true,
isStringProperty: true),
isStringProperty: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-prefix3-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty),
typeName: typeof(string).FullName,
isIndexer: true,
isStringProperty: true),
isStringProperty: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-prefix4-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty),
typeName: typeof(object).FullName,
isIndexer: true,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "valid-prefix5-",
propertyName: nameof(MultipleValidHtmlAttributePrefix.SortedDictionaryProperty),
typeName: typeof(int).FullName,
isIndexer: true,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
},
new string[0]
},
@ -1032,7 +1070,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
propertyName: nameof(MultipleInvalidHtmlAttributePrefix.LongProperty),
typeName: typeof(long).FullName,
isIndexer: false,
isStringProperty: false),
isStringProperty: false,
usageDescriptor: null),
},
new[]
{
@ -1065,7 +1104,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var errorSink = new ErrorSink();
// Act
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(AssemblyName, tagHelperType, errorSink);
var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
AssemblyName,
tagHelperType,
designTime: false,
errorSink: errorSink);
// Assert
var errors = errorSink.Errors.ToArray();
@ -1082,7 +1125,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Assert.Equal(
expectedAttributeDescriptors,
descriptor.Attributes,
CaseSensitiveTagHelperAttributeDescriptorComparer.Default);
TagHelperAttributeDescriptorComparer.Default);
}
public static TheoryData<string> ValidAttributeNameOrPrefixData
@ -1112,7 +1155,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
name,
propertyName: "ValidProperty",
typeName: "PropertyType",
isIndexer: false);
isIndexer: false,
usageDescriptor: null);
var errorSink = new ErrorSink();
// Act
@ -1135,7 +1179,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
name: prefix,
propertyName: "ValidProperty",
typeName: "PropertyType",
isIndexer: true);
isIndexer: true,
usageDescriptor: null);
var errorSink = new ErrorSink();
// Act
@ -1180,7 +1225,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
name,
propertyName: "InvalidProperty",
typeName: "PropertyType",
isIndexer: false);
isIndexer: false,
usageDescriptor: null);
var errorSink = new ErrorSink();
// Act
@ -1233,7 +1279,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
name: prefix,
propertyName: "InvalidProperty",
typeName: "ValuesType",
isIndexer: true);
isIndexer: true,
usageDescriptor: null);
var errorSink = new ErrorSink();
// Act

View File

@ -1368,7 +1368,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
typeName,
assemblyName,
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>());
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null);
}
private static TagHelperDescriptor CreatePrefixedValidPlainDescriptor(string prefix)
@ -1403,7 +1404,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private class TestTagHelperDescriptorResolver : TagHelperDescriptorResolver
{
public TestTagHelperDescriptorResolver(TagHelperTypeResolver typeResolver)
: base(typeResolver)
: base(typeResolver, designTime: false)
{
}
@ -1444,6 +1445,11 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private class AssemblyCheckingTagHelperDescriptorResolver : TagHelperDescriptorResolver
{
public AssemblyCheckingTagHelperDescriptorResolver()
: base(designTime: false)
{
}
public string CalledWithAssemblyName { get; set; }
protected override IEnumerable<TagHelperDescriptor> ResolveDescriptorsInAssembly(
@ -1462,6 +1468,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
private readonly Exception _error;
public ThrowingTagHelperDescriptorResolver(Exception error)
: base(designTime: false)
{
_error = error;
}

View File

@ -0,0 +1,41 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class TagHelperUsageDescriptorComparer : IEqualityComparer<TagHelperUsageDescriptor>
{
public static readonly TagHelperUsageDescriptorComparer Default = new TagHelperUsageDescriptorComparer();
private TagHelperUsageDescriptorComparer()
{
}
public bool Equals(TagHelperUsageDescriptor descriptorX, TagHelperUsageDescriptor descriptorY)
{
if (descriptorX == descriptorY)
{
return true;
}
return descriptorX != null &&
descriptorY != null &&
string.Equals(descriptorX.Summary, descriptorY.Summary, StringComparison.Ordinal) &&
string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal);
}
public int GetHashCode(TagHelperUsageDescriptor descriptor)
{
return HashCodeCombiner
.Start()
.Add(descriptor.Summary, StringComparer.Ordinal)
.Add(descriptor.Remarks, StringComparer.Ordinal)
.CombinedHash;
}
}
}

View File

@ -0,0 +1,385 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if !DNXCORE50
using System;
using System.IO;
using System.Reflection;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.AspNet.Testing;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class TagHelperUsageDescriptorFactoryTest
{
private const string TypeSummary = "The summary for <see cref=\"T:Microsoft.AspNet.Razor.Runtime." +
"TagHelpers.DocumentedTagHelper\" />.";
private const string TypeRemarks = "Inherits from <see cref=\"T:Microsoft.AspNet.Razor.Runtime." +
"TagHelpers.TagHelper\" />.";
private const string PropertySummary = "This <see cref=\"P:Microsoft.AspNet.Razor.Runtime." +
"TagHelpers.DocumentedTagHelper.SummaryProperty\" /> is of type <see cref=\"T:System.String\" />.";
private const string PropertyRemarks = "The <see cref=\"P:Microsoft.AspNet.Razor.Runtime." +
"TagHelpers.DocumentedTagHelper.SummaryProperty\" /> may be <c>null</c>.";
private const string PropertyWithSummaryAndRemarks_Summary = "This is a complex <see cref=\"T:System." +
"Collections.Generic.IDictionary`2\" />.";
private const string PropertyWithSummaryAndRemarks_Remarks = "<see cref=\"P:Microsoft.AspNet.Razor." +
"Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty\" /><see cref=\"P:Microsoft.AspNet.Razor.Runtime" +
".TagHelpers.DocumentedTagHelper.RemarksProperty\" />";
// These test assemblies don't really exist. They are used to look up corresponding XML for a fake assembly
// which is based on the DocumentedTagHelper type.
public static readonly string DocumentedAssemblyLocation =
Directory.GetCurrentDirectory() + "/TestFiles/NotLocalized/TagHelperDocumentation.dll";
public static readonly string LocalizedDocumentedAssemblyLocation =
Directory.GetCurrentDirectory() + "/TestFiles/Localized/TagHelperDocumentation.dll";
public static readonly string DocumentedAssemblyCodeBase =
"file:///" + DocumentedAssemblyLocation;
public static TheoryData CreateDescriptor_TypeDocumentationData
{
get
{
var defaultLocation = DocumentedAssemblyLocation;
var defaultCodeBase = DocumentedAssemblyCodeBase;
var nonExistentLocation = defaultLocation.Replace("TestFiles", "TestFile");
var nonExistentCodeBase = defaultCodeBase.Replace("TestFiles", "TestFile");
var invalidLocation = defaultLocation + '\0';
var invalidCodeBase = defaultCodeBase + '\0';
// tagHelperType, expectedUsageDescriptor
return new TheoryData<Type, TagHelperUsageDescriptor>
{
{ CreateDocumentationTagHelperType(location: null, codeBase: null), null },
{
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks)
},
{
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks)
},
{
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
new TagHelperUsageDescriptor(TypeSummary, TypeRemarks)
},
{ CreateType<SingleAttributeTagHelper>(defaultLocation, defaultCodeBase), null },
{ CreateDocumentationTagHelperType(nonExistentLocation, codeBase: null), null },
{ CreateDocumentationTagHelperType(location: null, codeBase: nonExistentCodeBase), null },
{ CreateType<SingleAttributeTagHelper>(invalidLocation, codeBase: null), null },
{ CreateDocumentationTagHelperType(location: null, codeBase: invalidCodeBase), null },
};
}
}
[Theory]
[MemberData(nameof(CreateDescriptor_TypeDocumentationData))]
public void CreateDescriptor_WithType_ReturnsExpectedDescriptors(
Type tagHelperType,
TagHelperUsageDescriptor expectedUsageDescriptor)
{
// Act
var usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(tagHelperType);
// Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
}
public static TheoryData CreateDescriptor_LocalizedTypeDocumentationData
{
get
{
// tagHelperType, expectedUsageDescriptor, culture
return new TheoryData<Type, TagHelperUsageDescriptor, string>
{
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "en-GB: " + TypeSummary,
remarks: "en-GB: " + TypeRemarks),
"en-GB"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "en: " + TypeSummary,
remarks: "en: " + TypeRemarks),
"en-US"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "fr-FR: " + TypeSummary,
remarks: "fr-FR: " + TypeRemarks),
"fr-FR"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "fr: " + TypeSummary,
remarks: "fr: " + TypeRemarks),
"fr-BE"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "nl-BE: " + TypeSummary,
remarks: "nl-BE: " + TypeRemarks),
"nl-BE"
}
};
}
}
[Theory]
[MemberData(nameof(CreateDescriptor_LocalizedTypeDocumentationData))]
public void CreateDescriptor_WithLocalizedType_ReturnsExpectedDescriptors(
Type tagHelperType,
TagHelperUsageDescriptor expectedUsageDescriptor,
string culture)
{
// Arrange
TagHelperUsageDescriptor usageDescriptor;
// Act
using (new CultureReplacer(culture))
{
usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(tagHelperType);
}
// Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
}
public static TheoryData CreateDescriptor_PropertyDocumentationData
{
get
{
var defaultLocation = DocumentedAssemblyLocation;
var defaultCodeBase = DocumentedAssemblyCodeBase;
var nonExistentLocation = defaultLocation.Replace("TestFiles", "TestFile");
var nonExistentCodeBase = defaultCodeBase.Replace("TestFiles", "TestFile");
var invalidLocation = defaultLocation + '\0';
var invalidCodeBase = defaultCodeBase + '\0';
// tagHelperType, propertyName, expectedUsageDescriptor
return new TheoryData<Type, string, TagHelperUsageDescriptor>
{
{
CreateDocumentationTagHelperType(location: null, codeBase: null),
nameof(DocumentedTagHelper.SummaryProperty),
null
},
{
CreateDocumentationTagHelperType(location: null, codeBase: null),
nameof(DocumentedTagHelper.RemarksProperty),
null
},
{
CreateDocumentationTagHelperType(location: null, codeBase: null),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
null
},
{
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
nameof(DocumentedTagHelper.UndocumentedProperty),
null
},
{
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
nameof(DocumentedTagHelper.SummaryProperty),
new TagHelperUsageDescriptor(PropertySummary, remarks: null)
},
{
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
nameof(DocumentedTagHelper.RemarksProperty),
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks)
},
{
CreateDocumentationTagHelperType(defaultLocation, codeBase: null),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
new TagHelperUsageDescriptor(
PropertyWithSummaryAndRemarks_Summary,
PropertyWithSummaryAndRemarks_Remarks)
},
{
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
nameof(DocumentedTagHelper.SummaryProperty),
new TagHelperUsageDescriptor(PropertySummary, remarks: null)
},
{
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
nameof(DocumentedTagHelper.RemarksProperty),
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks)
},
{
CreateDocumentationTagHelperType(location: null, codeBase: defaultCodeBase),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
new TagHelperUsageDescriptor(
PropertyWithSummaryAndRemarks_Summary,
PropertyWithSummaryAndRemarks_Remarks)
},
{
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
nameof(DocumentedTagHelper.SummaryProperty),
new TagHelperUsageDescriptor(PropertySummary, remarks: null)
},
{
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
nameof(DocumentedTagHelper.RemarksProperty),
new TagHelperUsageDescriptor(summary: null, remarks: PropertyRemarks)
},
{
CreateDocumentationTagHelperType(defaultLocation, defaultCodeBase),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
new TagHelperUsageDescriptor(
PropertyWithSummaryAndRemarks_Summary,
PropertyWithSummaryAndRemarks_Remarks)
},
{
CreateDocumentationTagHelperType(nonExistentLocation, codeBase: null),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
null
},
{
CreateDocumentationTagHelperType(location: null, codeBase: nonExistentCodeBase),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
null
},
{
CreateDocumentationTagHelperType(invalidLocation, codeBase: null),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
null
},
{
CreateDocumentationTagHelperType(location: null, codeBase: invalidCodeBase),
nameof(DocumentedTagHelper.RemarksAndSummaryProperty),
null
}
};
}
}
[Theory]
[MemberData(nameof(CreateDescriptor_PropertyDocumentationData))]
public void CreateDescriptor_WithProperty_ReturnsExpectedDescriptors(
Type tagHelperType,
string propertyName,
TagHelperUsageDescriptor expectedUsageDescriptor)
{
// Arrange
var mockPropertyInfo = new Mock<PropertyInfo>();
mockPropertyInfo.Setup(propertyInfo => propertyInfo.DeclaringType).Returns(tagHelperType);
mockPropertyInfo.Setup(propertyInfo => propertyInfo.Name).Returns(propertyName);
// Act
var usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(mockPropertyInfo.Object);
// Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
}
public static TheoryData CreateDescriptor_LocalizedPropertyData
{
get
{
// tagHelperType, expectedUsageDescriptor, culture
return new TheoryData<Type, TagHelperUsageDescriptor, string>
{
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "en-GB: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "en-GB: " + PropertyWithSummaryAndRemarks_Remarks),
"en-GB"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "en: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "en: " + PropertyWithSummaryAndRemarks_Remarks),
"en-US"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "fr-FR: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "fr-FR: " + PropertyWithSummaryAndRemarks_Remarks),
"fr-FR"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "fr: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "fr: " + PropertyWithSummaryAndRemarks_Remarks),
"fr-BE"
},
{
CreateDocumentationTagHelperType(LocalizedDocumentedAssemblyLocation, codeBase: null),
new TagHelperUsageDescriptor(
summary: "nl-BE: " + PropertyWithSummaryAndRemarks_Summary,
remarks: "nl-BE: " + PropertyWithSummaryAndRemarks_Remarks),
"nl-BE"
}
};
}
}
[Theory]
[MemberData(nameof(CreateDescriptor_LocalizedPropertyData))]
public void CreateDescriptor_WithLocalizedProperty_ReturnsExpectedDescriptors(
Type tagHelperType,
TagHelperUsageDescriptor expectedUsageDescriptor,
string culture)
{
// Arrange
var mockPropertyInfo = new Mock<PropertyInfo>();
mockPropertyInfo.Setup(propertyInfo => propertyInfo.DeclaringType).Returns(tagHelperType);
mockPropertyInfo
.Setup(propertyInfo => propertyInfo.Name)
.Returns(nameof(DocumentedTagHelper.RemarksAndSummaryProperty));
TagHelperUsageDescriptor usageDescriptor;
// Act
using (new CultureReplacer(culture))
{
usageDescriptor = TagHelperUsageDescriptorFactory.CreateDescriptor(mockPropertyInfo.Object);
}
// Assert
Assert.Equal(expectedUsageDescriptor, usageDescriptor, TagHelperUsageDescriptorComparer.Default);
}
private static Type CreateDocumentationTagHelperType(string location, string codeBase)
{
return CreateType<DocumentedTagHelper>(location, codeBase);
}
private static Type CreateType<TWrappedType>(string location, string codeBase)
{
var testAssembly = new TestAssembly(location, codeBase);
var wrappedType = typeof(TWrappedType);
var mockType = new Mock<Type>();
mockType.Setup(type => type.Assembly).Returns(testAssembly);
mockType.Setup(type => type.FullName).Returns(wrappedType.FullName);
mockType.Setup(type => type.DeclaringType).Returns(wrappedType.DeclaringType);
return mockType.Object;
}
private class TestAssembly : Assembly
{
public TestAssembly(string location, string codeBase)
{
Location = location;
CodeBase = codeBase;
}
public override string Location { get; }
public override string CodeBase { get; }
}
}
}
#endif

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Microsoft.AspNet.Razor.Runtime.Test</name>
</assembly>
<members>
<member name="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper">
<summary>
nl-BE: The summary for <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper" />.
</summary>
<remarks>
nl-BE: Inherits from <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper" />.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty">
<summary>
nl-BE: This <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> is of type <see cref="T:System.String" />.
</summary>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty">
<remarks>
nl-BE: The <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> may be <c>null</c>.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksAndSummaryProperty">
<summary>
nl-BE: This is a complex <see cref="T:System.Collections.Generic.IDictionary`2" />.
</summary>
<remarks>
nl-BE: <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /><see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty" />
</remarks>
</member>
</members>
</doc>

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Microsoft.AspNet.Razor.Runtime.Test</name>
</assembly>
<members>
<member name="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper">
<summary>
en-GB: The summary for <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper" />.
</summary>
<remarks>
en-GB: Inherits from <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper" />.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty">
<summary>
en-GB: This <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> is of type <see cref="T:System.String" />.
</summary>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty">
<remarks>
en-GB: The <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> may be <c>null</c>.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksAndSummaryProperty">
<summary>
en-GB: This is a complex <see cref="T:System.Collections.Generic.IDictionary`2" />.
</summary>
<remarks>
en-GB: <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /><see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty" />
</remarks>
</member>
</members>
</doc>

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Microsoft.AspNet.Razor.Runtime.Test</name>
</assembly>
<members>
<member name="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper">
<summary>
en: The summary for <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper" />.
</summary>
<remarks>
en: Inherits from <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper" />.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty">
<summary>
en: This <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> is of type <see cref="T:System.String" />.
</summary>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty">
<remarks>
en: The <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> may be <c>null</c>.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksAndSummaryProperty">
<summary>
en: This is a complex <see cref="T:System.Collections.Generic.IDictionary`2" />.
</summary>
<remarks>
en: <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /><see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty" />
</remarks>
</member>
</members>
</doc>

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Microsoft.AspNet.Razor.Runtime.Test</name>
</assembly>
<members>
<member name="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper">
<summary>
fr-FR: The summary for <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper" />.
</summary>
<remarks>
fr-FR: Inherits from <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper" />.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty">
<summary>
fr-FR: This <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> is of type <see cref="T:System.String" />.
</summary>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty">
<remarks>
fr-FR: The <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> may be <c>null</c>.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksAndSummaryProperty">
<summary>
fr-FR: This is a complex <see cref="T:System.Collections.Generic.IDictionary`2" />.
</summary>
<remarks>
fr-FR: <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /><see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty" />
</remarks>
</member>
</members>
</doc>

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Microsoft.AspNet.Razor.Runtime.Test</name>
</assembly>
<members>
<member name="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper">
<summary>
fr: The summary for <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper" />.
</summary>
<remarks>
fr: Inherits from <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper" />.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty">
<summary>
fr: This <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> is of type <see cref="T:System.String" />.
</summary>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty">
<remarks>
fr: The <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /> may be <c>null</c>.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksAndSummaryProperty">
<summary>
fr: This is a complex <see cref="T:System.Collections.Generic.IDictionary`2" />.
</summary>
<remarks>
fr: <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty" /><see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty" />
</remarks>
</member>
</members>
</doc>

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Microsoft.AspNet.Razor.Runtime.Test</name>
</assembly>
<members>
<member name="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper">
<summary>
The summary for <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper"/>.
</summary>
<remarks>
Inherits from <see cref="T:Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper"/>.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty">
<summary>
This <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty"/> is of type <see cref="T:System.String"/>.
</summary>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty">
<remarks>
The <see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty"/> may be <c>null</c>.
</remarks>
</member>
<member name="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksAndSummaryProperty">
<summary>
This is a complex <see cref="T:System.Collections.Generic.IDictionary`2"/>.
</summary>
<remarks>
<see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.SummaryProperty"/><see cref="P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper.RemarksProperty"/>
</remarks>
</member>
</members>
</doc>

View File

@ -0,0 +1,155 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if !DNXCORE50
using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Xunit;
namespace Microsoft.AspNet.Razor.Runtime
{
public class XmlDocumentationProviderTest
{
public static readonly string XmlTestFileLocation =
Directory.GetCurrentDirectory() + "/TestFiles/NotLocalized/TagHelperDocumentation.xml";
private static readonly TypeInfo DocumentedTagHelperTypeInfo = typeof(DocumentedTagHelper).GetTypeInfo();
private static readonly PropertyInfo DocumentedTagHelperSummaryPropertyInfo =
DocumentedTagHelperTypeInfo.GetProperty(nameof(DocumentedTagHelper.SummaryProperty));
private static readonly PropertyInfo DocumentedTagHelperRemarksPropertyInfo =
DocumentedTagHelperTypeInfo.GetProperty(nameof(DocumentedTagHelper.RemarksProperty));
private static readonly PropertyInfo DocumentedTagHelperRemarksSummaryPropertyInfo =
DocumentedTagHelperTypeInfo.GetProperty(nameof(DocumentedTagHelper.RemarksAndSummaryProperty));
[Fact]
public void CanReadXml()
{
// Act. Ensuring that reading the Xml file doesn't throw.
new XmlDocumentationProvider(XmlTestFileLocation);
}
public static TheoryData SummaryDocumentationData
{
get
{
var fullTypeName = DocumentedTagHelperTypeInfo.FullName;
// id, expectedSummary
return new TheoryData<string, string>
{
{
$"T:{fullTypeName}",
"The summary for <see cref=\"T:Microsoft.AspNet.Razor.Runtime.TagHelpers." +
"DocumentedTagHelper\" />."
},
{
$"P:{fullTypeName}.{DocumentedTagHelperSummaryPropertyInfo.Name}",
"This <see cref=\"P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper." +
"SummaryProperty\" /> is of type <see cref=\"T:System.String\" />."
},
{
$"P:{fullTypeName}.{DocumentedTagHelperRemarksPropertyInfo.Name}",
null
},
{
$"P:{fullTypeName}.{DocumentedTagHelperRemarksSummaryPropertyInfo.Name}",
"This is a complex <see cref=\"T:System.Collections.Generic.IDictionary`2\" />."
}
};
}
}
[Theory]
[MemberData(nameof(SummaryDocumentationData))]
public void GetSummary_ReturnsExpectedSummarys(string id, string expectedSummary)
{
// Arrange
var xmlDocumentationProvider = new XmlDocumentationProvider(XmlTestFileLocation);
// Act
var summary = xmlDocumentationProvider.GetSummary(id);
// Assert
Assert.Equal(expectedSummary, summary, StringComparer.Ordinal);
}
public static TheoryData RemarksDocumentationData
{
get
{
var fullTypeName = DocumentedTagHelperTypeInfo.FullName;
// id, expectedRemarks
return new TheoryData<string, string>
{
{
$"T:{fullTypeName}",
"Inherits from <see cref=\"T:Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper\" />."
},
{
$"P:{fullTypeName}.{DocumentedTagHelperSummaryPropertyInfo.Name}",
null
},
{
$"P:{fullTypeName}.{DocumentedTagHelperRemarksPropertyInfo.Name}",
"The <see cref=\"P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper." +
"SummaryProperty\" /> may be <c>null</c>."
},
{
$"P:{fullTypeName}.{DocumentedTagHelperRemarksSummaryPropertyInfo.Name}",
"<see cref=\"P:Microsoft.AspNet.Razor.Runtime.TagHelpers.DocumentedTagHelper." +
"SummaryProperty\" /><see cref=\"P:Microsoft.AspNet.Razor.Runtime.TagHelpers." +
"DocumentedTagHelper.RemarksProperty\" />"
}
};
}
}
[Theory]
[MemberData(nameof(RemarksDocumentationData))]
public void GetRemarks_ReturnsExpectedRemarks(string id, string expectedRemarks)
{
// Arrange
var xmlDocumentationProvider = new XmlDocumentationProvider(XmlTestFileLocation);
// Act
var remarks = xmlDocumentationProvider.GetRemarks(id);
// Assert
Assert.Equal(expectedRemarks, remarks, StringComparer.Ordinal);
}
[Fact]
public void GetId_UnderstandsTypeInfo()
{
// Arrange
var expectedId = "T:" + typeof(DocumentedTagHelper).FullName;
// Act
var id = XmlDocumentationProvider.GetId(DocumentedTagHelperTypeInfo);
// Assert
Assert.Equal(expectedId, id, StringComparer.Ordinal);
}
[Fact]
public void GetId_UnderstandsPropertyInfo()
{
// Arrange
var expectedId = string.Format(
CultureInfo.InvariantCulture,
"P:{0}.{1}",
typeof(DocumentedTagHelper).FullName,
nameof(DocumentedTagHelper.RemarksAndSummaryProperty));
// Act
var id = XmlDocumentationProvider.GetId(DocumentedTagHelperRemarksSummaryPropertyInfo);
// Assert
Assert.Equal(expectedId, id, StringComparer.Ordinal);
}
}
}
#endif

View File

@ -1,20 +1,24 @@
{
"version": "1.0.0",
"dependencies": {
"Microsoft.AspNet.Razor.Runtime": "4.0.0-*",
"Microsoft.AspNet.Testing": "1.0.0-*",
"xunit.runner.aspnet": "2.0.0-aspnet-*"
"version": "1.0.0",
"dependencies": {
"Microsoft.AspNet.Razor.Runtime": "4.0.0-*",
"Microsoft.AspNet.Testing": "1.0.0-*",
"xunit.runner.aspnet": "2.0.0-aspnet-*"
},
"commands": {
"test": "xunit.runner.aspnet"
},
"frameworks": {
"dnx451": {
"dependencies": {
"Moq": "4.2.1312.1622"
}
},
"commands": {
"test": "xunit.runner.aspnet"
},
"frameworks": {
"dnx451": { },
"dnxcore50": {
"dependencies": {
"System.Reflection.TypeExtensions": "4.0.0-beta-*",
"System.Runtime.Extensions": "4.0.10-beta-*"
}
}
"dnxcore50": {
"dependencies": {
"System.Reflection.TypeExtensions": "4.0.0-beta-*",
"System.Runtime.Extensions": "4.0.10-beta-*"
}
}
}
}

View File

@ -35,7 +35,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator
"catchall-bound-string",
"BoundRequiredString",
typeof(string).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
},
requiredAttributes: new[] { "catchall-unbound-required" }),
new TagHelperDescriptor(
@ -48,12 +49,14 @@ namespace Microsoft.AspNet.Razor.Test.Generator
"input-bound-required-string",
"BoundRequiredString",
typeof(string).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
"input-bound-string",
"BoundString",
typeof(string).FullName,
isIndexer: false)
isIndexer: false,
usageDescriptor: null)
},
requiredAttributes: new[] { "input-bound-required-string", "input-unbound-required" }),
};
@ -171,32 +174,38 @@ namespace Microsoft.AspNet.Razor.Test.Generator
name: "int-prefix-grabber",
propertyName: "IntProperty",
typeName: typeof(int).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "int-dictionary",
propertyName: "IntDictionaryProperty",
typeName: typeof(IDictionary<string, int>).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "string-dictionary",
propertyName: "StringDictionaryProperty",
typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>",
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "string-prefix-grabber",
propertyName: "StringProperty",
typeName: typeof(string).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "int-prefix-",
propertyName: "IntDictionaryProperty",
typeName: typeof(int).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "string-prefix-",
propertyName: "StringDictionaryProperty",
typeName: typeof(string).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
}),
new TagHelperDescriptor(
tagName: "input",
@ -208,22 +217,26 @@ namespace Microsoft.AspNet.Razor.Test.Generator
name: "int-dictionary",
propertyName: "IntDictionaryProperty",
typeName: typeof(IDictionary<string, int>).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "string-dictionary",
propertyName: "StringDictionaryProperty",
typeName: "Namespace.DictionaryWithoutParameterlessConstructor<string, string>",
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "int-prefix-",
propertyName: "IntDictionaryProperty",
typeName: typeof(int).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "string-prefix-",
propertyName: "StringDictionaryProperty",
typeName: typeof(string).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
}),
};
}
@ -1051,7 +1064,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
new TagHelperAttributeDescriptor("age", pAgePropertyInfo)
},
requiredAttributes: Enumerable.Empty<string>()),
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null),
new TagHelperDescriptor(
prefix,
tagName: "input",
@ -1061,7 +1075,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator
{
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
},
requiredAttributes: Enumerable.Empty<string>()),
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null),
new TagHelperDescriptor(
prefix,
tagName: "input",
@ -1072,7 +1087,8 @@ namespace Microsoft.AspNet.Razor.Test.Generator
new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
},
requiredAttributes: Enumerable.Empty<string>())
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null)
};
}

View File

@ -766,13 +766,24 @@ namespace Microsoft.AspNet.Razor.TagHelpers
new TagHelperDescriptor("person", "PersonTagHelper", "personAssembly",
attributes: new[]
{
new TagHelperAttributeDescriptor("age", "Age", typeof(int).FullName, isIndexer: false),
new TagHelperAttributeDescriptor(
"birthday",
"BirthDay",
typeof(DateTime).FullName,
isIndexer: false),
new TagHelperAttributeDescriptor("name", "Name", typeof(string).FullName, isIndexer: false),
name: "age",
propertyName: "Age",
typeName: typeof(int).FullName,
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "birthday",
propertyName: "BirthDay",
typeName: typeof(DateTime).FullName,
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "name",
propertyName: "Name",
typeName: typeof(string).FullName,
isIndexer: false,
usageDescriptor: null),
})
};
var providerContext = new TagHelperDescriptorProvider(descriptors);
@ -1772,12 +1783,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
name: "bound",
propertyName: "Bound",
typeName: typeof(bool).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "name",
propertyName: "Name",
typeName: typeof(string).FullName,
isIndexer: false)
isIndexer: false,
usageDescriptor: null)
})
};
var descriptorProvider = new TagHelperDescriptorProvider(descriptors);
@ -3266,7 +3279,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"bound-required-string",
"BoundRequiredString",
typeof(string).FullName,
isIndexer: false)
isIndexer: false,
usageDescriptor: null)
},
requiredAttributes: new[] { "unbound-required" }),
new TagHelperDescriptor(
@ -3279,7 +3293,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"bound-required-string",
"BoundRequiredString",
typeof(string).FullName,
isIndexer: false)
isIndexer: false,
usageDescriptor: null)
},
requiredAttributes: new[] { "bound-required-string" }),
new TagHelperDescriptor(
@ -3292,7 +3307,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"bound-required-int",
"BoundRequiredInt",
typeof(int).FullName,
isIndexer: false)
isIndexer: false,
usageDescriptor: null)
},
requiredAttributes: new[] { "bound-required-int" }),
new TagHelperDescriptor(
@ -3305,22 +3321,26 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"int-dictionary",
"DictionaryOfIntProperty",
typeof(IDictionary<string, int>).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
"string-dictionary",
"DictionaryOfStringProperty",
typeof(IDictionary<string, string>).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
"int-prefix-",
"DictionaryOfIntProperty",
typeof(int).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
"string-prefix-",
"DictionaryOfStringProperty",
typeof(string).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
},
requiredAttributes: Enumerable.Empty<string>()),
new TagHelperDescriptor(
@ -3333,12 +3353,14 @@ namespace Microsoft.AspNet.Razor.TagHelpers
"bound-string",
"BoundRequiredString",
typeof(string).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
"bound-int",
"BoundRequiredString",
typeof(int).FullName,
isIndexer: false)
isIndexer: false,
usageDescriptor: null)
},
requiredAttributes: Enumerable.Empty<string>()),
};

View File

@ -320,7 +320,8 @@ namespace Microsoft.AspNet.Razor.TagHelpers
typeName,
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>());
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null);
}
}
}

View File

@ -20,7 +20,9 @@ namespace Microsoft.AspNet.Razor.TagHelpers
typeName: "type name",
assemblyName: "assembly name",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: new[] { "required attribute one", "required attribute two" });
requiredAttributes: new[] { "required attribute one", "required attribute two" },
usageDescriptor: new TagHelperUsageDescriptor("usage summary", "usage remarks"));
var expectedSerializedDescriptor =
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
$"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
@ -29,7 +31,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," +
$"\"{ nameof(TagHelperDescriptor.Attributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":" +
"[\"required attribute one\",\"required attribute two\"]}";
"[\"required attribute one\",\"required attribute two\"]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":{{"+
$"\"{ nameof(TagHelperUsageDescriptor.Summary) }\":\"usage summary\"," +
$"\"{ nameof(TagHelperUsageDescriptor.Remarks) }\":\"usage remarks\"}}}}";
// Act
var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
@ -53,14 +58,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
name: "attribute one",
propertyName: "property name",
typeName: "property type name",
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "attribute two",
propertyName: "property name",
typeName: typeof(string).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
},
requiredAttributes: Enumerable.Empty<string>());
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null);
var expectedSerializedDescriptor =
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
$"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
@ -72,13 +80,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"}}," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]}}";
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
// Act
var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
@ -102,14 +113,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
name: "attribute one",
propertyName: "property name",
typeName: "property type name",
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "attribute two",
propertyName: "property name",
typeName: typeof(string).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
},
requiredAttributes: Enumerable.Empty<string>());
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null);
var expectedSerializedDescriptor =
$"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
$"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
@ -121,13 +135,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"}}," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]}}";
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
// Act
var serializedDescriptor = JsonConvert.SerializeObject(descriptor);
@ -148,14 +165,18 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{nameof(TagHelperDescriptor.AssemblyName)}\":\"assembly name\"," +
$"\"{nameof(TagHelperDescriptor.Attributes)}\":[]," +
$"\"{nameof(TagHelperDescriptor.RequiredAttributes)}\":" +
"[\"required attribute one\",\"required attribute two\"]}";
"[\"required attribute one\",\"required attribute two\"]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":{{" +
$"\"{ nameof(TagHelperUsageDescriptor.Summary) }\":\"usage summary\"," +
$"\"{ nameof(TagHelperUsageDescriptor.Remarks) }\":\"usage remarks\"}}}}";
var expectedDescriptor = new TagHelperDescriptor(
prefix: "prefix:",
tagName: "tag name",
typeName: "type name",
assemblyName: "assembly name",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: new[] { "required attribute one", "required attribute two" });
requiredAttributes: new[] { "required attribute one", "required attribute two" },
usageDescriptor: new TagHelperUsageDescriptor("usage summary", "usage remarks"));
// Act
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);
@ -169,6 +190,10 @@ namespace Microsoft.AspNet.Razor.TagHelpers
Assert.Equal(expectedDescriptor.AssemblyName, descriptor.AssemblyName, StringComparer.Ordinal);
Assert.Empty(descriptor.Attributes);
Assert.Equal(expectedDescriptor.RequiredAttributes, descriptor.RequiredAttributes, StringComparer.Ordinal);
Assert.Equal(
expectedDescriptor.UsageDescriptor,
descriptor.UsageDescriptor,
TagHelperUsageDescriptorComparer.Default);
}
[Fact]
@ -186,13 +211,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"}}," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]}}";
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
var expectedDescriptor = new TagHelperDescriptor(
prefix: "prefix:",
tagName: "tag name",
@ -204,14 +232,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
name: "attribute one",
propertyName: "property name",
typeName: "property type name",
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "attribute two",
propertyName: "property name",
typeName: typeof(string).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
},
requiredAttributes: Enumerable.Empty<string>());
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null);
// Act
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);
@ -267,13 +298,16 @@ namespace Microsoft.AspNet.Razor.TagHelpers
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"}}," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}," +
$"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
$"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]}}";
$"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
$"\"{ nameof(TagHelperAttributeDescriptor.UsageDescriptor) }\":null}}]," +
$"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
$"\"{ nameof(TagHelperDescriptor.UsageDescriptor) }\":null}}";
var expectedDescriptor = new TagHelperDescriptor(
prefix: "prefix:",
tagName: "tag name",
@ -285,14 +319,17 @@ namespace Microsoft.AspNet.Razor.TagHelpers
name: "attribute one",
propertyName: "property name",
typeName: "property type name",
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
new TagHelperAttributeDescriptor(
name: "attribute two",
propertyName: "property name",
typeName: typeof(string).FullName,
isIndexer: true),
isIndexer: true,
usageDescriptor: null),
},
requiredAttributes: Enumerable.Empty<string>());
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null);
// Act
var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);

View File

@ -910,7 +910,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
typeName: "mythTagHelper",
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>()),
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null),
new TagHelperDescriptor(
prefix: "th:",
tagName: "myth2",
@ -922,9 +923,11 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
name: "bound",
propertyName: "Bound",
typeName: typeof(bool).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
},
requiredAttributes: Enumerable.Empty<string>())
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null)
};
var availableDescriptorsText = new TagHelperDescriptor[]
{
@ -934,7 +937,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
typeName: "mythTagHelper",
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>()),
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null),
new TagHelperDescriptor(
prefix: "PREFIX",
tagName: "myth2",
@ -946,9 +950,11 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
name: "bound",
propertyName: "Bound",
typeName: typeof(bool).FullName,
isIndexer: false),
isIndexer: false,
usageDescriptor: null),
},
requiredAttributes: Enumerable.Empty<string>())
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null)
};
var availableDescriptorsCatchAll = new TagHelperDescriptor[]
{
@ -958,7 +964,8 @@ namespace Microsoft.AspNet.Razor.Test.TagHelpers
typeName: "mythTagHelper",
assemblyName: "SomeAssembly",
attributes: Enumerable.Empty<TagHelperAttributeDescriptor>(),
requiredAttributes: Enumerable.Empty<string>()),
requiredAttributes: Enumerable.Empty<string>(),
usageDescriptor: null),
};
// documentContent, expectedOutput, availableDescriptors

View File

@ -0,0 +1,40 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.Internal.Web.Utils;
namespace Microsoft.AspNet.Razor.TagHelpers
{
public class TagHelperUsageDescriptorComparer : IEqualityComparer<TagHelperUsageDescriptor>
{
public static readonly TagHelperUsageDescriptorComparer Default = new TagHelperUsageDescriptorComparer();
private TagHelperUsageDescriptorComparer()
{
}
public bool Equals(TagHelperUsageDescriptor descriptorX, TagHelperUsageDescriptor descriptorY)
{
if (descriptorX == descriptorY)
{
return true;
}
return descriptorX != null &&
descriptorY != null &&
string.Equals(descriptorX.Summary, descriptorY.Summary, StringComparison.Ordinal) &&
string.Equals(descriptorX.Remarks, descriptorY.Remarks, StringComparison.Ordinal);
}
public int GetHashCode(TagHelperUsageDescriptor descriptor)
{
return HashCodeCombiner
.Start()
.Add(descriptor.Summary, StringComparer.Ordinal)
.Add(descriptor.Remarks, StringComparer.Ordinal)
.CombinedHash;
}
}
}