HTML
using Nullean.Snapshots.Html;
page.Should().MatchHtmlSnapshot();
page.Should().BeHtml("<p class=\"lead\">Welcome</p>");
page.Should().ContainHtml("<strong>Welcome</strong>");
page.Should().NotContainHtml("<script>");
HTML is parsed with AngleSharp, pretty-printed (one element per line, tab indented) and compared structurally with
AngleSharp.Diffing: attribute order and whitespace do not matter (except inside <pre> and <textarea>, see below). A failure names each difference and shows a line
diff of the pretty-printed HTML:
HTML did not match snapshot: tests/Docs.Tests/.snapshots/Rendering/TableTests/Renders.verified.html
2 difference(s):
The text in table(0) > tbody(1) > tr(1) > td(1) > #text(0) is different.
expected: {kibana}
actual: {Kibana}
The attribute at table(0) > tbody(1) > tr(1) > td(1)[class] was not expected.
expected: missing
actual: class="x"
Line diff:
@@ line 1 @@
<table>
<tbody>
<tr>
- <td>{kibana}</td>
+ <td class="x">{Kibana}</td>
Whitespace is significant inside <pre>, <textarea> and <listing>, so the snapshot keeps it exactly, at any depth: a code block's lines,
blank lines and indentation, with the markup of a highlighted block (<pre><code><span>…) printed as it is, on the lines it has. A change that only
moves a newline or a space there fails the comparison, and the message shows the lines. Everywhere else whitespace still does not matter.
HtmlSnapshotOptions select, remove and transform before printing, applied to both sides:
var html = new HtmlSnapshotOptions()
.Select("main#content")
.Remove("script")
.RemoveAttributes("hx-*", "preload")
.RemoveAttributesFrom("a", "data-*")
.Transform(root => root.FirstElementChild?.Remove());
page.Should().MatchHtmlSnapshot(html);
- print the content of every match instead of the body (SelectFirst: only the first)
- drop matching elements
- drop attributes everywhere; * is a wildcard
- or only from matching elements
Select prints every element the selector matches, one after the other in document order, so .Select(".card") covers all the cards; an
element inside another match is not printed twice. SelectFirst keeps one. Removals, attribute removals and transforms run on each match.
ContainHtml ignores indentation, so a fragment matches wherever it is nested.
For a short value there is MatchInlineHtmlSnapshot, which keeps the expected value in the test as a literal: see inline snapshots.