HtmlUtils.java
package fr.sii.ogham.testing.assertion.util;
import fr.sii.ogham.testing.assertion.exception.ComparisonException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.xmlunit.builder.DiffBuilder;
import org.xmlunit.builder.Input;
import org.xmlunit.diff.DefaultComparisonFormatter;
import org.xmlunit.diff.DefaultNodeMatcher;
import org.xmlunit.diff.Diff;
import org.xmlunit.diff.ElementSelectors;
import wiremock.org.custommonkey.xmlunit.HTMLDocumentBuilder;
import wiremock.org.custommonkey.xmlunit.TolerantSaxDocumentBuilder;
import wiremock.org.custommonkey.xmlunit.XMLUnit;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import java.io.IOException;
public final class HtmlUtils {
/**
* Compare two HTML documents. The HTML strings are parsed into
* {@link Document}s. The HTML are compared by elements and attributes, not
* using directly using string.
*
* <p>
* Documents can be compared using different modes (either "identical" or "similar"):
* <ul>
* <li>Two documents are considered to be "identical" if they contain the
* same elements and attributes in the same order.</li>
* <li>Two documents are considered to be "similar" if they contain the same
* elements and attributes regardless of order.</li>
* </ul>
*
*
* @param expected
* the expected HTML
* @param actual
* the HTML content to check
* @param identical
* true to do an identical comparison, false for a similar comparison
* @return a report that let you know differences between the two HTML
* strings
*/
public static Diff compare(String expected, String actual, boolean identical) {
if (expected == null) {
throw new IllegalArgumentException("expected html can't be null");
}
try {
DiffBuilder builder = getComparatorBuilder(expected, actual);
if (identical) {
builder.checkForIdentical();
} else {
builder.checkForSimilar()
.ignoreComments()
.normalizeWhitespace()
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName));
}
return builder.build();
} catch (ComparisonException e) {
throw e;
} catch (RuntimeException e) {
throw new ComparisonException("Failed to compare HTML", e);
}
}
public static DiffBuilder getComparatorBuilder(String expected, String actual) {
try {
HTMLDocumentBuilder documentBuilder = new HTMLDocumentBuilder(new TolerantSaxDocumentBuilder(XMLUnit.newTestParser()));
Source expectedDoc = Input.fromDocument(documentBuilder.parse(expected)).build();
Source actualDoc = Input.fromDocument(documentBuilder.parse(actual == null ? "" : actual)).build();
return DiffBuilder.compare(expectedDoc)
.withTest(actualDoc)
.withComparisonFormatter(new NoFailureComparisonFormatter());
} catch (SAXException | IOException | ParserConfigurationException e) {
throw new ComparisonException("Failed to compare HTML", e);
}
}
public static class NoFailureComparisonFormatter extends DefaultComparisonFormatter {
@Override
protected void appendDocumentElementIndication(StringBuilder sb, Document doc) {
if (doc.getDocumentElement() == null) {
sb.append("<NULL>");
return;
}
super.appendDocumentElementIndication(sb, doc);
}
}
private HtmlUtils() {
super();
}
}