1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8	"bytes"
9	"testing"
10)
11
12func TestRenderer(t *testing.T) {
13	nodes := [...]*Node{
14		0: {
15			Type: ElementNode,
16			Data: "html",
17		},
18		1: {
19			Type: ElementNode,
20			Data: "head",
21		},
22		2: {
23			Type: ElementNode,
24			Data: "body",
25		},
26		3: {
27			Type: TextNode,
28			Data: "0<1",
29		},
30		4: {
31			Type: ElementNode,
32			Data: "p",
33			Attr: []Attribute{
34				{
35					Key: "id",
36					Val: "A",
37				},
38				{
39					Key: "foo",
40					Val: `abc"def`,
41				},
42			},
43		},
44		5: {
45			Type: TextNode,
46			Data: "2",
47		},
48		6: {
49			Type: ElementNode,
50			Data: "b",
51			Attr: []Attribute{
52				{
53					Key: "empty",
54					Val: "",
55				},
56			},
57		},
58		7: {
59			Type: TextNode,
60			Data: "3",
61		},
62		8: {
63			Type: ElementNode,
64			Data: "i",
65			Attr: []Attribute{
66				{
67					Key: "backslash",
68					Val: `\`,
69				},
70			},
71		},
72		9: {
73			Type: TextNode,
74			Data: "&4",
75		},
76		10: {
77			Type: TextNode,
78			Data: "5",
79		},
80		11: {
81			Type: ElementNode,
82			Data: "blockquote",
83		},
84		12: {
85			Type: ElementNode,
86			Data: "br",
87		},
88		13: {
89			Type: TextNode,
90			Data: "6",
91		},
92		14: {
93			Type: CommentNode,
94			Data: "comm",
95		},
96		15: {
97			Type: RawNode,
98			Data: "7<pre>8</pre>9",
99		},
100	}
101
102	// Build a tree out of those nodes, based on a textual representation.
103	// Only the ".\t"s are significant. The trailing HTML-like text is
104	// just commentary. The "0:" prefixes are for easy cross-reference with
105	// the nodes array.
106	treeAsText := [...]string{
107		0: `<html>`,
108		1: `.	<head>`,
109		2: `.	<body>`,
110		3: `.	.	"0&lt;1"`,
111		4: `.	.	<p id="A" foo="abc&#34;def">`,
112		5: `.	.	.	"2"`,
113		6: `.	.	.	<b empty="">`,
114		7: `.	.	.	.	"3"`,
115		8: `.	.	.	<i backslash="\">`,
116		9: `.	.	.	.	"&amp;4"`,
117		10: `.	.	"5"`,
118		11: `.	.	<blockquote>`,
119		12: `.	.	<br>`,
120		13: `.	.	"6"`,
121		14: `.	.	"<!--comm-->"`,
122		15: `.	.	"7<pre>8</pre>9"`,
123	}
124	if len(nodes) != len(treeAsText) {
125		t.Fatal("len(nodes) != len(treeAsText)")
126	}
127	var stack [8]*Node
128	for i, line := range treeAsText {
129		level := 0
130		for line[0] == '.' {
131			// Strip a leading ".\t".
132			line = line[2:]
133			level++
134		}
135		n := nodes[i]
136		if level == 0 {
137			if stack[0] != nil {
138				t.Fatal("multiple root nodes")
139			}
140			stack[0] = n
141		} else {
142			stack[level-1].AppendChild(n)
143			stack[level] = n
144			for i := level + 1; i < len(stack); i++ {
145				stack[i] = nil
146			}
147		}
148		// At each stage of tree construction, we check all nodes for consistency.
149		for j, m := range nodes {
150			if err := checkNodeConsistency(m); err != nil {
151				t.Fatalf("i=%d, j=%d: %v", i, j, err)
152			}
153		}
154	}
155
156	want := `<html><head></head><body>0&lt;1<p id="A" foo="abc&#34;def">` +
157		`2<b empty="">3</b><i backslash="\">&amp;4</i></p>` +
158		`5<blockquote></blockquote><br/>6<!--comm-->7<pre>8</pre>9</body></html>`
159	b := new(bytes.Buffer)
160	if err := Render(b, nodes[0]); err != nil {
161		t.Fatal(err)
162	}
163	if got := b.String(); got != want {
164		t.Errorf("got vs want:\n%s\n%s\n", got, want)
165	}
166}
167