Skip to content

Commit d06c7c4

Browse files
committed
tests - missing html suite
Signed-off-by: George Lemon <georgelemon@protonmail.com>
1 parent d179a25 commit d06c7c4

1 file changed

Lines changed: 175 additions & 0 deletions

File tree

tests/test_html.nim

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import std/[unittest, os, strutils, tables]
2+
import ../src/openparser/html
3+
4+
suite "HTML parser – basic":
5+
6+
test "parse simple document":
7+
let doc = parseHtml("<html><head><title>Hi</title></head><body><p>Text</p></body></html>")
8+
check doc.nodes.len == 1
9+
check doc.nodes[0].tag == tagHtml
10+
11+
test "inner text extraction":
12+
let doc = parseHtml("<div>Hello <b>world</b></div>")
13+
check doc.nodes[0].innerText() == "Hello world"
14+
15+
test "attributes parsed":
16+
let doc = parseHtml("<div id=\"x\" class=\"a b\">ok</div>")
17+
let attrs = doc.nodes[0].attributes
18+
check attrs["id"] == "x"
19+
check attrs["class"] == "a b"
20+
21+
test "self-closing tags":
22+
let doc = parseHtml("<br><hr><img src=\"a.png\">")
23+
check doc.nodes.len == 3
24+
check doc.nodes[0].tag == tagBr
25+
check doc.nodes[1].tag == tagHr
26+
check doc.nodes[2].tag == tagImg
27+
28+
test "unknown tags become tagUnknown":
29+
let doc = parseHtml("<foo>bar</foo>")
30+
check doc.nodes[0].tag == tagUnknown
31+
32+
suite "HTML parser – fault tolerance":
33+
34+
test "unterminated comment – recoverable":
35+
let doc = parseHtml("text <!-- unclosed comment")
36+
check doc.nodes.len >= 1
37+
# should contain a comment node with partial content
38+
var foundComment = false
39+
for n in doc.nodes:
40+
if n.kind == htmlComment:
41+
foundComment = true
42+
check "unclosed comment" in n.comment
43+
check foundComment
44+
45+
test "unterminated attribute value – recoverable":
46+
let doc = parseHtml("<div class=\"foo>text</div>")
47+
check doc.nodes.len == 1
48+
let node = doc.nodes[0]
49+
check node.tag == tagDiv
50+
check node.attributes["class"] == "foo"
51+
52+
test "unclosed tag – allowUnclosedTags true":
53+
let policy = HtmlParserPolicy(
54+
allowSelfClosingTags: true,
55+
allowUnclosedTags: true,
56+
allowComments: true,
57+
allowDoctype: true,
58+
allowProcessingInstructions: false,
59+
allowCdata: false,
60+
allowScriptAndStyleContent: true,
61+
allowEntities: true,
62+
allowRawText: false,
63+
allowHtmlInAttributes: false,
64+
allowUnquotedAttributes: false,
65+
allowDuplicateAttributes: false,
66+
allowInvalidTags: false,
67+
allowInvalidAttributeNames: false,
68+
allowInvalidAttributeValues: false,
69+
allowInvalidNesting: false,
70+
allowInvalidSyntax: false
71+
)
72+
let doc = parseHtml("<div><p>Text", policy)
73+
check doc.nodes.len == 1
74+
check doc.nodes[0].tag == tagDiv
75+
76+
test "unclosed tag – allowUnclosedTags false raises":
77+
let policy = HtmlParserPolicy(
78+
allowSelfClosingTags: true,
79+
allowUnclosedTags: false,
80+
allowComments: true,
81+
allowDoctype: true,
82+
allowProcessingInstructions: false,
83+
allowCdata: false,
84+
allowScriptAndStyleContent: true,
85+
allowEntities: true,
86+
allowRawText: false,
87+
allowHtmlInAttributes: false,
88+
allowUnquotedAttributes: false,
89+
allowDuplicateAttributes: false,
90+
allowInvalidTags: false,
91+
allowInvalidAttributeNames: false,
92+
allowInvalidAttributeValues: false,
93+
allowInvalidNesting: false,
94+
allowInvalidSyntax: false
95+
)
96+
expect HtmlParserError:
97+
discard parseHtml("<div><p>Text", policy)
98+
99+
test "mismatched closing tag – skipped, not fatal":
100+
let doc = parseHtml("<div><p>text</div></p>")
101+
check doc.nodes.len == 1
102+
check doc.nodes[0].tag == tagDiv
103+
104+
test "bare text outside tags":
105+
let doc = parseHtml("just text")
106+
check doc.nodes.len == 1
107+
check doc.nodes[0].kind == htmlInnerText
108+
check doc.nodes[0].value.text == "just text"
109+
110+
test "stray > character":
111+
let doc = parseHtml("<div>ok</div>>extra")
112+
check doc.nodes.len >= 1
113+
114+
test "empty input":
115+
let doc = parseHtml("")
116+
check doc.nodes.len == 0
117+
118+
test "only comment":
119+
let doc = parseHtml("<!-- hello -->")
120+
check doc.nodes.len == 1
121+
check doc.nodes[0].kind == htmlComment
122+
check doc.nodes[0].comment == " hello "
123+
124+
suite "HTML parser – parseHtmlFile":
125+
126+
test "parseHtmlFile returns HtmlDocument":
127+
let path = "tests" / "data" / "test_html_sample.html"
128+
writeFile(path, "<html><body><p>file content</p></body></html>")
129+
defer: removeFile(path)
130+
let doc = parseHtmlFile(path)
131+
check doc.nodes.len == 1
132+
check doc.nodes[0].tag == tagHtml
133+
134+
test "parseHtmlFile with custom policy":
135+
let path = "tests" / "data" / "test_html_custom.html"
136+
writeFile(path, "<div>unclosed")
137+
defer: removeFile(path)
138+
let policy = defaulHtmlParsingPolicy()
139+
let doc = parseHtmlFile(path, policy)
140+
check doc.nodes.len == 1
141+
142+
suite "HTML parser – edge cases":
143+
144+
test "nested elements":
145+
let doc = parseHtml("<div><span><b>deep</b></span></div>")
146+
let el = doc.nodes[0]
147+
check el.tag == tagDiv
148+
check el.children.len == 1
149+
check el.children[0].tag == tagSpan
150+
check el.children[0].children[0].tag == tagB
151+
152+
test "multiple root nodes":
153+
let doc = parseHtml("<p>one</p><p>two</p><p>three</p>")
154+
check doc.nodes.len == 3
155+
for n in doc.nodes:
156+
check n.tag == tagP
157+
158+
test "comments inside elements":
159+
let doc = parseHtml("<div><!-- inner --></div>")
160+
let el = doc.nodes[0]
161+
check el.children.len == 1
162+
check el.children[0].kind == htmlComment
163+
164+
test "self-closing inside normal element":
165+
let doc = parseHtml("<div>before<br>after</div>")
166+
let el = doc.nodes[0]
167+
check el.children.len == 3
168+
check el.children[0].kind == htmlInnerText
169+
check el.children[1].tag == tagBr
170+
check el.children[2].kind == htmlInnerText
171+
172+
test "deeply nested unclosed tags with allowUnclosedTags":
173+
let doc = parseHtml("<div><span><b>text", defaulHtmlParsingPolicy())
174+
check doc.nodes.len == 1
175+
check doc.nodes[0].tag == tagDiv

0 commit comments

Comments
 (0)