Add tests for ReadOnlyTagHelperAttributes and TagHelperAttributes.

#279
This commit is contained in:
N. Taylor Mullen 2015-04-23 12:18:42 -07:00
parent 7c604d2b11
commit dcee0d2ff7
9 changed files with 1862 additions and 366 deletions

View File

@ -0,0 +1,39 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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.Runtime.TagHelpers
{
public class CaseSensitiveTagHelperAttributeComparer : IEqualityComparer<IReadOnlyTagHelperAttribute>
{
public readonly static CaseSensitiveTagHelperAttributeComparer Default =
new CaseSensitiveTagHelperAttributeComparer();
private CaseSensitiveTagHelperAttributeComparer()
{
}
public bool Equals(
[NotNull] IReadOnlyTagHelperAttribute attributeX,
[NotNull] IReadOnlyTagHelperAttribute attributeY)
{
return
attributeX == attributeY ||
// Normal comparer doesn't care about the Name case, in tests we do.
string.Equals(attributeX.Name, attributeY.Name, StringComparison.Ordinal) &&
Equals(attributeX.Value, attributeY.Value);
}
public int GetHashCode([NotNull] IReadOnlyTagHelperAttribute attribute)
{
return HashCodeCombiner
.Start()
.Add(attribute.Name, StringComparer.Ordinal)
.Add(attribute.Value)
.CombinedHash;
}
}
}

View File

@ -0,0 +1,702 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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 System.Linq;
using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class ReadOnlyTagHelperAttributeListTest
{
public static TheoryData IntIndexerData
{
get
{
var first = new TagHelperAttribute("First", "First Value");
var second = new TagHelperAttribute("Second", "Second Value");
var third = new TagHelperAttribute("Third", "Third Value");
return new TheoryData<
IEnumerable<IReadOnlyTagHelperAttribute>, // initialAttributes
int, // indexToLookup
IReadOnlyTagHelperAttribute> // expectedAttribute
{
{ new[] { first }, 0, first },
{ new[] { first, second }, 0, first },
{ new[] { first, second }, 1, second },
{ new[] { first, second, third}, 1, second },
{ new[] { first, second, third }, 2, third },
{ new[] { first, first, second, third}, 1, first },
};
}
}
[Theory]
[MemberData(nameof(IntIndexerData))]
public void IntIndexer_ReturnsExpectedAttribute(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
int indexToLookup,
IReadOnlyTagHelperAttribute expectedAttribute)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(initialAttributes);
// Act
var attribute = attributes[indexToLookup];
// Assert
Assert.Equal(expectedAttribute, attribute, CaseSensitiveTagHelperAttributeComparer.Default);
}
public static TheoryData IntIndexerThrowData
{
get
{
return new TheoryData<int> { 2, -1, 20 };
}
}
[Theory]
[MemberData(nameof(IntIndexerThrowData))]
public void IntIndexer_ThrowsIfInvalidIndex(int index)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
new[]
{
new TagHelperAttribute("a", "av"),
new TagHelperAttribute("b", "bv")
});
// Act & Assert
var exception = Assert.Throws<ArgumentOutOfRangeException>("index", () => attributes[index]);
}
public static TheoryData StringIndexerData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var B = new TagHelperAttribute("BName", "BName Value");
var C = new TagHelperAttribute("CName", "CName Value");
return new TheoryData<
IEnumerable<IReadOnlyTagHelperAttribute>, // initialAttributes
string, // nameToLookup
IReadOnlyTagHelperAttribute> // expectedAttribute
{
{ new[] { A }, "AName", A },
{ new[] { A }, "AnAmE", A },
{ new[] { A, B }, "AName", A },
{ new[] { A, B }, "AnAmE", A },
{ new[] { A, B }, "BName", B },
{ new[] { A, B }, "BnAmE", B },
{ new[] { A, B, C }, "BName", B },
{ new[] { A, B, C }, "bname", B },
{ new[] { A, B, C }, "CName", C },
{ new[] { A, B, C }, "cnamE", C },
// Multiple elements same name
{ new[] { A, B, A2, C }, "AName", A },
{ new[] { A, B, A2, C }, "aname", A },
{ new[] { B, A2, A }, "aname", A2 },
{ new[] { B, A2, A, C }, "AName", A2 },
{ new[] { A, A3 }, "AName", A },
{ new[] { A3, A }, "aname", A3 },
{ new[] { A, A2, A3 }, "AName", A },
{ new[] { C, B, A3, A }, "AName", A3 },
// Null expected lookups
{ new[] { A }, "_AName_", null },
{ new[] { A }, "completely different", null },
{ new[] { A, B }, "_AName_", null },
{ new[] { A, B }, "completely different", null },
{ new[] { A, B, C }, "_BName_", null },
{ new[] { A, B, C }, "completely different", null },
{ new[] { A, A2, B, C }, "_cnamE_", null },
{ new[] { A, A2, B, C }, "completely different", null },
{ new[] { A, A2, A3, B, C }, "_cnamE_", null },
{ new[] { A, A2, A3, B, C }, "completely different", null },
};
}
}
[Theory]
[MemberData(nameof(StringIndexerData))]
public void StringIndexer_ReturnsExpectedAttribute(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
string nameToLookup,
IReadOnlyTagHelperAttribute expectedAttribute)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(initialAttributes);
// Act
var attribute = attributes[nameToLookup];
// Assert
Assert.Equal(expectedAttribute, attribute, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
public void Count_ReturnsNumberOfAttributes()
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(
new[]
{
new TagHelperAttribute(),
new TagHelperAttribute(),
new TagHelperAttribute()
});
// Act
var count = attributes.Count;
// Assert
Assert.Equal(3, count);
}
public static TheoryData ContainsData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var B = new TagHelperAttribute("BName", "BName Value");
var C = new TagHelperAttribute("CName", "CName Value");
return new TheoryData<
IEnumerable<IReadOnlyTagHelperAttribute>, // initialAttributes
IReadOnlyTagHelperAttribute, // attributeToLookup
bool> // expected
{
{ new[] { A }, A, true },
{ new[] { A }, new TagHelperAttribute(A.Name, A.Value), true },
{ new[] { A }, new TagHelperAttribute("aname", A.Value), true },
{ new[] { A, B }, A, true },
{ new[] { A, B }, new TagHelperAttribute(A.Name, A.Value), true },
{ new[] { A, B }, new TagHelperAttribute("AnaMe", A.Value), true },
{ new[] { A, B }, B, true },
{ new[] { A, B }, new TagHelperAttribute(B.Name, B.Value), true },
{ new[] { A, B }, new TagHelperAttribute("BNAME", B.Value), true },
{ new[] { A, B, C }, B, true },
{ new[] { A, B, C }, new TagHelperAttribute(B.Name, B.Value), true },
{ new[] { A, B, C }, new TagHelperAttribute("bname", B.Value), true },
{ new[] { A, B, C }, C, true },
{ new[] { A, B, C }, new TagHelperAttribute(C.Name, C.Value), true },
{ new[] { A, B, C }, new TagHelperAttribute("CNAme", C.Value), true },
{ new[] { A }, B, false },
{ new[] { A }, new TagHelperAttribute(A.Name, "different value"), false },
{ new[] { A }, new TagHelperAttribute("aname_not", "different value"), false },
{ new[] { A, B }, A2, false },
{ new[] { A, B }, new TagHelperAttribute(A.Name, "different value"), false },
{ new[] { A, B }, new TagHelperAttribute("AnaMe_not", "different value"), false },
{ new[] { A, B }, new TagHelperAttribute(B.Name, "different value"), false },
{ new[] { A, B }, new TagHelperAttribute("BNAME_not", "different value"), false },
{ new[] { A, B, C }, A2, false },
{ new[] { A, B, C }, new TagHelperAttribute(B.Name, "different value"), false },
{ new[] { A, B, C }, new TagHelperAttribute("bname_not", "different value"), false },
{ new[] { A, B, C }, new TagHelperAttribute(C.Name, "different value"), false },
{ new[] { A, B, C }, new TagHelperAttribute("CNAme_not", "different value"), false },
// Multiple elements same name
{ new[] { A, B, A2, C }, A, true },
{ new[] { A, B, A2, C }, new TagHelperAttribute(A.Name, A.Value), true },
{ new[] { A, B, A2, C }, new TagHelperAttribute("aname", A.Value), true },
{ new[] { B, A2, A }, A2, true },
{ new[] { B, A2, A }, new TagHelperAttribute(A.Name, A.Value), true },
{ new[] { B, A2, A }, new TagHelperAttribute("AnAME", A2.Value), true },
{ new[] { B, A2, A, C }, A, true },
{ new[] { B, A2, A, C }, new TagHelperAttribute(A.Name, A.Value), true },
{ new[] { B, A2, A, C }, new TagHelperAttribute("ANAME", A.Value), true },
{ new[] { A, A3 }, A, true },
{ new[] { A, A3 }, new TagHelperAttribute(A.Name, A.Value), true },
{ new[] { A, A3 }, new TagHelperAttribute("ANamE", A.Value), true },
{ new[] { A3, A }, A3, true },
{ new[] { A3, A }, new TagHelperAttribute(A3.Name, A3.Value), true },
{ new[] { A3, A }, new TagHelperAttribute("anamE", A3.Value), true },
{ new[] { A, A2, A3 }, A, true },
{ new[] { A, A2, A3 }, new TagHelperAttribute(A.Name, A.Value), true },
{ new[] { A, A2, A3 }, new TagHelperAttribute("ANAme", A.Value), true },
{ new[] { C, B, A3, A }, A3, true },
{ new[] { C, B, A3, A }, new TagHelperAttribute(A3.Name, A3.Value), true },
{ new[] { C, B, A3, A }, new TagHelperAttribute("aname", A3.Value), true },
{ new[] { A, B, A2, C }, A3, false },
{ new[] { A, B, A2, C }, new TagHelperAttribute(A.Name, A3.Value), false },
{ new[] { A, B, A2, C }, new TagHelperAttribute("aname_not", "different value"), false },
{ new[] { B, A2, A }, A3, false },
{ new[] { B, A2, A }, new TagHelperAttribute(A.Name, A3.Value), false },
{ new[] { B, A2, A }, new TagHelperAttribute("AnAME_not", "different value"), false },
{ new[] { B, A2, A, C }, A3, false },
{ new[] { B, A2, A, C }, new TagHelperAttribute(A.Name, A3.Value), false },
{ new[] { B, A2, A, C }, new TagHelperAttribute("ANAME_not", "different value"), false },
{ new[] { A, A3 }, B, false },
{ new[] { A, A3 }, new TagHelperAttribute(A.Name, A2.Value), false },
{ new[] { A, A3 }, new TagHelperAttribute("ANamE_not", "different value"), false },
{ new[] { A3, A }, B, false },
{ new[] { A3, A }, new TagHelperAttribute(A3.Name, A2.Value), false },
{ new[] { A3, A }, new TagHelperAttribute("anamE_not", "different value"), false },
{ new[] { A, A2, A3 }, B, false },
{ new[] { A, A2, A3 }, new TagHelperAttribute(A.Name, B.Value), false },
{ new[] { A, A2, A3 }, new TagHelperAttribute("ANAme_not", "different value"), false },
{ new[] { C, B, A3, A }, A2, false },
{ new[] { C, B, A3, A }, new TagHelperAttribute(A3.Name, A2.Value), false },
{ new[] { C, B, A3, A }, new TagHelperAttribute("aname_not", "different value"), false },
};
}
}
[Theory]
[MemberData(nameof(ContainsData))]
public void Contains_ReturnsExpectedResult(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
IReadOnlyTagHelperAttribute attributeToLookup,
bool expected)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(initialAttributes);
// Act
var contains = attributes.Contains(attributeToLookup);
// Assert
Assert.Equal(expected, contains);
}
public static TheoryData ContainsNameData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var B = new TagHelperAttribute("BName", "BName Value");
var C = new TagHelperAttribute("CName", "CName Value");
return new TheoryData<
IEnumerable<IReadOnlyTagHelperAttribute>, // initialAttributes
string, // nameToLookup
bool> // expected
{
{ new[] { A }, A.Name, true },
{ new[] { A }, "aname", true },
{ new[] { A, B }, A.Name, true },
{ new[] { A, B }, "AnaMe", true },
{ new[] { A, B }, B.Name, true },
{ new[] { A, B }, "BNAME", true },
{ new[] { A, B, C }, B.Name, true },
{ new[] { A, B, C }, "bname", true },
{ new[] { A, B, C }, C.Name, true },
{ new[] { A, B, C }, "CNAme", true },
{ new[] { A }, B.Name, false },
{ new[] { A, B }, C.Name, false },
{ new[] { A, B, C }, "different", false },
// Multiple elements same name
{ new[] { A, B, A2, C }, A.Name, true },
{ new[] { A, B, A2, C }, "aname", true },
{ new[] { B, A2, A }, A2.Name, true },
{ new[] { B, A2, A }, "AnAME", true },
{ new[] { B, A2, A, C }, A.Name, true },
{ new[] { B, A2, A, C }, "ANAME", true },
{ new[] { A, A3 }, A.Name, true },
{ new[] { A, A3 }, "ANamE", true },
{ new[] { A, A2, A3 }, A.Name, true },
{ new[] { A, A2, A3 }, "ANAme", true },
{ new[] { C, B, A3, A }, A3.Name, true },
{ new[] { C, B, A3, A }, "aname", true },
{ new[] { A, B, A2, C }, "aname_not", false },
{ new[] { B, A2, A }, C.Name, false },
{ new[] { B, A2, A }, "AnAME_not", false },
{ new[] { B, A2, A, C }, "different", false },
{ new[] { B, A2, A, C }, "ANAME_not", false },
{ new[] { A, A3 }, B.Name, false },
{ new[] { A, A3 }, "ANamE_not", false },
{ new[] { A3, A }, B.Name, false },
{ new[] { A3, A }, "anamE_not", false },
{ new[] { A, A2, A3 }, B.Name, false },
{ new[] { A, A2, A3 }, "ANAme_not", false },
{ new[] { C, B, A3, A }, "different", false },
{ new[] { C, B, A3, A }, "aname_not", false },
};
}
}
[Theory]
[MemberData(nameof(ContainsNameData))]
public void ContainsName_ReturnsExpectedResult(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
string nameToLookup,
bool expected)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(initialAttributes);
// Act
var contains = attributes.ContainsName(nameToLookup);
// Assert
Assert.Equal(expected, contains);
}
public static TheoryData IndexOfData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var B = new TagHelperAttribute("BName", "BName Value");
var C = new TagHelperAttribute("CName", "CName Value");
return new TheoryData<
IEnumerable<IReadOnlyTagHelperAttribute>, // initialAttributes
IReadOnlyTagHelperAttribute, // attributeToLookup
int> // expected
{
{ new[] { A }, A, 0 },
{ new[] { A }, new TagHelperAttribute(A.Name, A.Value), 0 },
{ new[] { A }, new TagHelperAttribute("aname", A.Value), 0 },
{ new[] { A, B }, A, 0 },
{ new[] { A, B }, new TagHelperAttribute(A.Name, A.Value), 0 },
{ new[] { A, B }, new TagHelperAttribute("AnaMe", A.Value), 0 },
{ new[] { A, B }, B, 1 },
{ new[] { A, B }, new TagHelperAttribute(B.Name, B.Value), 1 },
{ new[] { A, B }, new TagHelperAttribute("BNAME", B.Value), 1 },
{ new[] { A, B, C }, B, 1 },
{ new[] { A, B, C }, new TagHelperAttribute(B.Name, B.Value), 1 },
{ new[] { A, B, C }, new TagHelperAttribute("bname", B.Value), 1 },
{ new[] { A, B, C }, C, 2 },
{ new[] { A, B, C }, new TagHelperAttribute(C.Name, C.Value), 2 },
{ new[] { A, B, C }, new TagHelperAttribute("CNAme", C.Value), 2 },
{ new[] { A }, B, -1 },
{ new[] { A }, new TagHelperAttribute(A.Name, "different value"), -1 },
{ new[] { A }, new TagHelperAttribute("aname_not", "different value"), -1 },
{ new[] { A, B }, A2, -1 },
{ new[] { A, B }, new TagHelperAttribute(A.Name, "different value"), -1 },
{ new[] { A, B }, new TagHelperAttribute("AnaMe_not", "different value"), -1 },
{ new[] { A, B }, new TagHelperAttribute(B.Name, "different value"), -1 },
{ new[] { A, B }, new TagHelperAttribute("BNAME_not", "different value"), -1 },
{ new[] { A, B, C }, A2, -1 },
{ new[] { A, B, C }, new TagHelperAttribute(B.Name, "different value"), -1 },
{ new[] { A, B, C }, new TagHelperAttribute("bname_not", "different value"), -1 },
{ new[] { A, B, C }, new TagHelperAttribute(C.Name, "different value"), -1 },
{ new[] { A, B, C }, new TagHelperAttribute("CNAme_not", "different value"), -1 },
// Multiple elements same name
{ new[] { A, B, A2, C }, A, 0 },
{ new[] { A, B, A2, C }, new TagHelperAttribute(A.Name, A.Value), 0 },
{ new[] { A, B, A2, C }, new TagHelperAttribute("aname", A.Value), 0 },
{ new[] { B, A2, A }, A2, 1 },
{ new[] { B, A2, A }, new TagHelperAttribute(A.Name, A.Value), 2 },
{ new[] { B, A2, A }, new TagHelperAttribute("AnAME", A2.Value), 1 },
{ new[] { B, A2, A, C }, A, 2 },
{ new[] { B, A2, A, C }, new TagHelperAttribute(A.Name, A.Value), 2 },
{ new[] { B, A2, A, C }, new TagHelperAttribute("ANAME", A.Value), 2 },
{ new[] { A, A3 }, A, 0 },
{ new[] { A, A3 }, new TagHelperAttribute(A.Name, A.Value), 0 },
{ new[] { A, A3 }, new TagHelperAttribute("ANamE", A.Value), 0 },
{ new[] { A3, A }, A3, 0 },
{ new[] { A3, A }, new TagHelperAttribute(A3.Name, A3.Value), 0 },
{ new[] { A3, A }, new TagHelperAttribute("anamE", A3.Value), 0 },
{ new[] { A, A2, A3 }, A, 0 },
{ new[] { A, A2, A3 }, new TagHelperAttribute(A.Name, A.Value), 0 },
{ new[] { A, A2, A3 }, new TagHelperAttribute("ANAme", A.Value), 0 },
{ new[] { C, B, A3, A }, A3, 2 },
{ new[] { C, B, A3, A }, new TagHelperAttribute(A3.Name, A3.Value), 2 },
{ new[] { C, B, A3, A }, new TagHelperAttribute("aname", A3.Value), 2 },
{ new[] { A, B, A2, C }, A3, -1 },
{ new[] { A, B, A2, C }, new TagHelperAttribute(A.Name, A3.Value), -1 },
{ new[] { A, B, A2, C }, new TagHelperAttribute("aname_not", "different value"), -1 },
{ new[] { B, A2, A }, A3, -1 },
{ new[] { B, A2, A }, new TagHelperAttribute(A.Name, A3.Value), -1 },
{ new[] { B, A2, A }, new TagHelperAttribute("AnAME_not", "different value"), -1 },
{ new[] { B, A2, A, C }, A3, -1 },
{ new[] { B, A2, A, C }, new TagHelperAttribute(A.Name, A3.Value), -1 },
{ new[] { B, A2, A, C }, new TagHelperAttribute("ANAME_not", "different value"), -1 },
{ new[] { A, A3 }, B, -1 },
{ new[] { A, A3 }, new TagHelperAttribute(A.Name, A2.Value), -1 },
{ new[] { A, A3 }, new TagHelperAttribute("ANamE_not", "different value"), -1 },
{ new[] { A3, A }, B, -1 },
{ new[] { A3, A }, new TagHelperAttribute(A3.Name, A2.Value), -1 },
{ new[] { A3, A }, new TagHelperAttribute("anamE_not", "different value"), -1 },
{ new[] { A, A2, A3 }, B, -1 },
{ new[] { A, A2, A3 }, new TagHelperAttribute(A.Name, B.Value), -1 },
{ new[] { A, A2, A3 }, new TagHelperAttribute("ANAme_not", "different value"), -1 },
{ new[] { C, B, A3, A }, A2, -1 },
{ new[] { C, B, A3, A }, new TagHelperAttribute(A3.Name, A2.Value), -1 },
{ new[] { C, B, A3, A }, new TagHelperAttribute("aname_not", "different value"), -1 },
};
}
}
[Theory]
[MemberData(nameof(IndexOfData))]
public void IndexOf_ReturnsExpectedResult(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
IReadOnlyTagHelperAttribute attributeToLookup,
int expected)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(initialAttributes);
// Act
var index = attributes.IndexOf(attributeToLookup);
// Assert
Assert.Equal(expected, index);
}
public static TheoryData TryGetAttributeData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var B = new TagHelperAttribute("BName", "BName Value");
var C = new TagHelperAttribute("CName", "CName Value");
return new TheoryData<
IEnumerable<IReadOnlyTagHelperAttribute>, // initialAttributes
string, // nameToLookup
IReadOnlyTagHelperAttribute, // expectedAttribute
bool> // expectedResult
{
{ new[] { A }, "AName", A, true },
{ new[] { A }, "AnAmE", A, true },
{ new[] { A, B }, "AName", A, true },
{ new[] { A, B }, "AnAmE", A, true },
{ new[] { A, B }, "BName", B, true },
{ new[] { A, B }, "BnAmE", B, true },
{ new[] { A, B, C }, "BName", B, true },
{ new[] { A, B, C }, "bname", B, true },
{ new[] { A, B, C }, "CName", C, true },
{ new[] { A, B, C }, "cnamE", C, true },
// Multiple elements same name
{ new[] { A, B, A2, C }, "AName", A, true },
{ new[] { A, B, A2, C }, "aname", A, true },
{ new[] { B, A2, A }, "aname", A2, true },
{ new[] { B, A2, A, C }, "AName", A2, true },
{ new[] { A, A3 }, "AName", A, true },
{ new[] { A3, A }, "aname", A3, true },
{ new[] { A, A2, A3 }, "AName", A, true },
{ new[] { C, B, A3, A }, "AName", A3, true },
// Null expected lookups
{ new[] { A }, "_AName_", null, false },
{ new[] { A }, "completely different", null, false },
{ new[] { A, B }, "_AName_", null, false },
{ new[] { A, B }, "completely different", null, false },
{ new[] { A, B, C }, "_BName_", null, false },
{ new[] { A, B, C }, "completely different", null, false },
{ new[] { A, A2, B, C }, "_cnamE_", null, false },
{ new[] { A, A2, B, C }, "completely different", null, false },
{ new[] { A, A2, A3, B, C }, "_cnamE_", null, false },
{ new[] { A, A2, A3, B, C }, "completely different", null, false },
};
}
}
[Theory]
[MemberData(nameof(TryGetAttributeData))]
public void TryGetAttribute_ReturnsExpectedValueAndAttribute(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
string nameToLookup,
IReadOnlyTagHelperAttribute expectedAttribute,
bool expectedResult)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(initialAttributes);
IReadOnlyTagHelperAttribute attribute;
// Act
var result = attributes.TryGetAttribute(nameToLookup, out attribute);
// Assert
Assert.Equal(expectedResult, result);
Assert.Equal(expectedAttribute, attribute, CaseSensitiveTagHelperAttributeComparer.Default);
}
public static TheoryData TryGetAttributesData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var B = new TagHelperAttribute("BName", "BName Value");
var C = new TagHelperAttribute("CName", "CName Value");
return new TheoryData<
IEnumerable<IReadOnlyTagHelperAttribute>, // initialAttributes
string, // nameToLookup
IEnumerable<IReadOnlyTagHelperAttribute>, // expectedAttributes
bool> // expectedResult
{
{ new[] { A }, "AName", new[] { A }, true },
{ new[] { A }, "AnAmE", new[] { A }, true },
{ new[] { A, B }, "AName", new[] { A }, true },
{ new[] { A, B }, "AnAmE", new[] { A }, true },
{ new[] { A, B }, "BName", new[] { B }, true },
{ new[] { A, B }, "BnAmE", new[] { B }, true },
{ new[] { A, B, C }, "BName", new[] { B }, true },
{ new[] { A, B, C }, "bname", new[] { B }, true },
{ new[] { A, B, C }, "CName", new[] { C }, true },
{ new[] { A, B, C }, "cnamE", new[] { C }, true },
// Multiple elements same name
{ new[] { A, B, A2, C }, "AName", new[] { A, A2 }, true },
{ new[] { A, B, A2, C }, "aname", new[] { A, A2 }, true },
{ new[] { B, A2, A }, "aname", new[] { A2, A }, true },
{ new[] { B, A2, A, C }, "AName", new[] { A2, A }, true },
{ new[] { A, A3 }, "AName", new[] { A, A3 }, true },
{ new[] { A3, A }, "aname", new[] { A3, A }, true },
{ new[] { A, A2, A3 }, "AName", new[] { A, A2, A3 }, true },
{ new[] { C, B, A3, A }, "AName", new[] { A3, A }, true },
// Null expected lookups
{ new[] { A }, "_AName_", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A }, "completely different", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, B }, "_AName_", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, B }, "completely different", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, B, C }, "_BName_", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, B, C }, "way different", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, A2, B, C }, "_cnamE_", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, A2, B, C }, "way different", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, A2, A3, B, C }, "_cnamE_", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
{ new[] { A, A2, A3, B, C }, "different", Enumerable.Empty<IReadOnlyTagHelperAttribute>(), false },
};
}
}
[Theory]
[MemberData(nameof(TryGetAttributesData))]
public void TryGetAttributes_ReturnsExpectedValueAndAttribute(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
string nameToLookup,
IEnumerable<IReadOnlyTagHelperAttribute> expectedAttributes,
bool expectedResult)
{
// Arrange
var attributes = new ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>(initialAttributes);
IEnumerable<IReadOnlyTagHelperAttribute> resolvedAttributes;
// Act
var result = attributes.TryGetAttributes(nameToLookup, out resolvedAttributes);
// Assert
Assert.Equal(expectedResult, result);
Assert.Equal(expectedAttributes, resolvedAttributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
public void Attributes_EqualsInitialAttributes()
{
// Arrange
var expectedAttributes = new[]
{
new TagHelperAttribute("A", "AV"),
new TagHelperAttribute("B", "BV")
};
// Act
var attributes = new TestableReadOnlyTagHelperAttributes(expectedAttributes);
// Assert
Assert.Equal(expectedAttributes, attributes.PublicAttributes);
}
[Fact]
public void GetEnumerator_ReturnsUnderlyingAttributesEnumerator()
{
// Arrange & Act
var attributes = new TestableReadOnlyTagHelperAttributes(new[]
{
new TagHelperAttribute("A", "AV"),
new TagHelperAttribute("B", "BV")
});
// Assert
Assert.Equal(attributes.GetEnumerator(), attributes.PublicAttributes.GetEnumerator());
}
[Fact]
public void ModifyingUnderlyingAttributes_AffectsExposedAttributes()
{
// Arrange
var attributes = new TestableReadOnlyTagHelperAttributes(Enumerable.Empty<IReadOnlyTagHelperAttribute>());
var expectedAttributes = new[]
{
new TagHelperAttribute("A", "AV"),
new TagHelperAttribute("B", "BV")
};
// Act
attributes.PublicAttributes.AddRange(expectedAttributes);
// Assert
Assert.Equal(attributes, expectedAttributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Theory]
[MemberData(nameof(IntIndexerData))]
public void ModifyingUnderlyingAttributes_IntIndexer_ReturnsExpectedResult(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
int indexToLookup,
IReadOnlyTagHelperAttribute expectedAttribute)
{
// Arrange
var attributes = new TestableReadOnlyTagHelperAttributes(Enumerable.Empty<IReadOnlyTagHelperAttribute>());
attributes.PublicAttributes.AddRange(initialAttributes);
// Act
var attribute = attributes[indexToLookup];
// Assert
Assert.Equal(expectedAttribute, attribute, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Theory]
[MemberData(nameof(StringIndexerData))]
public void ModifyingUnderlyingAttributes_StringIndexer_ReturnsExpectedResult(
IEnumerable<IReadOnlyTagHelperAttribute> initialAttributes,
string nameToLookup,
IReadOnlyTagHelperAttribute expectedAttribute)
{
// Arrange
var attributes = new TestableReadOnlyTagHelperAttributes(Enumerable.Empty<IReadOnlyTagHelperAttribute>());
attributes.PublicAttributes.AddRange(initialAttributes);
// Act
var attribute = attributes[nameToLookup];
// Assert
Assert.Equal(expectedAttribute, attribute, CaseSensitiveTagHelperAttributeComparer.Default);
}
private class TestableReadOnlyTagHelperAttributes : ReadOnlyTagHelperAttributeList<IReadOnlyTagHelperAttribute>
{
public TestableReadOnlyTagHelperAttributes(IEnumerable<IReadOnlyTagHelperAttribute> attributes)
: base(attributes)
{
}
public List<IReadOnlyTagHelperAttribute> PublicAttributes
{
get
{
return Attributes;
}
}
}
}
}

View File

@ -0,0 +1,698 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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 System.Linq;
using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public class TagHelperAttributeListTest
{
[Theory]
[MemberData(
nameof(ReadOnlyTagHelperAttributeListTest.IntIndexerData),
MemberType = typeof(ReadOnlyTagHelperAttributeListTest))]
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 static TheoryData IntIndexerSetData
{
get
{
var first = new TagHelperAttribute("First", "First Value");
var second = new TagHelperAttribute("Second", "Second Value");
var third = new TagHelperAttribute("Third", "Third Value");
var set = new TagHelperAttribute("Set", "Set Value");
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
int, // indexToSet
TagHelperAttribute, // setValue
IEnumerable<TagHelperAttribute>> // expectedAttributes
{
{ new[] { first }, 0, set, new[] { set } },
{ new[] { first, second }, 0, set, new[] { set, second } },
{ new[] { first, second }, 1, set, new[] { first, set } },
{ new[] { first, second, third}, 1, set, new[] { first, set, third } },
{ new[] { first, second, third }, 2, set, new[] { first, second, set } },
{ new[] { first, first, second, third}, 1, set, new[] { first, set, second, third } },
};
}
}
[Theory]
[MemberData(nameof(IntIndexerSetData))]
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);
}
[Theory]
[MemberData(
nameof(ReadOnlyTagHelperAttributeListTest.IntIndexerThrowData),
MemberType = typeof(ReadOnlyTagHelperAttributeListTest))]
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]);
}
[Theory]
[MemberData(
nameof(ReadOnlyTagHelperAttributeListTest.IntIndexerThrowData),
MemberType = typeof(ReadOnlyTagHelperAttributeListTest))]
public void IntIndexer_Setter_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] = new TagHelperAttribute("C", "CV");
});
}
[Theory]
[MemberData(
nameof(ReadOnlyTagHelperAttributeListTest.StringIndexerData),
MemberType = typeof(ReadOnlyTagHelperAttributeListTest))]
public void StringIndexer_GetsExpectedAttribute(
IEnumerable<TagHelperAttribute> initialAttributes,
string nameToLookup,
TagHelperAttribute expectedAttribute)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
// Act
var attribute = attributes[nameToLookup];
// Assert
Assert.Equal(expectedAttribute, attribute, CaseSensitiveTagHelperAttributeComparer.Default);
}
public static TheoryData StringIndexerSetData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var ASet = new TagHelperAttribute("aname", "AName Set Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A2Set = new TagHelperAttribute("aname", "AName Second Set Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var A3Set = new TagHelperAttribute("aname", "AName Third Set Value");
var B = new TagHelperAttribute("BName", "BName Value");
var BSet = new TagHelperAttribute("bname", "BName Set Value");
var C = new TagHelperAttribute("CName", "CName Value");
var CSet = new TagHelperAttribute("cname", "CName Set Value");
var set = new TagHelperAttribute("Set", "Set Value");
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
string, // keyToSet
TagHelperAttribute, // setValue
IEnumerable<TagHelperAttribute>> // expectedAttributes
{
{ new[] { A }, "AName", ASet, new[] { ASet } },
{ new[] { A }, "AnAmE", ASet, new[] { ASet } },
{ new[] { A }, "AnAmE", "AV", new[] { new TagHelperAttribute("AnAmE", "AV") } },
{ new[] { A, B }, "AName", ASet, new[] { ASet, B } },
{ new[] { A, B }, "AnAmE", ASet, new[] { ASet, B } },
{ new[] { A, B }, "AnAmE", "AV", new[] { new TagHelperAttribute("AnAmE", "AV"), B } },
{ new[] { A, B }, "BName", BSet, new[] { A, BSet } },
{ new[] { A, B }, "BnAmE", BSet, new[] { A, BSet } },
{ new[] { A, B }, "BnAmE", "BV", new[] { A, new TagHelperAttribute("BnAmE", "BV") } },
{ new[] { A, B, C }, "BName", BSet, new[] { A, BSet, C } },
{ new[] { A, B, C }, "bname", BSet, new[] { A, BSet, C } },
{ new[] { A, B, C }, "bname", "BV", new[] { A, new TagHelperAttribute("bname", "BV"), C } },
{ new[] { A, B, C }, "CName", CSet, new[] { A, B, CSet } },
{ new[] { A, B, C }, "cnamE", CSet, new[] { A, B, CSet } },
{ new[] { A, B, C }, "cnamE", "CV", new[] { A, B, new TagHelperAttribute("cnamE", "CV") } },
{ Enumerable.Empty<TagHelperAttribute>(), "Set", set, new[] { set } },
{ new[] { B }, "Set", set, new[] { B, set } },
{ new[] { B }, "Set", "Set Value", new[] { B, set } },
{ new[] { A, B }, "Set", set, new[] { A, B, set } },
{ new[] { A, B }, "Set", "Set Value", new[] { A, B, set } },
// Multiple elements same name
{ new[] { A, B, A2, C }, "AName", ASet, new[] { ASet, B, C } },
{ new[] { A, B, A2, C }, "aname", ASet, new[] { ASet, B, C } },
{ new[] { A, B, A2, C }, "aname", "av", new[] { new TagHelperAttribute("aname", "av"), B, C } },
{ new[] { B, A2, A }, "aname", A2Set, new[] { B, A2Set } },
{ new[] { B, A2, A }, "aname", "av", new[] { B, new TagHelperAttribute("aname", "av") } },
{ new[] { B, A2, A, C }, "AName", A2Set, new[] { B, A2Set, C } },
{ new[] { B, A2, A, C }, "AName", "av", new[] { B, new TagHelperAttribute("AName", "av"), C } },
{ new[] { A, A3 }, "AName", ASet, new[] { ASet } },
{ new[] { A, A3 }, "AName", "av", new[] { new TagHelperAttribute("AName", "av") } },
{ new[] { A3, A }, "aname", A3Set, new[] { A3Set } },
{ new[] { A3, A }, "aname", "av", new[] { new TagHelperAttribute("aname", "av") } },
{ new[] { A, A2, A3 }, "AName", ASet, new[] { ASet } },
{ new[] { A, A2, A3 }, "AName", "av", new[] { new TagHelperAttribute("AName", "av") } },
{ new[] { C, B, A3, A }, "AName", A3Set, new[] { C, B, A3Set } },
{ new[] { C, B, A3, A }, "AName", "av", new[] { C, B, new TagHelperAttribute("AName", "av") } },
{ new[] { A, A2, A3 }, "BNamE", BSet, new[] { A, A2, A3, BSet } },
{ new[] { A, A2, A3 }, "bname", "BName Set Value", new[] { A, A2, A3, BSet } },
{ new[] { A, A2, A3, B, C }, "Set", set, new[] { A, A2, A3, B, C, set } },
{ new[] { A, A2, A3, B, C }, "Set", "Set Value", new[] { A, A2, A3, B, C, set } },
};
}
}
[Theory]
[MemberData(nameof(StringIndexerSetData))]
public void StringIndexer_SetsAttributeAtExpectedLocation(
IEnumerable<TagHelperAttribute> initialAttributes,
string keyToSet,
TagHelperAttribute setValue,
IEnumerable<TagHelperAttribute> expectedAttributes)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
// Act
attributes[keyToSet] = setValue;
// Assert
Assert.Equal(expectedAttributes, attributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
public void StringIndexer_Setter_ThrowsIfIndexInvalid()
{
// Arrange
var attributes = new TagHelperAttributeList(new[]
{
new TagHelperAttribute("A", "AV"),
new TagHelperAttribute("B", "BV")
});
// Act & Assert
var exception = Assert.Throws<ArgumentOutOfRangeException>("index", () =>
{
attributes[2] = new TagHelperAttribute("C", "CV");
});
}
public static TheoryData StringIndexerSetterThrowData
{
get
{
// attributes
return new TheoryData<TagHelperAttributeList>
{
{ new TagHelperAttributeList() },
{ new TagHelperAttributeList { { "something", "a value" } } },
{ new TagHelperAttributeList { { "somethingelse", "a value" } } },
{ new TagHelperAttributeList { { "SomethingElse", "a value" } } },
{ new TagHelperAttributeList { { "something", "a value" }, { "somethingelse", "a value" } } },
{ new TagHelperAttributeList { { "SomethingElse", "a value" }, { "somethingelse", "a value" } } }
};
}
}
[Theory]
[MemberData(nameof(StringIndexerSetterThrowData))]
public void StringIndexer_Setter_ThrowsIfUnmatchingKey(
TagHelperAttributeList attributes)
{
// Arrange
var expectedMessage = $"Cannot add a {nameof(TagHelperAttribute)} with inconsistent names. The " +
$"{nameof(TagHelperAttribute.Name)} property 'somethingelse' must match the location 'something'." +
$"{Environment.NewLine}Parameter name: name";
// Act & Assert
var exception = Assert.Throws<ArgumentException>("name", () =>
{
attributes["something"] = new TagHelperAttribute("somethingelse", "value");
});
Assert.Equal(expectedMessage, exception.Message);
}
[Fact]
public void ICollection_IsReadOnly_ReturnsFalse()
{
// Arrange
var attributes = new TagHelperAttributeList() as ICollection<TagHelperAttribute>;
// Act
var isReadOnly = attributes.IsReadOnly;
// Assert
Assert.False(isReadOnly);
}
public static TheoryData AddData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var B = new TagHelperAttribute("BName", "BName Value");
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
TagHelperAttribute, // attributeToAdd
IEnumerable<TagHelperAttribute>> // expectedAttributes
{
{ Enumerable.Empty<TagHelperAttribute>(), A, new[] { A } },
{ new[] { A }, B, new[] { A, B } },
{ new[] { A }, A2, new[] { A, A2 } },
};
}
}
[Theory]
[MemberData(nameof(AddData))]
public void Add_AppendsAttributes(
IEnumerable<TagHelperAttribute> initialAttributes,
TagHelperAttribute attributeToAdd,
IEnumerable<TagHelperAttribute> expectedAttributes)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
// Act
attributes.Add(attributeToAdd);
// Assert
Assert.Equal(expectedAttributes, attributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
public void Add_ThrowsWhenNameAndValueAreNull()
{
// Arrange
var attributes = new TagHelperAttributeList();
var expectedMessage = $"Cannot add a '{typeof(TagHelperAttribute).FullName}' with a null " +
$"'{nameof(TagHelperAttribute.Name)}'.{Environment.NewLine}Parameter name: attribute";
// Act & Assert
var exception = Assert.Throws<ArgumentException>("attribute",
() => attributes.Add(new TagHelperAttribute()));
Assert.Equal(expectedMessage, exception.Message);
}
[Fact]
public void Add_ThrowsWhenNameIsNull()
{
// Arrange
var attributes = new TagHelperAttributeList();
var expectedMessage = $"Cannot add a '{typeof(TagHelperAttribute).FullName}' with a null " +
$"'{nameof(TagHelperAttribute.Name)}'.{Environment.NewLine}Parameter name: attribute";
// Act & Assert
var exception = Assert.Throws<ArgumentException>("attribute",
() => attributes.Add(new TagHelperAttribute
{
Value = "Anything"
}));
Assert.Equal(expectedMessage, exception.Message);
}
public static TheoryData InsertData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var B = new TagHelperAttribute("BName", "BName Value");
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
TagHelperAttribute, // attributeToAdd
int, // locationToInsert
IEnumerable<TagHelperAttribute>> // expectedAttributes
{
{ Enumerable.Empty<TagHelperAttribute>(), A, 0, new[] { A } },
{ new[] { A }, B, 1, new[] { A, B } },
{ new[] { A }, B, 0, new[] { B, A } },
{ new[] { A }, A2, 1, new[] { A, A2 } },
{ new[] { A }, A2, 0, new[] { A2, A } },
{ new[] { A, B }, A2, 0, new[] { A2, A, B } },
{ new[] { A, B }, A2, 1, new[] { A, A2, B } },
{ new[] { A, B }, A2, 2, new[] { A, B, A2 } },
};
}
}
[Theory]
[MemberData(nameof(InsertData))]
public void Insert_InsertsAttributes(
IEnumerable<TagHelperAttribute> initialAttributes,
TagHelperAttribute attributeToAdd,
int locationToInsert,
IEnumerable<TagHelperAttribute> expectedAttributes)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
// Act
attributes.Insert(locationToInsert, attributeToAdd);
// Assert
Assert.Equal(expectedAttributes, attributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
public void Insert_ThrowsWhenNameIsNull()
{
// Arrange
var attributes = new TagHelperAttributeList();
var expectedMessage = $"Cannot add a '{typeof(TagHelperAttribute).FullName}' with a null " +
$"'{nameof(TagHelperAttribute.Name)}'.{Environment.NewLine}Parameter name: attribute";
// Act & Assert
var exception = Assert.Throws<ArgumentException>("attribute",
() => attributes.Insert(0, new TagHelperAttribute
{
Value = "Anything"
}));
Assert.Equal(expectedMessage, exception.Message);
}
[Fact]
public void Insert_ThrowsWhenIndexIsOutOfRange()
{
// Arrange
var attributes = new TagHelperAttributeList(
new[]
{
new TagHelperAttribute("a", "av"),
new TagHelperAttribute("b", "bv"),
});
// Act & Assert
var exception = Assert.Throws<ArgumentOutOfRangeException>("index",
() => attributes.Insert(3, new TagHelperAttribute("c", "cb")));
}
public static TheoryData CopyToData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var B = new TagHelperAttribute("BName", "BName Value");
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
TagHelperAttribute[], // attributesToCopy
int, // locationToCopy
IEnumerable<TagHelperAttribute>> // expectedAttributes
{
{ Enumerable.Empty<TagHelperAttribute>(), new[] { A }, 0, new[] { A } },
{ Enumerable.Empty<TagHelperAttribute>(), new[] { A, B }, 0, new[] { A, B } },
{ new[] { A }, new[] { B }, 1, new[] { A, B } },
{ new[] { A }, new[] { B }, 0, new[] { B } },
{ new[] { A }, new[] { A2 }, 1, new[] { A, A2 } },
{ new[] { A }, new[] { A2 }, 0, new[] { A2 } },
{ new[] { A, B }, new[] { A2 }, 0, new[] { A2, B } },
{ new[] { A, B }, new[] { A2 }, 1, new[] { A, A2 } },
{ new[] { A, B }, new[] { A2 }, 2, new[] { A, B, A2 } },
{ new[] { A, B }, new[] { A2, A2 }, 0, new[] { A2, A2 } },
{ new[] { A, B, A2 }, new[] { A2, A2 }, 1, new[] { A, A2, A2 } },
{ new[] { A, B }, new[] { A2, A2 }, 2, new[] { A, B, A2, A2 } },
};
}
}
[Theory]
[MemberData(nameof(CopyToData))]
public void CopyTo_CopiesAttributes(
IEnumerable<TagHelperAttribute> initialAttributes,
TagHelperAttribute[] attributesToCopy,
int locationToCopy,
IEnumerable<TagHelperAttribute> expectedAttributes)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
var attributeDestination = new TagHelperAttribute[expectedAttributes.Count()];
attributes.ToArray().CopyTo(attributeDestination, 0);
// Act
attributesToCopy.CopyTo(attributeDestination, locationToCopy);
// Assert
Assert.Equal(expectedAttributes, attributeDestination, CaseSensitiveTagHelperAttributeComparer.Default);
}
public static TheoryData RemoveAllData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var A3 = new TagHelperAttribute("AName", "AName Third Value");
var B = new TagHelperAttribute("BName", "BName Value");
var C = new TagHelperAttribute("CName", "CName Value");
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
string, // keyToRemove
IEnumerable<TagHelperAttribute>, // expectedAttributes
bool> // expectedRemoval
{
{ new[] { A }, "AName", Enumerable.Empty<TagHelperAttribute>(), true },
{ new[] { A }, "AnAmE", Enumerable.Empty<TagHelperAttribute>(), true },
{ new[] { A, B }, "AName", new[] { B }, true },
{ new[] { A, B }, "AnAmE", new[] { B }, true },
{ new[] { A, B }, "BName", new[] { A }, true },
{ new[] { A, B }, "BnAmE", new[] { A }, true },
{ new[] { A, B, C }, "BName", new[] { A, C }, true },
{ new[] { A, B, C }, "bname", new[] { A, C }, true },
{ new[] { A, B, C }, "CName", new[] { A, B }, true },
{ new[] { A, B, C }, "cnamE", new[] { A, B }, true },
// Multiple elements same name
{ new[] { A, B, A2, C }, "AName", new[] { B, C }, true },
{ new[] { A, B, A2, C }, "aname", new[] { B, C }, true },
{ new[] { B, A2, A }, "aname", new[] { B }, true },
{ new[] { B, A2, A, C }, "AName", new[] { B, C }, true },
{ new[] { A, A3 }, "AName", Enumerable.Empty<TagHelperAttribute>(), true },
{ new[] { A3, A }, "aname", Enumerable.Empty<TagHelperAttribute>(), true },
{ new[] { A, A2, A3 }, "AName", Enumerable.Empty<TagHelperAttribute>(), true },
{ new[] { C, B, A3, A }, "AName", new[] { C, B }, true },
// No removal expected lookups
{ Enumerable.Empty<TagHelperAttribute>(), "_0_", Enumerable.Empty<TagHelperAttribute>(), false },
{ new[] { A }, "_AName_", new[] { A }, false },
{ new[] { A }, "completely different", new[] { A }, false },
{ new[] { A, B }, "_AName_", new[] { A, B }, false },
{ new[] { A, B }, "completely different", new[] { A, B }, false },
{ new[] { A, B, C }, "_BName_", new[] { A, B, C }, false },
{ new[] { A, B, C }, "completely different", new[] { A, B, C }, false },
{ new[] { A, A2, B, C }, "_cnamE_", new[] { A, A2, B, C }, false },
{ new[] { A, A2, B, C }, "completely different", new[] { A, A2, B, C }, false },
{ new[] { A, A2, A3, B, C }, "_cnamE_", new[] { A, A2, A3, B, C }, false },
{ new[] { A, A2, A3, B, C }, "completely different", new[] { A, A2, A3, B, C }, false },
};
}
}
[Theory]
[MemberData(nameof(RemoveAllData))]
public void RemoveAll_RemovesAllExpectedAttributes(
IEnumerable<TagHelperAttribute> initialAttributes,
string keyToRemove,
IEnumerable<TagHelperAttribute> expectedAttributes,
bool expectedRemoval)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
// Act
var removed = attributes.RemoveAll(keyToRemove);
// Assert
Assert.Equal(expectedRemoval, removed);
Assert.Equal(expectedAttributes, attributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
public static TheoryData RemoveData
{
get
{
var A = new TagHelperAttribute("AName", "av");
var A2 = new TagHelperAttribute("aname", "av");
var A3 = new TagHelperAttribute("AName", "av");
var B = new TagHelperAttribute("BName", "bv");
var C = new TagHelperAttribute("CName", "cv");
var empty = Enumerable.Empty<TagHelperAttribute>();
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
TagHelperAttribute, // attributeToRemove
IEnumerable<TagHelperAttribute>, // expectedAttributes
bool> // expectedResult
{
{ new[] { A }, A, empty, true },
{ new[] { A }, new TagHelperAttribute("AnAmE", "av"), empty, true },
{ new[] { A, B }, A, new[] { B }, true },
{ new[] { A, B }, new TagHelperAttribute("AnAmE", "av"), new[] { B }, true },
{ new[] { A, B }, B, new[] { A }, true },
{ new[] { A, B }, new TagHelperAttribute("BnAmE", "bv"), new[] { A }, true },
{ new[] { A, B, C }, B, new[] { A, C }, true },
{ new[] { A, B, C }, new TagHelperAttribute("bname", "bv"), new[] { A, C }, true },
{ new[] { A, B, C }, C, new[] { A, B }, true },
{ new[] { A, B, C }, new TagHelperAttribute("cnamE", "cv"), new[] { A, B }, true },
// Multiple elements same name
{ new[] { A, B, A2, C }, A, new[] { B, A2, C }, true },
{ new[] { A, B, A2, C }, new TagHelperAttribute("aname", "av"), new[] { B, A2, C }, true },
{ new[] { B, A2, A }, new TagHelperAttribute("aname", "av"), new[] { B, A }, true },
{ new[] { B, A2, A, C }, A, new[] { B, A, C }, true },
{ new[] { A, A3 }, A3, new[] { A3 }, true },
{ new[] { A3, A }, new TagHelperAttribute("aname", "av"), new[] { A }, true },
{ new[] { A, A2, A3 }, new TagHelperAttribute("AName", "av"), new[] { A2, A3 }, true },
{ new[] { C, B, A3, A }, new TagHelperAttribute("AName", "av"), new[] { C, B, A }, true },
// Null expected lookups
{ Enumerable.Empty<TagHelperAttribute>(), "_0_", Enumerable.Empty<TagHelperAttribute>(), false },
{ new[] { A }, "_AName_", new[] { A }, false },
{ new[] { A }, "completely different", new[] { A }, false },
{ new[] { A, B }, "_AName_", new[] { A, B }, false },
{ new[] { A, B }, "completely different", new[] { A, B }, false },
{ new[] { A, B, C }, "_BName_", new[] { A, B, C }, false },
{ new[] { A, B, C }, "completely different", new[] { A, B, C }, false },
{ new[] { A, A2, B, C }, "_cnamE_", new[] { A, A2, B, C }, false },
{ new[] { A, A2, B, C }, "completely different", new[] { A, A2, B, C }, false },
{ new[] { A, A2, A3, B, C }, "_cnamE_", new[] { A, A2, A3, B, C }, false },
{ new[] { A, A2, A3, B, C }, "completely different", new[] { A, A2, A3, B, C }, false },
};
}
}
[Theory]
[MemberData(nameof(RemoveData))]
public void Remove_ReturnsExpectedValueAndRemovesFirstAttribute(
IEnumerable<TagHelperAttribute> initialAttributes,
TagHelperAttribute attributeToRemove,
IEnumerable<TagHelperAttribute> expectedAttributes,
bool expectedResult)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
// Act
var result = attributes.Remove(attributeToRemove);
// Assert
Assert.Equal(expectedResult, result);
Assert.Equal(expectedAttributes, attributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
public static TheoryData RemoveAtData
{
get
{
var A = new TagHelperAttribute("AName", "AName Value");
var A2 = new TagHelperAttribute("aname", "AName Second Value");
var B = new TagHelperAttribute("BName", "BName Value");
return new TheoryData<
IEnumerable<TagHelperAttribute>, // initialAttributes
int, // locationToRemove
IEnumerable<TagHelperAttribute>> // expectedAttributes
{
{ new[] { A }, 0, Enumerable.Empty<TagHelperAttribute>() },
{ new[] { A, B }, 0, new[] { B } },
{ new[] { A, B }, 1, new[] { A } },
{ new[] { A, A2 }, 0, new[] { A2 } },
{ new[] { A, A2 }, 1, new[] { A } },
{ new[] { A, B, A2 }, 0, new[] { B, A2 } },
{ new[] { A, B, A2 }, 1, new[] { A, A2 } },
{ new[] { A, B, A2 }, 2, new[] { A, B } },
};
}
}
[Theory]
[MemberData(nameof(RemoveAtData))]
public void RemoveAt_RemovesAttributeAtSpecifiedIndex(
IEnumerable<TagHelperAttribute> initialAttributes,
int locationToRemove,
IEnumerable<TagHelperAttribute> expectedAttributes)
{
// Arrange
var attributes = new TagHelperAttributeList(initialAttributes);
// Act
attributes.RemoveAt(locationToRemove);
// Assert
Assert.Equal(expectedAttributes, attributes, CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
public void RemoveAt_ThrowsWhenIndexIsOutOfRange()
{
// Arrange
var attributes = new TagHelperAttributeList(
new[]
{
new TagHelperAttribute("a", "av"),
new TagHelperAttribute("b", "bv"),
});
// Act & Assert
var exception = Assert.Throws<ArgumentOutOfRangeException>("index",
() => attributes.RemoveAt(3));
}
[Fact]
public void Clear_RemovesAllAttributes()
{
// Arrange
var attributes = new TagHelperAttributeList(
new[]
{
new TagHelperAttribute("a", "av"),
new TagHelperAttribute("b", "bv"),
});
// Act
attributes.Clear();
// Assert
Assert.Empty(attributes);
}
}
}

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
@ -21,7 +22,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Act
var context = new TagHelperContext(
allAttributes: new Dictionary<string, object>(),
allAttributes: Enumerable.Empty<IReadOnlyTagHelperAttribute>(),
items: expectedItems,
uniqueId: string.Empty,
getChildContentAsync: () => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));

View File

@ -148,6 +148,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
}
[Theory]
[MemberData(nameof(DictionaryCaseTestingData))]
public void HtmlAttributes_IgnoresCase(string originalName, string updatedName)
{
@ -160,22 +161,23 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Assert
var attribute = Assert.Single(executionContext.HTMLAttributes);
Assert.Equal(new KeyValuePair<string, object>(originalName, "something else"), attribute);
Assert.Equal(new TagHelperAttribute(originalName, "something else"), attribute);
}
[Theory]
[MemberData(nameof(DictionaryCaseTestingData))]
public void AllAttributes_IgnoresCase(string originalName, string updatedName)
{
// Arrange
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
executionContext.AllAttributes[originalName] = false;
executionContext.AllAttributes.Add(originalName, value: false);
// Act
executionContext.AllAttributes[updatedName] = true;
executionContext.AllAttributes[updatedName].Value = true;
// Assert
var attribute = Assert.Single(executionContext.AllAttributes);
Assert.Equal(new KeyValuePair<string, object>(originalName, true), attribute);
Assert.Equal(new TagHelperAttribute(originalName, true), attribute);
}
[Fact]
@ -183,7 +185,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "btn" },
{ "foo", "bar" }
@ -194,7 +196,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
executionContext.AddHtmlAttribute("foo", "bar");
// Assert
Assert.Equal(expectedAttributes, executionContext.HTMLAttributes);
Assert.Equal(
expectedAttributes,
executionContext.HTMLAttributes,
CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]
@ -202,7 +207,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var executionContext = new TagHelperExecutionContext("p", selfClosing: false);
var expectedAttributes = new Dictionary<string, object>
var expectedAttributes = new TagHelperAttributeList
{
{ "class", "btn" },
{ "something", true },
@ -215,7 +220,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
executionContext.AddHtmlAttribute("foo", "bar");
// Assert
Assert.Equal(expectedAttributes, executionContext.AllAttributes);
Assert.Equal(
expectedAttributes,
executionContext.AllAttributes,
CaseSensitiveTagHelperAttributeComparer.Default);
}
[Fact]

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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;
using Xunit;
namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
@ -142,7 +141,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var tagHelperOutput = new TagHelperOutput("p",
attributes: new Dictionary<string, object>
new TagHelperAttributeList
{
{ "class", "btn" },
{ "something", " spaced " }
@ -175,7 +174,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
// Arrange
var tagHelperOutput = new TagHelperOutput("p",
attributes: new Dictionary<string, object>
new TagHelperAttributeList
{
{ originalName, "btn" },
});
@ -185,7 +184,10 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Assert
var attribute = Assert.Single(tagHelperOutput.Attributes);
Assert.Equal(new KeyValuePair<string, object>(originalName, "super button"), attribute);
Assert.Equal(
new TagHelperAttribute(updateName, "super button"),
attribute,
CaseSensitiveTagHelperAttributeComparer.Default);
}
}
}

View File

@ -135,8 +135,8 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
// Assert
Assert.Equal("foo", output.TagName);
Assert.Equal("somethingelse", output.Attributes["class"]);
Assert.Equal("world", output.Attributes["hello"]);
Assert.Equal("somethingelse", output.Attributes["class"].Value);
Assert.Equal("world", output.Attributes["hello"].Value);
Assert.Equal(true, output.SelfClosing);
}
@ -154,7 +154,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
var output = await runner.RunAsync(executionContext);
// Assert
Assert.Equal("True", output.Attributes["foo"]);
Assert.Equal("True", output.Attributes["foo"].Value);
}
[Fact]
@ -183,8 +183,14 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
Processed = true;
output.TagName = "foo";
output.Attributes["class"] = "somethingelse";
output.Attributes["hello"] = "world";
TagHelperAttribute classAttribute;
if (output.Attributes.TryGetAttribute("class", out classAttribute))
{
classAttribute.Value = "somethingelse";
}
output.Attributes.Add("hello", "world");
output.SelfClosing = true;
}
}
@ -203,7 +209,7 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes["foo"] = context.AllAttributes["foo"].ToString();
output.Attributes.Add("foo", context.AllAttributes["foo"].Value.ToString());
}
}

View File

@ -153,24 +153,26 @@ namespace Microsoft.AspNet.Razor.Test.Framework
public class MarkupTagHelperBlock : TagHelperBlock
{
public MarkupTagHelperBlock(string tagName)
: this(tagName, selfClosing: false, attributes: new Dictionary<string, SyntaxTreeNode>())
: this(tagName, selfClosing: false, attributes: new List<KeyValuePair<string, SyntaxTreeNode>>())
{
}
public MarkupTagHelperBlock(string tagName, bool selfClosing)
: this(tagName, selfClosing, new Dictionary<string, SyntaxTreeNode>())
: this(tagName, selfClosing, new List<KeyValuePair<string, SyntaxTreeNode>>())
{
}
public MarkupTagHelperBlock(string tagName,
IDictionary<string, SyntaxTreeNode> attributes)
public MarkupTagHelperBlock(
string tagName,
IList<KeyValuePair<string, SyntaxTreeNode>> attributes)
: this(tagName, selfClosing: false, attributes: attributes, children: new SyntaxTreeNode[0])
{
}
public MarkupTagHelperBlock(string tagName,
bool selfClosing,
IDictionary<string, SyntaxTreeNode> attributes)
public MarkupTagHelperBlock(
string tagName,
bool selfClosing,
IList<KeyValuePair<string, SyntaxTreeNode>> attributes)
: this(tagName, selfClosing, attributes, new SyntaxTreeNode[0])
{
}
@ -179,27 +181,29 @@ namespace Microsoft.AspNet.Razor.Test.Framework
: this(
tagName,
selfClosing: false,
attributes: new Dictionary<string, SyntaxTreeNode>(),
attributes: new List<KeyValuePair<string, SyntaxTreeNode>>(),
children: children)
{
}
public MarkupTagHelperBlock(string tagName, bool selfClosing, params SyntaxTreeNode[] children)
: this(tagName, selfClosing, new Dictionary<string, SyntaxTreeNode>(), children)
: this(tagName, selfClosing, new List<KeyValuePair<string, SyntaxTreeNode>>(), children)
{
}
public MarkupTagHelperBlock(string tagName,
IDictionary<string, SyntaxTreeNode> attributes,
params SyntaxTreeNode[] children)
public MarkupTagHelperBlock(
string tagName,
IList<KeyValuePair<string, SyntaxTreeNode>> attributes,
params SyntaxTreeNode[] children)
: base(new TagHelperBlockBuilder(tagName, selfClosing: false, attributes: attributes, children: children))
{
}
public MarkupTagHelperBlock(string tagName,
bool selfClosing,
IDictionary<string, SyntaxTreeNode> attributes,
params SyntaxTreeNode[] children)
public MarkupTagHelperBlock(
string tagName,
bool selfClosing,
IList<KeyValuePair<string, SyntaxTreeNode>> attributes,
params SyntaxTreeNode[] children)
: base(new TagHelperBlockBuilder(tagName, selfClosing, attributes, children))
{
}