Skip to content

Commit

Permalink
When including an expression-based property using ShouldBeEquivalentT…
Browse files Browse the repository at this point in the history
…o it should start evaluation at the root.

Fixed #462
  • Loading branch information
dennisdoomen committed Aug 26, 2016
1 parent 3abfc14 commit 9029a05
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
Expand Up @@ -23,7 +23,7 @@ public IncludeMemberByPathSelectionRule(string pathToInclude) : base(pathToInclu
{
var matchingMembers =
from member in context.RuntimeType.GetNonPrivateMembers()
where pathToInclude.StartsWith(currentPath.Combine(member.Name))
where pathToInclude.IsParentOrChildOf(currentPath.Combine(member.Name))
select member;

return selectedMembers.Concat(matchingMembers).ToArray();
Expand Down
27 changes: 22 additions & 5 deletions Src/Core/Equivalency/Selection/MemberPath.cs
@@ -1,24 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace FluentAssertions.Equivalency.Selection
{
/// <summary>
/// Encapsulates a dotted path to a (nested) member of a type.
/// Encapsulates a dotted candidate to a (nested) member of a type.
/// </summary>
internal class MemberPath
{
private readonly List<string> segments = new List<string>();

public MemberPath(string dottedPath)
{
segments.AddRange(dottedPath.Split('.'));
segments.AddRange(Segmentize(dottedPath));
}

public bool StartsWith(string subPath)
public bool IsParentOrChildOf(string candidate)
{
string[] subPathSegments = subPath.Split('.');
return segments.Take(subPathSegments.Length).SequenceEqual(subPathSegments);
return IsParent(candidate) || IsChild(candidate);
}

private bool IsChild(string candidate)
{
return Segmentize(candidate).Take(segments.Count).SequenceEqual(segments);
}

private bool IsParent(string candidate)
{
string[] candidateSegments = Segmentize(candidate);

return candidateSegments.SequenceEqual(segments.Take(candidateSegments.Length));
}

private static string[] Segmentize(string dottedPath)
{
return dottedPath.Split(new[] { '.', '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
}
}
}
43 changes: 43 additions & 0 deletions Tests/FluentAssertions.Shared.Specs/BasicEquivalencySpecs.cs
Expand Up @@ -574,6 +574,49 @@ public void When_including_a_property_it_should_exactly_match_the_property()
act.ShouldNotThrow();
}

public class CustomType
{
public string Name { get; set; }
}

public class ClassA
{
public List<CustomType> ListOfCustomTypes { get; set; }
}

[TestMethod]
public void When_including_a_property_using_an_expression_it_should_evaluate_it_from_the_root()
{
//-----------------------------------------------------------------------------------------------------------
// Arrange
//-----------------------------------------------------------------------------------------------------------
var list1 = new List<CustomType>
{
new CustomType {Name = "A"},
new CustomType {Name = "B"}
};

var list2 = new List<CustomType>
{
new CustomType {Name = "C"},
new CustomType {Name = "D"}
};

var objectA = new ClassA { ListOfCustomTypes = list1 };
var objectB = new ClassA { ListOfCustomTypes = list2 };

//-----------------------------------------------------------------------------------------------------------
// Act
//-----------------------------------------------------------------------------------------------------------
Action act = () => objectA.ShouldBeEquivalentTo(objectB, options => options.Including(x => x.ListOfCustomTypes));

//-----------------------------------------------------------------------------------------------------------
// Assert
//-----------------------------------------------------------------------------------------------------------
act.ShouldThrow<AssertFailedException>().
WithMessage("*C*but*A*D*but*B*");
}

[TestMethod]
public void When_null_is_provided_as_property_expression_it_should_throw()
{
Expand Down

0 comments on commit 9029a05

Please sign in to comment.