Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit 268dde0

Browse files
author
NTaylorMullen
committed
Add tests to validate TagHelperDescriptorResolver.
- Tested the descriptor resolver and its underlying dependencies (TagHelperTypeResolver and TagHelperDescriptorFactory). #99 #158
1 parent ab88a63 commit 268dde0

File tree

8 files changed

+522
-2
lines changed

8 files changed

+522
-2
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
5+
{
6+
public class Valid_PlainTagHelper : ITagHelper
7+
{
8+
}
9+
10+
public class Valid_InheritedTagHelper : Valid_PlainTagHelper
11+
{
12+
}
13+
14+
public class SingleAttributeTagHelper : ITagHelper
15+
{
16+
public int IntAttribute { get; set; }
17+
}
18+
19+
public class MissingAccessorTagHelper : ITagHelper
20+
{
21+
public string ValidAttribute { get; set; }
22+
public string InvalidNoGetAttribute { set { } }
23+
public string InvalidNoSetAttribute { get { return string.Empty; } }
24+
}
25+
26+
public class PrivateAccessorTagHelper : ITagHelper
27+
{
28+
public string ValidAttribute { get; set; }
29+
public string InvalidPrivateSetAttribute { get; private set; }
30+
public string InvalidPrivateGetAttribute { private get; set; }
31+
}
32+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using Microsoft.AspNet.Razor.TagHelpers;
7+
using Microsoft.Internal.Web.Utils;
8+
9+
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
10+
{
11+
public class CompleteTagHelperDescriptorComparer : TagHelperDescriptorComparer
12+
{
13+
public new static readonly CompleteTagHelperDescriptorComparer Default =
14+
new CompleteTagHelperDescriptorComparer();
15+
16+
private CompleteTagHelperDescriptorComparer()
17+
{
18+
}
19+
20+
public new bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
21+
{
22+
return base.Equals(descriptorX, descriptorY) &&
23+
descriptorX.Attributes.SequenceEqual(descriptorY.Attributes,
24+
CompleteTagHelperAttributeDescriptorComparer.Default);
25+
}
26+
27+
public new int GetHashCode(TagHelperDescriptor descriptor)
28+
{
29+
return HashCodeCombiner.Start()
30+
.Add(base.GetHashCode())
31+
.Add(descriptor.Attributes)
32+
.CombinedHash;
33+
}
34+
35+
private class CompleteTagHelperAttributeDescriptorComparer : IEqualityComparer<TagHelperAttributeDescriptor>
36+
{
37+
public static readonly CompleteTagHelperAttributeDescriptorComparer Default =
38+
new CompleteTagHelperAttributeDescriptorComparer();
39+
40+
private CompleteTagHelperAttributeDescriptorComparer()
41+
{
42+
}
43+
44+
public bool Equals(TagHelperAttributeDescriptor descriptorX, TagHelperAttributeDescriptor descriptorY)
45+
{
46+
return descriptorX.AttributeName == descriptorY.AttributeName &&
47+
descriptorX.AttributePropertyName == descriptorY.AttributePropertyName;
48+
}
49+
50+
public int GetHashCode(TagHelperAttributeDescriptor descriptor)
51+
{
52+
return HashCodeCombiner.Start()
53+
.Add(descriptor.AttributeName)
54+
.Add(descriptor.AttributePropertyName)
55+
.CombinedHash;
56+
}
57+
}
58+
}
59+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNet.Razor.TagHelpers;
5+
using Xunit;
6+
7+
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
8+
{
9+
public class TagHelperDescriptorFactoryTest
10+
{
11+
[Fact]
12+
public void DescriptorFactory_BuildsDescriptorsFromSimpleTypes()
13+
{
14+
// Arrange
15+
var expectedDescriptor = new TagHelperDescriptor("Object", "System.Object", ContentBehavior.None);
16+
17+
// Act
18+
var descriptor = TagHelperDescriptorFactory.CreateDescriptor(typeof(object));
19+
20+
// Assert
21+
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
22+
}
23+
24+
[Fact]
25+
public void DescriptorFactory_BuildsDescriptorsWithConventionNames()
26+
{
27+
// Arrange
28+
var intProperty = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
29+
var expectedDescriptor = new TagHelperDescriptor(
30+
"SingleAttribute",
31+
typeof(SingleAttributeTagHelper).FullName,
32+
ContentBehavior.None,
33+
new[] {
34+
new TagHelperAttributeDescriptor(nameof(SingleAttributeTagHelper.IntAttribute), intProperty)
35+
});
36+
37+
// Act
38+
var descriptor = TagHelperDescriptorFactory.CreateDescriptor(typeof(SingleAttributeTagHelper));
39+
40+
// Assert
41+
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
42+
}
43+
44+
[Fact]
45+
public void DescriptorFactory_OnlyAcceptsPropertiesWithGetAndSet()
46+
{
47+
// Arrange
48+
var validProperty = typeof(MissingAccessorTagHelper).GetProperty(
49+
nameof(MissingAccessorTagHelper.ValidAttribute));
50+
var expectedDescriptor = new TagHelperDescriptor(
51+
"MissingAccessor",
52+
typeof(MissingAccessorTagHelper).FullName,
53+
ContentBehavior.None,
54+
new[] {
55+
new TagHelperAttributeDescriptor(nameof(MissingAccessorTagHelper.ValidAttribute), validProperty)
56+
});
57+
58+
// Act
59+
var descriptor = TagHelperDescriptorFactory.CreateDescriptor(typeof(MissingAccessorTagHelper));
60+
61+
// Assert
62+
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
63+
}
64+
65+
[Fact]
66+
public void DescriptorFactory_OnlyAcceptsPropertiesWithPublicGetAndSet()
67+
{
68+
// Arrange
69+
var validProperty = typeof(PrivateAccessorTagHelper).GetProperty(
70+
nameof(PrivateAccessorTagHelper.ValidAttribute));
71+
var expectedDescriptor = new TagHelperDescriptor(
72+
"PrivateAccessor",
73+
typeof(PrivateAccessorTagHelper).FullName,
74+
ContentBehavior.None,
75+
new[] {
76+
new TagHelperAttributeDescriptor(
77+
nameof(PrivateAccessorTagHelper.ValidAttribute), validProperty)
78+
});
79+
80+
// Act
81+
var descriptor = TagHelperDescriptorFactory.CreateDescriptor(typeof(PrivateAccessorTagHelper));
82+
83+
// Assert
84+
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
85+
}
86+
}
87+
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Reflection;
8+
using Microsoft.AspNet.Razor.TagHelpers;
9+
using Xunit;
10+
11+
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
12+
{
13+
public class TagHelperDescriptorResolverTest : TagHelperTypeResolverTest
14+
{
15+
[Fact]
16+
public void DescriptorResolver_DoesNotReturnInvalidTagHelpersWhenSpecified()
17+
{
18+
// Arrange
19+
var tagHelperDescriptorResolver =
20+
new TagHelperDescriptorResolver(
21+
new TestTagHelperTypeResolver(TestableTagHelpers));
22+
23+
// Act
24+
var descriptors = tagHelperDescriptorResolver.Resolve(
25+
"Microsoft.AspNet.Razor.Runtime.Test.TagHelpers.Invalid_AbstractTagHelper, MyAssembly");
26+
descriptors = descriptors.Concat(tagHelperDescriptorResolver.Resolve(
27+
"Microsoft.AspNet.Razor.Runtime.Test.TagHelpers.Invalid_GenericTagHelper`, MyAssembly"));
28+
descriptors = descriptors.Concat(tagHelperDescriptorResolver.Resolve(
29+
"Microsoft.AspNet.Razor.Runtime.Test.TagHelpers.Invalid_NestedPublicTagHelper, MyAssembly"));
30+
descriptors = descriptors.Concat(tagHelperDescriptorResolver.Resolve(
31+
"Microsoft.AspNet.Razor.Runtime.Test.TagHelpers.Invalid_NestedInternalTagHelper, MyAssembly"));
32+
descriptors = descriptors.Concat(tagHelperDescriptorResolver.Resolve(
33+
"Microsoft.AspNet.Razor.Runtime.Test.TagHelpers.Invalid_PrivateTagHelper, MyAssembly"));
34+
descriptors = descriptors.Concat(tagHelperDescriptorResolver.Resolve(
35+
"Microsoft.AspNet.Razor.Runtime.Test.TagHelpers.Invalid_ProtectedTagHelper, MyAssembly"));
36+
descriptors = descriptors.Concat(tagHelperDescriptorResolver.Resolve(
37+
"Microsoft.AspNet.Razor.Runtime.Test.TagHelpers.Invalid_InternalTagHelper, MyAssembly"));
38+
39+
// Assert
40+
Assert.Empty(descriptors);
41+
}
42+
43+
[Theory]
44+
[InlineData("Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper,MyAssembly")]
45+
[InlineData(" Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper,MyAssembly")]
46+
[InlineData("Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper ,MyAssembly")]
47+
[InlineData(" Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper ,MyAssembly")]
48+
[InlineData("Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper, MyAssembly")]
49+
[InlineData("Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper,MyAssembly ")]
50+
[InlineData("Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper, MyAssembly ")]
51+
[InlineData(" Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper, MyAssembly ")]
52+
[InlineData(" Microsoft.AspNet.Razor.Runtime.TagHelpers.Valid_PlainTagHelper , MyAssembly ")]
53+
public void DescriptorResolver_IgnoresSpaces(string lookupText)
54+
{
55+
// Arrange
56+
var tagHelperTypeResolver = new TestTagHelperTypeResolver(TestableTagHelpers)
57+
{
58+
OnGetLibraryDefinedTypes = (assemblyName) =>
59+
{
60+
Assert.Equal("MyAssembly", assemblyName.Name);
61+
}
62+
};
63+
var tagHelperDescriptorResolver = new TagHelperDescriptorResolver(tagHelperTypeResolver);
64+
var expectedDescriptor = new TagHelperDescriptor("Valid_Plain",
65+
typeof(Valid_PlainTagHelper).FullName,
66+
ContentBehavior.None);
67+
68+
// Act
69+
var descriptors = tagHelperDescriptorResolver.Resolve(lookupText);
70+
71+
// Assert
72+
var descriptor = Assert.Single(descriptors);
73+
Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
74+
}
75+
76+
[Fact]
77+
public void DescriptorResolver_ResolvesOnlyTypeResolverProvidedTypes()
78+
{
79+
// Arrange
80+
var resolver = new TagHelperDescriptorResolver(
81+
new LookupBasedTagHelperTypeResolver(
82+
new Dictionary<string, IEnumerable<Type>>(StringComparer.OrdinalIgnoreCase)
83+
{
84+
{ "lookupText1", ValidTestableTagHelpers },
85+
{ "lookupText2", new Type[]{ typeof(Valid_PlainTagHelper) } }
86+
}));
87+
var expectedDescriptor = new TagHelperDescriptor("Valid_Plain",
88+
typeof(Valid_PlainTagHelper).FullName,
89+
ContentBehavior.None);
90+
91+
// Act
92+
var descriptors = resolver.Resolve("lookupText2");
93+
94+
// Assert
95+
var descriptor = Assert.Single(descriptors);
96+
Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
97+
}
98+
99+
[Fact]
100+
public void DescriptorResolver_ResolvesMultipleTypes()
101+
{
102+
// Arrange
103+
var resolver = new TagHelperDescriptorResolver(
104+
new LookupBasedTagHelperTypeResolver(
105+
new Dictionary<string, IEnumerable<Type>>(StringComparer.OrdinalIgnoreCase)
106+
{
107+
{ "lookupText", new Type[]{ typeof(Valid_PlainTagHelper), typeof(Valid_InheritedTagHelper) } },
108+
}));
109+
var expectedDescriptors = new TagHelperDescriptor[]
110+
{
111+
new TagHelperDescriptor("Valid_Plain",
112+
typeof(Valid_PlainTagHelper).FullName,
113+
ContentBehavior.None),
114+
new TagHelperDescriptor("Valid_Inherited",
115+
typeof(Valid_InheritedTagHelper).FullName,
116+
ContentBehavior.None)
117+
};
118+
119+
// Act
120+
var descriptors = resolver.Resolve("lookupText").ToArray();
121+
122+
// Assert
123+
Assert.Equal(descriptors.Length, 2);
124+
Assert.Equal(descriptors, expectedDescriptors, CompleteTagHelperDescriptorComparer.Default);
125+
}
126+
127+
[Fact]
128+
public void DescriptorResolver_DoesNotResolveTypesForNoTypeResolvingLookupText()
129+
{
130+
// Arrange
131+
var resolver = new TagHelperDescriptorResolver(
132+
new LookupBasedTagHelperTypeResolver(
133+
new Dictionary<string, IEnumerable<Type>>(StringComparer.OrdinalIgnoreCase)
134+
{
135+
{ "lookupText1", ValidTestableTagHelpers },
136+
{ "lookupText2", new Type[]{ typeof(Valid_PlainTagHelper) } }
137+
}));
138+
139+
// Act
140+
var descriptors = resolver.Resolve("lookupText").ToArray();
141+
142+
// Assert
143+
Assert.Empty(descriptors);
144+
}
145+
146+
[Theory]
147+
[InlineData("")]
148+
[InlineData(null)]
149+
public void DescriptorResolver_ResolveThrowsIfNullOrEmptyLookupText(string lookupText)
150+
{
151+
// Arrange
152+
var tagHelperDescriptorResolver =
153+
new TagHelperDescriptorResolver(
154+
new TestTagHelperTypeResolver(InvalidTestableTagHelpers));
155+
156+
var expectedMessage =
157+
Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText) +
158+
Environment.NewLine +
159+
"Parameter name: lookupText";
160+
161+
// Act & Assert
162+
var ex = Assert.Throws<ArgumentException>(nameof(lookupText),
163+
() =>
164+
{
165+
tagHelperDescriptorResolver.Resolve(lookupText);
166+
});
167+
168+
Assert.Equal(expectedMessage, ex.Message);
169+
}
170+
171+
private class LookupBasedTagHelperTypeResolver : TagHelperTypeResolver
172+
{
173+
private Dictionary<string, IEnumerable<Type>> _lookupValues;
174+
175+
public LookupBasedTagHelperTypeResolver(Dictionary<string, IEnumerable<Type>> lookupValues)
176+
{
177+
_lookupValues = lookupValues;
178+
}
179+
180+
internal override IEnumerable<TypeInfo> GetLibraryDefinedTypes(AssemblyName assemblyName)
181+
{
182+
IEnumerable<Type> types;
183+
184+
_lookupValues.TryGetValue(assemblyName.Name, out types);
185+
186+
return types?.Select(type => type.GetTypeInfo()) ?? Enumerable.Empty<TypeInfo>();
187+
}
188+
}
189+
}
190+
}

0 commit comments

Comments
 (0)