AngleSharp / AngleSharp.Diffing

A library that makes it possible to compare two AngleSharp node lists and get a list of differences between them.
MIT License
37 stars 6 forks source link

Same comments create a diff. #25

Closed SebastianStehle closed 1 year ago

SebastianStehle commented 2 years ago

Bug Report

Prerequisites

For more information, see the CONTRIBUTING guide.

Description

When I compare two comments a diff is created.

Steps to Reproduce

using AngleSharp.Diffing;
using AngleSharp.Diffing.Strategies.AttributeStrategies;
using AngleSharp.Diffing.Strategies.TextNodeStrategies;

var comment = "<!-- [endif] -->";

var diffs =
    DiffBuilder
        .Compare(comment)
        .WithTest(comment)
        .WithOptions(options => options
            .AddAttributeComparer()
            .AddAttributeNameMatcher()
            .AddBooleanAttributeComparer(BooleanAttributeComparision.Strict)
            .AddClassAttributeComparer()
            .AddCssSelectorMatcher()
            .AddElementComparer()
            .AddIgnoreElementSupport()
            .AddSearchingNodeMatcher()
            .AddStyleAttributeComparer()
            .AddStyleSheetComparer()
            .AddTextComparer(WhitespaceOption.Normalize, ignoreCase: false)
            .IgnoreDiffAttributes()
        )
        .Build();

Console.WriteLine(diffs.Count());

Shows one diff.

egil commented 2 years ago

Does this still break if you just do?

var comment = "<!-- [endif] -->";

var diffs =
    DiffBuilder
        .Compare(comment)
        .WithTest(comment)        
        .Build();

Assert.Equal(0, diffs.Count());

Does this happy to other types of comments? E.g.:

SebastianStehle commented 2 years ago

No, this works. It also happens with other comments. Both empty and with a text.

egil commented 2 years ago

No, this works. It also happens with other comments. Both empty and with a text.

Sorry, which of my questions are you referring to?

SebastianStehle commented 2 years ago

Your code works,

With my code both comments do not work.

egil commented 2 years ago

Ok, I wonder which of the strategies being added are causing this. Is it only this exact configuration that causes this? If not, do you mind reducing the example down as much as possible.

SebastianStehle commented 2 years ago

This is the smallest config I could come up with:

var diffs =
    DiffBuilder
        .Compare(comment)
        .WithTest(comment)
        .WithOptions(options => options
                .AddSearchingNodeMatcher()
        )
        .Build();
egil commented 2 years ago

OK, interesting, thanks.

Does all these cases fail?

[Theory]
[InlineData("<!--comment-->", "<!--comment-->")]
[InlineData("<!-- [endif] -->", "<!-- [endif] -->")]
[InlineData("<!-- -->", "<!-- -->")]
[InlineData("<!---->", "<!---->")]
public void Test001(string controlHtml, string testHtml)
{
    var diffs =
        DiffBuilder
            .Compare(controlHtml)
            .WithTest(testHtml)
            .WithOptions(options => options
                    .AddSearchingNodeMatcher()
            )
            .Build();

    Assert.Equal(0, diffs.Count());
}

The first, "<!--comment-->", is from the test of ForwardSearchingNodeMatcher, which is the matcher used when calling AddSearchingNodeMatcher, so I would think it would work.

SebastianStehle commented 2 years ago

Yes, all these fail in my case. I also added the test to my fork and it fails there as well.

egil commented 2 years ago

Ok, thanks. That will take some additional investigation.

egil commented 1 year ago

@SebastianStehle, sorry for the very long response time on this. Here is what happens:

When you use the WithOptions call, you are responsible for adding in all the compares, matches, filters, etc., since the defaults options are not used.

The default options/configuration is, by the way, this:

options
  .IgnoreDiffAttributes()
  .IgnoreComments()
  .AddSearchingNodeMatcher()
  .AddCssSelectorMatcher()
  .AddAttributeNameMatcher()
  .AddElementComparer()
  .AddIgnoreElementSupport()
  .AddStyleSheetComparer()
  .AddTextComparer(WhitespaceOption.Normalize, ignoreCase: false)
  .AddAttributeComparer()
  .AddClassAttributeComparer()
  .AddBooleanAttributeComparer(BooleanAttributeComparision.Strict)
  .AddStyleAttributeComparer()
  .AddIgnoreChildrenElementSupport()
  .AddIgnoreAttributesElementSupport();

So to make your code work, you just have to call .AddCommentComparer() in the builder options, otherwise the differ does not know how to compare comments. By default, comments are ignored if you do use WithOptions.

using AngleSharp.Diffing;
using AngleSharp.Diffing.Strategies.AttributeStrategies;
using AngleSharp.Diffing.Strategies.TextNodeStrategies;

var comment = "<!-- [endif] -->";

var diffs =
    DiffBuilder
        .Compare(comment)
        .WithTest(comment)
        .WithOptions(options => options
            .AddAttributeComparer()
            .AddAttributeNameMatcher()
            .AddBooleanAttributeComparer(BooleanAttributeComparision.Strict)
            .AddClassAttributeComparer()
            .AddCssSelectorMatcher()
            .AddElementComparer()
            .AddIgnoreElementSupport()
            .AddSearchingNodeMatcher()
            .AddStyleAttributeComparer()
            .AddStyleSheetComparer()
            .AddTextComparer(WhitespaceOption.Normalize, ignoreCase: false)
+           .AddCommentComparer()
            .IgnoreDiffAttributes()
        )
        .Build();

Console.WriteLine(diffs.Count());