// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package html import ( "bytes" "fmt" "strings" "testing" ) func TestRenderer(t *testing.T) { nodes := [...]*Node{ 0: { Type: ElementNode, Data: "html", }, 1: { Type: ElementNode, Data: "head", }, 2: { Type: ElementNode, Data: "body", }, 3: { Type: TextNode, Data: "0<1", }, 4: { Type: ElementNode, Data: "p", Attr: []Attribute{ { Key: "id", Val: "A", }, { Key: "foo", Val: `abc"def`, }, }, }, 5: { Type: TextNode, Data: "2", }, 6: { Type: ElementNode, Data: "b", Attr: []Attribute{ { Key: "empty", Val: "", }, }, }, 7: { Type: TextNode, Data: "3", }, 8: { Type: ElementNode, Data: "i", Attr: []Attribute{ { Key: "backslash", Val: `\`, }, }, }, 9: { Type: TextNode, Data: "&4", }, 10: { Type: TextNode, Data: "5", }, 11: { Type: ElementNode, Data: "blockquote", }, 12: { Type: ElementNode, Data: "br", }, 13: { Type: TextNode, Data: "6", }, 14: { Type: CommentNode, Data: "comm", }, 15: { Type: CommentNode, Data: "x-->y", // Needs escaping. }, 16: { Type: RawNode, Data: "7
89", }, } // Build a tree out of those nodes, based on a textual representation. // Only the ".\t"s are significant. The trailing HTML-like text is // just commentary. The "0:" prefixes are for easy cross-reference with // the nodes array. treeAsText := [...]string{ 0: ``, 1: `. `, 2: `. `, 3: `. . "0<1"`, 4: `. .
`,
5: `. . . "2"`,
6: `. . . `,
7: `. . . . "3"`,
8: `. . . `,
9: `. . . . "&4"`,
10: `. . "5"`,
11: `. . ` +
`23&4`,
12: `. .
`,
13: `. . "6"`,
14: `. . ""`,
15: `. . ""`,
16: `. . "78
9"`,
}
if len(nodes) != len(treeAsText) {
t.Fatal("len(nodes) != len(treeAsText)")
}
var stack [8]*Node
for i, line := range treeAsText {
level := 0
for line[0] == '.' {
// Strip a leading ".\t".
line = line[2:]
level++
}
n := nodes[i]
if level == 0 {
if stack[0] != nil {
t.Fatal("multiple root nodes")
}
stack[0] = n
} else {
stack[level-1].AppendChild(n)
stack[level] = n
for i := level + 1; i < len(stack); i++ {
stack[i] = nil
}
}
// At each stage of tree construction, we check all nodes for consistency.
for j, m := range nodes {
if err := checkNodeConsistency(m); err != nil {
t.Fatalf("i=%d, j=%d: %v", i, j, err)
}
}
}
want := `0<1
678
9`
b := new(bytes.Buffer)
if err := Render(b, nodes[0]); err != nil {
t.Fatal(err)
}
if got := b.String(); got != want {
t.Errorf("got vs want:\n%s\n%s\n", got, want)
}
}
func TestRenderTextNodes(t *testing.T) {
elements := []string{"style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript"}
for _, namespace := range []string{
"", // html
"svg",
"math",
} {
for _, e := range elements {
var namespaceOpen, namespaceClose string
if namespace != "" {
namespaceOpen, namespaceClose = fmt.Sprintf("<%s>", namespace), fmt.Sprintf("%s>", namespace)
}
doc := fmt.Sprintf(`%s<%s>&%s>%s`, namespaceOpen, e, e, namespaceClose)
n, err := Parse(strings.NewReader(doc))
if err != nil {
t.Fatal(err)
}
b := bytes.NewBuffer(nil)
if err := Render(b, n); err != nil {
t.Fatal(err)
}
expected := doc
if namespace != "" {
expected = strings.Replace(expected, "&", "&", 1)
}
if b.String() != expected {
t.Errorf("unexpected output: got %q, want %q", b.String(), expected)
}
}
}
}