diff --git a/CHANGELOG.md b/CHANGELOG.md index 0721ce5..068a2d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.17.0 + +Released on Wednesday, September 8, 2021. + +- Added the ability to ignore an elements children or its attributes. By [@grishat](https://github.com/grishat). + # 0.16.0 Released on Wednesday, June 24, 2021. diff --git a/src/AngleSharp.Diffing.Tests/Core/HtmlDifferenceEngineTest.cs b/src/AngleSharp.Diffing.Tests/Core/HtmlDifferenceEngineTest.cs index 302f713..6068afb 100644 --- a/src/AngleSharp.Diffing.Tests/Core/HtmlDifferenceEngineTest.cs +++ b/src/AngleSharp.Diffing.Tests/Core/HtmlDifferenceEngineTest.cs @@ -357,6 +357,44 @@ public void Test2() results.ShouldBeEmpty(); } + [Theory(DisplayName = "When comparer returns SkipChildren flag from an element comparison, child nodes are not compared")] + [InlineData(CompareResult.Same | CompareResult.SkipChildren)] + [InlineData(CompareResult.Skip | CompareResult.SkipChildren)] + public void Test3(CompareResult compareResult) + { + var sut = CreateHtmlDiffer( + nodeMatcher: OneToOneNodeListMatcher, + nodeFilter: NoneNodeFilter, + nodeComparer: c => c.Control.Node.NodeName == "P" ? compareResult : throw new Exception("NODE COMPARER SHOULD NOT BE CALLED ON CHILD NODES"), + attrMatcher: AttributeNameMatcher, + attrFilter: NoneAttrFilter, + attrComparer: SameResultAttrComparer + ); + + var results = sut.Compare(ToNodeList(@"
foo
"), ToNodeList(@"baz
")); + + results.ShouldBeEmpty(); + } + + [Theory(DisplayName = "When comparer returns SkipAttributes flag from an element comparison, attributes are not compared")] + [InlineData(CompareResult.Same | CompareResult.SkipAttributes)] + [InlineData(CompareResult.Skip | CompareResult.SkipAttributes)] + public void Test4(CompareResult compareResult) + { + var sut = CreateHtmlDiffer( + nodeMatcher: OneToOneNodeListMatcher, + nodeFilter: NoneNodeFilter, + nodeComparer: c => compareResult, + attrMatcher: AttributeNameMatcher, + attrFilter: NoneAttrFilter, + attrComparer: SameResultAttrComparer + ); + + var results = sut.Compare(ToNodeList(@""), ToNodeList(@"")); + + results.ShouldBeEmpty(); + } + #region NodeFilters private static FilterDecision NoneNodeFilter(ComparisonSource source) => FilterDecision.Keep; private static FilterDecision RemoveCommentNodeFilter(ComparisonSource source) => source.Node.NodeType == NodeType.Comment ? FilterDecision.Exclude : FilterDecision.Keep; diff --git a/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs b/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs index 8d973c2..be8914f 100644 --- a/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs +++ b/src/AngleSharp.Diffing.Tests/DiffBuilderTest.cs @@ -89,5 +89,41 @@ public void Test004() nodeComparerCalled.ShouldBeTrue(); attrComparerCalled.ShouldBeTrue(); } + + [Theory(DisplayName = "When a control element has 'diff:ignoreChildren', calling Build() with DefaultOptions() returns empty diffs")] + [InlineData(@"hello world
", + @"world says hello
")] + [InlineData(@"hello
", + @"world says hello
")] + [InlineData(@"hello world
", + @"world says
")] + public void Test005(string control, string test) + { + var diffs = DiffBuilder + .Compare(control) + .WithTest(test) + .Build() + .ToList(); + + diffs.ShouldBeEmpty(); + } + + [Theory(DisplayName = "When a control element has 'diff:ignoreAttributes', calling Build() with DefaultOptions() returns empty diffs")] + [InlineData(@"", + @"")] + [InlineData(@"", + @"")] + [InlineData(@"", + @"")] + public void Test006(string control, string test) + { + var diffs = DiffBuilder + .Compare(control) + .WithTest(test) + .Build() + .ToList(); + + diffs.ShouldBeEmpty(); + } } } diff --git a/src/AngleSharp.Diffing.Tests/Strategies/ElementStrategies/IgnoreAttributesElementComparerTest.cs b/src/AngleSharp.Diffing.Tests/Strategies/ElementStrategies/IgnoreAttributesElementComparerTest.cs new file mode 100644 index 0000000..6959de7 --- /dev/null +++ b/src/AngleSharp.Diffing.Tests/Strategies/ElementStrategies/IgnoreAttributesElementComparerTest.cs @@ -0,0 +1,44 @@ +using System.Linq; + +using AngleSharp.Diffing.Core; + +using Shouldly; + +using Xunit; + +namespace AngleSharp.Diffing.Strategies.ElementStrategies +{ + public class IgnoreAttributesElementComparerTest : DiffingTestBase + { + public IgnoreAttributesElementComparerTest(DiffingTestFixture fixture) : base(fixture) + { + } + + [Theory(DisplayName = "When a control element does not contain the 'diff:ignoreAttributes' attribute or it is 'diff:ignoreAttributes=false', the current decision is returned")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + public void Test001(string controlHtml) + { + var comparison = ToComparison(controlHtml, ""); + + IgnoreAttributesElementComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different); + IgnoreAttributesElementComparer.Compare(comparison, CompareResult.Same).ShouldBe(CompareResult.Same); + IgnoreAttributesElementComparer.Compare(comparison, CompareResult.Skip).ShouldBe(CompareResult.Skip); + } + + [Theory(DisplayName = "When a control element has 'diff:ignoreAttributes' attribute, CompareResult.SkipAttributes flag is returned")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + public void Test002(string controlHtml) + { + var comparison = ToComparison(controlHtml, ""); + + IgnoreAttributesElementComparer.Compare(comparison, CompareResult.Same).ShouldBe(CompareResult.Same | CompareResult.SkipAttributes); + IgnoreAttributesElementComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different | CompareResult.SkipAttributes); + } + } +} diff --git a/src/AngleSharp.Diffing.Tests/Strategies/ElementStrategies/IgnoreChildrenElementComparerTest.cs b/src/AngleSharp.Diffing.Tests/Strategies/ElementStrategies/IgnoreChildrenElementComparerTest.cs new file mode 100644 index 0000000..c02e7b0 --- /dev/null +++ b/src/AngleSharp.Diffing.Tests/Strategies/ElementStrategies/IgnoreChildrenElementComparerTest.cs @@ -0,0 +1,44 @@ +using System.Linq; + +using AngleSharp.Diffing.Core; + +using Shouldly; + +using Xunit; + +namespace AngleSharp.Diffing.Strategies.ElementStrategies +{ + public class IgnoreChildrenElementComparerTest : DiffingTestBase + { + public IgnoreChildrenElementComparerTest(DiffingTestFixture fixture) : base(fixture) + { + } + + [Theory(DisplayName = "When a control element does not contain the 'diff:ignoreChildren' attribute or it is 'diff:ignoreChildren=false', the current decision is returned")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + public void Test001(string controlHtml) + { + var comparison = ToComparison(controlHtml, ""); + + IgnoreChildrenElementComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different); + IgnoreChildrenElementComparer.Compare(comparison, CompareResult.Same).ShouldBe(CompareResult.Same); + IgnoreChildrenElementComparer.Compare(comparison, CompareResult.Skip).ShouldBe(CompareResult.Skip); + } + + [Theory(DisplayName = "When a control element has 'diff:ignoreChildren' attribute, CompareResult.SkipChildren flag is returned")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + [InlineData(@"")] + public void Test002(string controlHtml) + { + var comparison = ToComparison(controlHtml, ""); + + IgnoreChildrenElementComparer.Compare(comparison, CompareResult.Same).ShouldBe(CompareResult.Same | CompareResult.SkipChildren); + IgnoreChildrenElementComparer.Compare(comparison, CompareResult.Different).ShouldBe(CompareResult.Different | CompareResult.SkipChildren); + } + } +} diff --git a/src/AngleSharp.Diffing/Core/CompareResult.cs b/src/AngleSharp.Diffing/Core/CompareResult.cs index 4ec46ea..7b5ea20 100644 --- a/src/AngleSharp.Diffing/Core/CompareResult.cs +++ b/src/AngleSharp.Diffing/Core/CompareResult.cs @@ -1,22 +1,33 @@ -namespace AngleSharp.Diffing.Core +using System; + +namespace AngleSharp.Diffing.Core { ///