gth(t, doc.Find("#main").Nodes, 0)
	assertLength(t, doc.Find("body > #n1").Nodes, 1)
	assertLength(t, doc.Find("body > #nf5").Nodes, 1)

	printSel(t, doc.Selection)
}

func TestUnwrapBody(t *testing.T) {
	doc := Doc2Clone()

	doc.Find("#main").Unwrap()
	assertLength(t, doc.Find("body").Nodes, 1)
	assertLength(t, doc.Find("body > #main").Nodes, 1)

	printSel(t, doc.Selection)
}

func TestUnwrapHead(t *testing.T) {
	doc := Doc2Clone()

	doc.Find("title").Unwrap()
	assertLength(t, doc.Find("head").Nodes, 0)
	assertLength(t, doc.Find("head > title").Nodes, 0)
	assertLength(t, doc.Find("title").Nodes, 1)

	printSel(t, doc.Selection)
}

func TestUnwrapHtml(t *testing.T) {
	doc := Doc2Clone()

	doc.Find("head").Unwrap()
	assertLength(t, doc.Find("html").Nodes, 0)
	assertLength(t, doc.Find("html head").Nodes, 0)
	assertLength(t, doc.Find("head").Nodes, 1)

	printSel(t, doc.Selection)
}

func TestWrap(t *testing.T) {
	doc := Doc2Clone()
	doc.Find("#nf1").Wrap("#nf2")
	nf1 := doc.Find("#foot #nf2 #nf1")
	assertLength(t, nf1.Nodes, 1)

	nf2 := doc.Find("#nf2")
	assertLength(t, nf2.Nodes, 2)

	printSel(t, doc.Selection)
}

func TestWrapEmpty(t *testing.T) {
	doc := Doc2Clone()
	doc.Find("#nf1").Wrap("#doesnt-exist")

	origHtml, _ := Doc2().Html()
	newHtml, _ := doc.Html()

	if origHtml != newHtml {
		t.Error("Expected the two documents to be identical.")
	}

	printSel(t, doc.Selection)
}

func TestWrapHtml(t *testing.T) {
	doc := Doc2Clone()
	doc.Find(".odd").WrapHtml(wrapHtml)
	nf2 := doc.Find("#ins #nf2")
	assertLength(t, nf2.Nodes, 1)
	printSel(t, doc.Selection)
}

func TestWrapSelection(t *testing.T) {
	doc := Doc2Clone()
	doc.Find("#nf1").WrapSelection(doc.Find("#nf2"))
	nf1 := doc.Find("#foot #nf2 #nf1")
	assertLength(t, nf1.Nodes, 1)

	nf2 := doc.Find("#nf2")
	assertLength(t, nf2.Nodes, 2)

	printSel(t, doc.Selection)
}

func TestWrapAll(t *testing.T) {
	doc := Doc2Clone()
	doc.Find(".odd").WrapAll("#nf1")
	nf1 := doc.Find("#main #nf1")
	assertLength(t, nf1.Nodes, 1)

	sel := nf1.Find("#n2 ~ #n4 ~ #n6 ~ #nf2 ~ #nf4 ~ #nf6")
	assertLength(t, sel.Nodes, 1)

	printSel(t, doc.Selection)
}

func TestWrapAllHtml(t *testing.T) {
	doc := Doc2Clone()
	doc.Find(".odd").WrapAllHtml(wrapHtml)
	nf1 := doc.Find("#main div#ins div p em b #n2 ~ #n4 ~ #n6 ~ #nf2 ~ #nf4 ~ #nf6")
	assertLength(t, nf1.Nodes, 1)
	printSel(t, doc.Selection)
}

func TestWrapInnerNoContent(t *testing.T) {
	doc := Doc2Clone()
	doc.Find(".one").WrapInner(".two")

	twos := doc.Find(".two")
	assertLength(t, twos.Nodes, 4)
	assertLength(t, doc.Find(".one .two").Nodes, 2)

	printSel(t, doc.Selection)
}

func TestWrapInnerWithContent(t *testing.T) {
	doc := Doc3Clone()
	doc.Find(".one").WrapInner(".two")

	twos := doc.Find(".two")
	assertLength(t, twos.Nodes, 4)
	assertLength(t, doc.Find(".one .two").Nodes, 2)

	printSel(t, doc.Selection)
}

func TestWrapInnerNoWrapper(t *testing.T) {
	doc := Doc2Clone()
	doc.Find(".one").WrapInner(".not-exist")

	twos := doc.Find(".two")
	assertLength(t, twos.Nodes, 2)
	assertLength(t, doc.Find(".one").Nodes, 2)
	assertLength(t, doc.Find(".one .two").Nodes, 0)

	printSel(t, doc.Selection)
}

func TestWrapInnerHtml(t *testing.T) {
	doc := Doc2Clone()
	doc.Find("#foot").WrapInnerHtml(wrapHtml)

	foot := doc.Find("#foot div#ins div p em b #nf1 ~ #nf2 ~ #nf3")
	assertLength(t, foot.Nodes, 1)

	printSel(t, doc.Selection)
}

func TestParsingRespectsVaryingContext(t *testing.T) {
	docA := loadString(t, `
	<html>
		<body>
			<a class="x"></a>
		</body>
	</html>`)
	docTable := loadString(t, `
	<html>
		<body>
			<table class="x"></table>
		</body>
	</html>`)
	docBoth := loadString(t, `
	<html>
		<body>
			<table class="x"></table>
			<a class="x"></a>
		</body>
	</html>`)

	sA := docA.Find(".x").AppendHtml("<tr><td>Hello</td></tr>")
	sTable := docTable.Find(".x").AppendHtml("<tr><td>Hello</td></tr>")
	sBoth := docBoth.Find(".x").AppendHtml("<tr><td>Hello</td></tr>")

	printSel(t, docA.Selection)
	printSel(t, docTable.Selection)
	printSel(t, docBoth.Selection)

	oA, _ := sA.Html()
	oTable, _ := sTable.Html()

	if oA == oTable {
		t.Errorf("Expected inner html of <a> and <table> to not be equal, but got %s and %s", oA, oTable)
	}

	oBothTable, _ := sBoth.First().Html()
	if oBothTable != oTable {
		t.Errorf("Expected inner html of <table> and <table> in doc containing both tags to be equal, but got %s and %s",
			oTable,
			oBothTable)
	}

	oBothA, _ := sBoth.Last().Html()
	if oBothA != oA {
		t.Errorf("Expected inner html of <a> and <a> in doc containing both tags to be equal, but got %s and %s",
			oA,
			oBothA)
	}
}

func TestHtmlWithNonElementNode(t *testing.T) {
	const data = `
<html>
  <head>
  </head>
  <body>
    <p>
      This is <span>some</span><b>text</b>.
    </p>
  </body>
</html>
`

	cases := map[string]func(*Selection, string) *Selection{
		"AfterHtml":       (*Selection).AfterHtml,
		"AppendHtml":      (*Selection).AppendHtml,
		"BeforeHtml":      (*Selection).BeforeHtml,
		"PrependHtml":     (*Selection).PrependHtml,
		"ReplaceWithHtml": (*Selection).ReplaceWithHtml,
		"SetHtml":         (*Selection).SetHtml,
	}
	for nm, fn := range cases {
		// this test is only to make sure that the HTML parsing/manipulation
		// methods do not raise panics when executed over Selections that contain
		// non-Element nodes.
		t.Run(nm, func(t *testing.T) {
			doc := loadString(t, data)
			sel := doc.Find("p").Contents()
			func() {
				defer func() {
					if err := recover(); err != nil {
						t.Fatal(err)
					}
				}()
				fn(sel, "<div></div>")
			}()

			// print the resulting document in verbose mode
			h, err := OuterHtml(doc.Selection)
			if err != nil {
				log.Fatal(err)
			}
			t.Log(h)
		})
	}
}
