Skip to content

Commit

Permalink
Merge 47b6647 into 418a405
Browse files Browse the repository at this point in the history
  • Loading branch information
logiclrd committed Mar 1, 2022
2 parents 418a405 + 47b6647 commit 212a579
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,21 @@ public class StructuralEqualityEquivalencyStep : IEquivalencyStep
IMember matchingMember = FindMatchFor(selectedMember, context.CurrentNode, comparands.Subject, options);
if (matchingMember is not null)
{
if (!options.ExcludeNonBrowsable || matchingMember.IsBrowsable)
var nestedComparands = new Comparands
{
var nestedComparands = new Comparands
{
Subject = matchingMember.GetValue(comparands.Subject),
Expectation = selectedMember.GetValue(comparands.Expectation),
CompileTimeType = selectedMember.Type
};

if (selectedMember.Name != matchingMember.Name)
{
// In case the matching process selected a different member on the subject,
// adjust the current member so that assertion failures report the proper name.
selectedMember.Name = matchingMember.Name;
}

parent.RecursivelyAssertEquality(nestedComparands, context.AsNestedMember(selectedMember));
Subject = matchingMember.GetValue(comparands.Subject),
Expectation = selectedMember.GetValue(comparands.Expectation),
CompileTimeType = selectedMember.Type
};

if (selectedMember.Name != matchingMember.Name)
{
// In case the matching process selected a different member on the subject,
// adjust the current member so that assertion failures report the proper name.
selectedMember.Name = matchingMember.Name;
}

parent.RecursivelyAssertEquality(nestedComparands, context.AsNestedMember(selectedMember));
}
}

Expand All @@ -85,6 +82,13 @@ public class StructuralEqualityEquivalencyStep : IEquivalencyStep
where match is not null
select match;

// This excludes non-browsable members from the subject. If a member is marked non-browsable
// in the expectation, it gets excluded in GetMembersFromExpectation.
if (config.ExcludeNonBrowsable)
{
query = query.Where(member => member.IsBrowsable);
}

return query.FirstOrDefault();
}

Expand All @@ -99,6 +103,13 @@ public class StructuralEqualityEquivalencyStep : IEquivalencyStep
new MemberSelectionContext(comparands.CompileTimeType, comparands.RuntimeType, options));
}

// This excludes non-browsable members from the expectation. If a member is marked non-browsable
// in the subject, it gets excluded in FindMatchFor.
if (options.ExcludeNonBrowsable)
{
members = members.Where(member => member.IsBrowsable);
}

return members;
}
}
Expand Down
210 changes: 206 additions & 4 deletions Tests/FluentAssertions.Equivalency.Specs/SelectionRulesSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1723,29 +1723,231 @@ public void When_non_browsable_property_differs_excluding_non_browsable_members_
subject.Should().BeEquivalentTo(expectation, config => config.ExcludingNonBrowsableMembers());
}

[Fact]
public void When_property_is_non_browsable_only_in_subject_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject = new ClassWithNonBrowsableMembers() { NonBrowsableProperty = 0 };
var expectation = new ClassWithMatchingMemberNamesButEverythingIsBrowsable() { NonBrowsableProperty = 1 };

// Act & Assert
subject.Should().BeEquivalentTo(expectation, config => config.ExcludingNonBrowsableMembers());
}

[Fact]
public void When_property_is_non_browsable_only_in_expectation_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject = new ClassWithMatchingMemberNamesButEverythingIsBrowsable() { NonBrowsableProperty = 0 };
var expectation = new ClassWithNonBrowsableMembers() { NonBrowsableProperty = 1 };

// Act & Assert
subject.Should().BeEquivalentTo(expectation, config => config.ExcludingNonBrowsableMembers());
}

[Fact]
public void When_field_is_non_browsable_only_in_subject_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject = new ClassWithNonBrowsableMembers() { NonBrowsableField = 0 };
var expectation = new ClassWithMatchingMemberNamesButEverythingIsBrowsable() { NonBrowsableField = 1 };

// Act & Assert
subject.Should().BeEquivalentTo(expectation, config => config.ExcludingNonBrowsableMembers());
}

[Fact]
public void When_field_is_non_browsable_only_in_expectation_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject = new ClassWithMatchingMemberNamesButEverythingIsBrowsable() { NonBrowsableField = 0 };
var expectation = new ClassWithNonBrowsableMembers() { NonBrowsableField = 1 };

// Act & Assert
subject.Should().BeEquivalentTo(expectation, config => config.ExcludingNonBrowsableMembers());
}

public class NonBrowsableOnOneButMissingFromTheOther
{
[Fact]
public void When_property_is_missing_from_subject_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject =
new
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
NonBrowsableField = 2,
/* NonBrowsableProperty missing */
};

var expected =
new ClassWithNonBrowsableMembers
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
NonBrowsableField = 2,
NonBrowsableProperty = 2,
};

// Act & Assert
subject.Should().BeEquivalentTo(expected, opt => opt.ExcludingNonBrowsableMembers());
}

[Fact]
public void When_field_is_missing_from_subject_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject =
new
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
/* NonBrowsableField missing */
NonBrowsableProperty = 2,
};

var expected =
new ClassWithNonBrowsableMembers
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
NonBrowsableField = 2,
NonBrowsableProperty = 2,
};

// Act & Assert
subject.Should().BeEquivalentTo(expected, opt => opt.ExcludingNonBrowsableMembers());
}

[Fact]
public void When_property_is_missing_from_expectation_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject =
new ClassWithNonBrowsableMembers
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
NonBrowsableField = 2,
NonBrowsableProperty = 2,
};

var expected =
new
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
NonBrowsableField = 2,
/* NonBrowsableProperty missing */
};

// Act & Assert
subject.Should().BeEquivalentTo(expected, opt => opt.ExcludingNonBrowsableMembers());
}

[Fact]
public void When_field_is_missing_from_expectation_excluding_non_browsable_members_should_make_it_succeed()
{
// Arrange
var subject =
new ClassWithNonBrowsableMembers
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
NonBrowsableField = 2,
NonBrowsableProperty = 2,
};

var expected =
new
{
BrowsableField = 1,
BrowsableProperty = 1,
ExplicitlyBrowsableField = 1,
ExplicitlyBrowsableProperty = 1,
AdvancedBrowsableField = 1,
AdvancedBrowsableProperty = 1,
/* NonBrowsableField missing */
NonBrowsableProperty = 2,
};

// Act & Assert
subject.Should().BeEquivalentTo(expected, opt => opt.ExcludingNonBrowsableMembers());
}
}

private class ClassWithNonBrowsableMembers
{
public int BrowsableField;
public int BrowsableField = -1;

public int BrowsableProperty { get; set; }

[EditorBrowsable(EditorBrowsableState.Always)]
public int ExplicitlyBrowsableField;
public int ExplicitlyBrowsableField = -1;

[EditorBrowsable(EditorBrowsableState.Always)]
public int ExplicitlyBrowsableProperty { get; set; }

[EditorBrowsable(EditorBrowsableState.Advanced)]
public int AdvancedBrowsableField;
public int AdvancedBrowsableField = -1;

[EditorBrowsable(EditorBrowsableState.Advanced)]
public int AdvancedBrowsableProperty { get; set; }

[EditorBrowsable(EditorBrowsableState.Never)]
public int NonBrowsableField;
public int NonBrowsableField = -1;

[EditorBrowsable(EditorBrowsableState.Never)]
public int NonBrowsableProperty { get; set; }
}

private class ClassWithMatchingMemberNamesButEverythingIsBrowsable
{
public int BrowsableField = -1;

public int BrowsableProperty { get; set; }

public int ExplicitlyBrowsableField = -1;

public int ExplicitlyBrowsableProperty { get; set; }

public int AdvancedBrowsableField = -1;

public int AdvancedBrowsableProperty { get; set; }

public int NonBrowsableField = -1;

public int NonBrowsableProperty { get; set; }
}
}
}

0 comments on commit 212a579

Please sign in to comment.