# Features covered: HTML parser
#
# This file contains a collection of tests for the HTML parser.
# Tested functionalities:
#    html-1.*: Character encoding
#    html-2.*: Parsing tests
#    html-3.*: Bad data
#    html-4.*: DOM building
#
# Copyright (c) 2002-2007 Rolf Ade.
#
# RCS: @(#) $Id$

source [file join [file dir [info script]] loadtdom.tcl]

test html-1.1 {HTML character entities} {
    set doc [dom parse -html {<html><body>&nbsp;&iexcl;&Auml;&uuml;</body></html>}]
    set root [$doc documentElement]
    set body [$root firstChild]
    set result [$body text]
    $doc delete
    set result
} "\u00A0\u00A1\u00c4\u00fc"

test html-1.2 {character entities} {
    set doc [dom parse -html {<html><body>&#214;&#xC4;&#xc4;</body></html>}]
    set root [$doc documentElement]
    set body [$root firstChild]
    set result [$body text]
    $doc delete
    set result
} "\u00d6\u00c4\u00c4"

test html-1.3 {character entities} {
    set doc [dom parse -html {<html>&euro;&ni;</html>}]
    set root [$doc documentElement]
    set result [$root text]
    $doc delete
    set result
} "\u20ac\u220b"

test html-1.4 {Invalid numeric character entity} {
    set doc [dom parse -html {<html>&#39xyz</html>}]
    set root [$doc documentElement]
    set result [$root text]
    $doc delete
    set result
} "&#39xyz"

test html-1.5 {Numeric character entity} {
    set doc [dom parse -html {<html>&#123456789012345678;</html>}]
    set root [$doc documentElement]
    set result [$root text]
    $doc delete
    set result
} "&#123456789012345678;"

test html-1.6 {Numeric character entity} {
    set doc [dom parse -html {<html>&#xabcdef;</html>}]
    set root [$doc documentElement]
    set result [$root text]
    $doc delete
    set result
} "&#xabcdef;"

test html-1.7 {character entities} {
    set doc [dom parse -html {<html>&frac14;</html>}]
    set root [$doc documentElement]
    set result [$root text]
    $doc delete
    set result
} "\u00bc"

proc toutf8 c {
    set s [encoding convertto utf-8 $c]
    binary scan $s H* x
    regsub -all -expanded {..} $x {\x&}
}

test html-1.8 {character entities} {
    set result ""
    foreach {entity byteseq} {
        "amp"       "\\x26"
        "lt"        "\\x3C"
        "gt"        "\\x3E"
        "apos"      "\\x27"
        "quot"      "\\x22"
        "nbsp"      "\\xC2\\xA0"
        "iexcl"     "\\xC2\\xA1"
        "cent"      "\\xC2\\xA2"
        "pound"     "\\xC2\\xA3"
        "curren"    "\\xC2\\xA4"
        "yen"       "\\xC2\\xA5"
        "brvbar"    "\\xC2\\xA6"
        "sect"      "\\xC2\\xA7"
        "uml"       "\\xC2\\xA8"
        "copy"      "\\xC2\\xA9"
        "ordf"      "\\xC2\\xAA"
        "laquo"     "\\xC2\\xAB"
        "not"       "\\xC2\\xAC"
        "shy"       "\\xC2\\xAD"
        "reg"       "\\xC2\\xAE"
        "macr"      "\\xC2\\xAF"
        "deg"       "\\xC2\\xB0"
        "plusmn"    "\\xC2\\xB1"
        "sup2"      "\\xC2\\xB2"
        "sup3"      "\\xC2\\xB3"
        "acute"     "\\xC2\\xB4"
        "micro"     "\\xC2\\xB5"
        "para"      "\\xC2\\xB6"
        "middot"    "\\xC2\\xB7"
        "cedil"     "\\xC2\\xB8"
        "sup1"      "\\xC2\\xB9"
        "ordm"      "\\xC2\\xBA"
        "raquo"     "\\xC2\\xBB"
        "frac14"    "\\xC2\\xBC"
        "frac12"    "\\xC2\\xBD"
        "frac34"    "\\xC2\\xBE"
        "iquest"    "\\xC2\\xBF"
        "Agrave"    "\\xC3\\x80"
        "Aacute"    "\\xC3\\x81"
        "Acirc"     "\\xC3\\x82"
        "Atilde"    "\\xC3\\x83"
        "Auml"      "\\xC3\\x84"
        "Aring"     "\\xC3\\x85"
        "AElig"     "\\xC3\\x86"
        "Ccedil"    "\\xC3\\x87"
        "Egrave"    "\\xC3\\x88"
        "Eacute"    "\\xC3\\x89"
        "Ecirc"     "\\xC3\\x8A"
        "Euml"      "\\xC3\\x8B"
        "Igrave"    "\\xC3\\x8C"
        "Iacute"    "\\xC3\\x8D"
        "Icirc"     "\\xC3\\x8E"
        "Iuml"      "\\xC3\\x8F"
        "ETH"       "\\xC3\\x90"
        "Ntilde"    "\\xC3\\x91"
        "Ograve"    "\\xC3\\x92"
        "Oacute"    "\\xC3\\x93"
        "Ocirc"     "\\xC3\\x94"
        "Otilde"    "\\xC3\\x95"
        "Ouml"      "\\xC3\\x96"
        "times"     "\\xC3\\x97"
        "Oslash"    "\\xC3\\x98"
        "Ugrave"    "\\xC3\\x99"
        "Uacute"    "\\xC3\\x9A"
        "Ucirc"     "\\xC3\\x9B"
        "Uuml"      "\\xC3\\x9C"
        "Yacute"    "\\xC3\\x9D"
        "THORN"     "\\xC3\\x9E"
        "szlig"     "\\xC3\\x9F"
        "agrave"    "\\xC3\\xA0"
        "aacute"    "\\xC3\\xA1"
        "acirc"     "\\xC3\\xA2"
        "atilde"    "\\xC3\\xA3"
        "auml"      "\\xC3\\xA4"
        "aring"     "\\xC3\\xA5"
        "aelig"     "\\xC3\\xA6"
        "ccedil"    "\\xC3\\xA7"
        "egrave"    "\\xC3\\xA8"
        "eacute"    "\\xC3\\xA9"
        "ecirc"     "\\xC3\\xAA"
        "euml"      "\\xC3\\xAB"
        "igrave"    "\\xC3\\xAC"
        "iacute"    "\\xC3\\xAD"
        "icirc"     "\\xC3\\xAE"
        "iuml"      "\\xC3\\xAF"
        "eth"       "\\xC3\\xB0"
        "ntilde"    "\\xC3\\xB1"
        "ograve"    "\\xC3\\xB2"
        "oacute"    "\\xC3\\xB3"
        "ocirc"     "\\xC3\\xB4"
        "otilde"    "\\xC3\\xB5"
        "ouml"      "\\xC3\\xB6"
        "divide"    "\\xC3\\xB7"
        "oslash"    "\\xC3\\xB8"
        "ugrave"    "\\xC3\\xB9"
        "uacute"    "\\xC3\\xBA"
        "ucirc"     "\\xC3\\xBB"
        "uuml"      "\\xC3\\xBC"
        "yacute"    "\\xC3\\xBD"
        "thorn"     "\\xC3\\xBE"
        "yuml"      "\\xC3\\xBF"
        "OElig"     "\\xC5\\x92"
        "oelig"     "\\xC5\\x93"
        "Scaron"    "\\xC5\\xA0"
        "scaron"    "\\xC5\\xA1"
        "Yuml"      "\\xC5\\xB8"
        "circ"      "\\xCB\\x86"
        "tilde"     "\\xCB\\x9C"
        "ensp"      "\\xE2\\x80\\x82"
        "emsp"      "\\xE2\\x80\\x83"
        "thinsp"    "\\xE2\\x80\\x89"
        "zwnj"      "\\xE2\\x81\\xB0"
        "zwj"       "\\xE2\\x80\\x8D"
        "lrm"       "\\xE2\\x80\\x8E"
        "rlm"       "\\xE2\\x80\\x8F"
        "ndash"     "\\xE2\\x80\\x93"
        "mdash"     "\\xE2\\x80\\x94"
        "lsquo"     "\\xE2\\x80\\x98"
        "rsquo"     "\\xE2\\x80\\x99"
        "sbquo"     "\\xE2\\x80\\x9A"
        "ldquo"     "\\xE2\\x80\\x9C"
        "rdquo"     "\\xE2\\x80\\x9D"
        "bdquo"     "\\xE2\\x80\\x9E"
        "dagger"    "\\xE2\\x80\\xA0"
        "Dagger"    "\\xE2\\x80\\xA1"
        "permil"    "\\xE2\\x80\\xB0"
        "lsaquo"    "\\xE2\\x80\\xB9"
        "rsaquo"    "\\xE2\\x80\\xBA"
        "euro"      "\\xE2\\x82\\xAC"
        "fnof"      "\\xC6\\x92"
        "Alpha"     "\\xCE\\x91"
        "Beta"      "\\xCE\\x92"
        "Gamma"     "\\xCE\\x93"
        "Delta"     "\\xCE\\x94"
        "Epsilon"   "\\xCE\\x95"
        "Zeta"      "\\xCE\\x96"
        "Eta"       "\\xCE\\x97"
        "Theta"     "\\xCE\\x98"
        "Iota"      "\\xCE\\x99"
        "Kappa"     "\\xCE\\x9A"
        "Lambda"    "\\xCE\\x9B"
        "Mu"        "\\xCE\\x9C"
        "Nu"        "\\xCE\\x9D"
        "Xi"        "\\xCE\\x9E"
        "Omicron"   "\\xCE\\x9F"
        "Pi"        "\\xCE\\xA0"
        "Rho"       "\\xCE\\xA1"
        "Sigma"     "\\xCE\\xA3"
        "Tau"       "\\xCE\\xA4"
        "Upsilon"   "\\xCE\\xA5"
        "Phi"       "\\xCE\\xA6"
        "Chi"       "\\xCE\\xA7"
        "Psi"       "\\xCE\\xA8"
        "Omega"     "\\xCE\\xA9"
        "alpha"     "\\xCE\\xB1"
        "beta"      "\\xCE\\xB2"
        "gamma"     "\\xCE\\xB3"
        "delta"     "\\xCE\\xB4"
        "epsilon"   "\\xCE\\xB5"
        "zeta"      "\\xCE\\xB6"
        "eta"       "\\xCE\\xB7"
        "theta"     "\\xCE\\xB8"
        "iota"      "\\xCE\\xB9"
        "kappa"     "\\xCE\\xBA"
        "lambda"    "\\xCE\\xBB"
        "mu"        "\\xCE\\xBC"
        "nu"        "\\xCE\\xBD"
        "xi"        "\\xCE\\xBE"
        "omicron"   "\\xCE\\xBF"
        "pi"        "\\xCF\\x80"
        "rho"       "\\xCF\\x81"
        "sigmaf"    "\\xCF\\x82"
        "sigma"     "\\xCF\\x83"
        "tau"       "\\xCF\\x84"
        "upsilon"   "\\xCF\\x85"
        "phi"       "\\xCF\\x86"
        "chi"       "\\xCF\\x87"
        "psi"       "\\xCF\\x88"
        "omega"     "\\xCF\\x89"
        "thetasym"  "\\xCF\\x91"
        "upsih"     "\\xCF\\x92"
        "piv"       "\\xCF\\x96"
        "bull"      "\\xE2\\x80\\xA2"
        "hellip"    "\\xE2\\x80\\xA6"
        "prime"     "\\xE2\\x80\\xB2"
        "Prime"     "\\xE2\\x80\\xB3"
        "oline"     "\\xE2\\x80\\xBE"
        "frasl"     "\\xE2\\x81\\x84"
        "weierp"    "\\xE2\\x84\\x98"
        "image"     "\\xE2\\x84\\x91"
        "real"      "\\xE2\\x84\\x9C"
        "trade"     "\\xE2\\x84\\xA2"
        "alefsym"   "\\xE2\\x84\\xB5"
        "larr"      "\\xE2\\x86\\x90"
        "uarr"      "\\xE2\\x86\\x91"
        "rarr"      "\\xE2\\x86\\x92"
        "darr"      "\\xE2\\x86\\x93"
        "harr"      "\\xE2\\x86\\x94"
        "crarr"     "\\xE2\\x86\\xB5"
        "lArr"      "\\xE2\\x87\\x90"
        "uArr"      "\\xE2\\x87\\x91"
        "rArr"      "\\xE2\\x87\\x92"
        "dArr"      "\\xE2\\x87\\x93"
        "hArr"      "\\xE2\\x87\\x94"
        "forall"    "\\xE2\\x88\\x80"
        "part"      "\\xE2\\x88\\x82"
        "exist"     "\\xE2\\x88\\x83"
        "empty"     "\\xE2\\x88\\x85"
        "nabla"     "\\xE2\\x88\\x87"
        "isin"      "\\xE2\\x88\\x88"
        "notin"     "\\xE2\\x88\\x89"
        "ni"        "\\xE2\\x88\\x8B"
        "prod"      "\\xE2\\x88\\x8F"
        "sum"       "\\xE2\\x88\\x91"
        "minus"     "\\xE2\\x88\\x92"
        "lowast"    "\\xE2\\x88\\x97"
        "radic"     "\\xE2\\x88\\x9A"
        "prop"      "\\xE2\\x88\\x9D"
        "infin"     "\\xE2\\x88\\x9E"
        "ang"       "\\xE2\\x88\\xA0"
        "and"       "\\xE2\\x88\\xA7"
        "or"        "\\xE2\\x88\\xA8"
        "cap"       "\\xE2\\x88\\xA9"
        "cup"       "\\xE2\\x88\\xAA"
        "int"       "\\xE2\\x88\\xAB"
        "there4"    "\\xE2\\x88\\xB4"
        "sim"       "\\xE2\\x88\\xBC"
        "cong"      "\\xE2\\x89\\x85"
        "asymp"     "\\xE2\\x89\\x88"
        "ne"        "\\xE2\\x89\\xA0"
        "equiv"     "\\xE2\\x89\\xA1"
        "le"        "\\xE2\\x89\\xA4"
        "ge"        "\\xE2\\x89\\xA5"
        "sub"       "\\xE2\\x8A\\x82"
        "sup"       "\\xE2\\x8A\\x83"
        "nsub"      "\\xE2\\x8A\\x84"
        "sube"      "\\xE2\\x8A\\x86"
        "supe"      "\\xE2\\x8A\\x87"
        "oplus"     "\\xE2\\x8A\\x95"
        "otimes"    "\\xE2\\x8A\\x97"
        "perp"      "\\xE2\\x8A\\xA5"
        "sdot"      "\\xE2\\x8B\\x85"
        "lceil"     "\\xE2\\x8C\\x88"
        "rceil"     "\\xE2\\x8C\\x89"
        "lfloor"    "\\xE2\\x8C\\x8A"
        "rfloor"    "\\xE2\\x8C\\x8B"
        "lang"      "\\xE2\\x8C\\xA9"
        "rang"      "\\xE2\\x8C\\xAA"
        "loz"       "\\xE2\\x97\\x8A"
        "spades"    "\\xE2\\x99\\xA0"
        "clubs"     "\\xE2\\x99\\xA3"
        "hearts"    "\\xE2\\x99\\xA5"
        "diams"     "\\xE2\\x99\\xA6"
    } {
        set html "<html><body>&$entity;</body></html>"
        set doc [dom parse -html $html]
        set root [$doc documentElement]
        set body [$root firstChild]
        if {[toutf8 [$body text]] ne [string tolower $byteseq]} {
            lappend result $entity [toutf8 [$body text]] [string tolower $byteseq]
        }
        $doc delete
    }
    set result
} ""


test html-2.1 {not closed p tags} {
    set doc [dom parse -html {
        <html><body><p>Para 1<p>Para 2<p>Para 3</body></html>
    }]
    set result [$doc asXML -indent none]
    $doc delete
    set result
} {<html><body><p>Para 1</p><p>Para 2</p><p>Para 3</p></body></html>}

test html-2.2 {HTML parsing} {
    set doc [dom parse -html {
        <HTML><HEAD></HEAD>
        <BODY>
        <H1>HTML</H1>
        </BODY>
        </HTML>
    }]
    set result [$doc asXML -indent none]
    $doc delete
    set result
} {<html><head/><body><h1>HTML</h1></body></html>}

test html-2.3 {HTML parsing} {
    set doc [dom parse -html {
        <!-- comment -->
        <HTML><HEAD></HEAD>
        <BODY>
        <H1>HTML</H1>
        </BODY>
        </HTML>
    }]
    set result [$doc asXML -indent none]
    $doc delete
    set result
} {<!-- comment --><html><head/><body><h1>HTML</h1></body></html>}

test html-2.4 {HTML parsing} {
    set doc [dom parse -html {
        <!-- comment -->
        <HTML><HEAD></HEAD>
        <BODY>
        <H1>HTML</H1>
        </BODY>
        </HTML>
        <!-- comment -->
    }]
    $doc documentElement root
    set result [$root nodeName]
    $doc delete
    set result
} {html}

test html-2.5 {HTML parsing} {
    set doc [dom parse -html {<html> <head><title></title></head><body>
        <form>
        <select id="L" name="nls_language">
        <option value="">--</option>
        <option value="en_US" selected="on">en_US</option>
        <option value="es_ES">es_ES</option>
        <option value="de_DE">de_DE</option>
        </select>
        </form>
        </body></html>
    }]
    $doc asHTML
} {<html>
<head><title></title></head><body><form><select id="L" name="nls_language">
<option value="">--</option><option value="en_US" selected="on">en_US</option><option value="es_ES">es_ES</option><option value="de_DE">de_DE</option>
</select></form></body>
</html>}

test html-2.6 {HTML parsing} {
    set doc [dom parse -html {<html> <head><title></title></head><body>
        <form>
        <select id="L" name="nls_language">
        <option value="">--
        <option value="en_US" selected="on">en_US
        <option value="es_ES">es_ES
        <option value="de_DE">de_DE
        </select>
        </form>
        </body></html>
    }]
    $doc asHTML
} {<html>
<head><title></title></head><body><form><select id="L" name="nls_language">
<option value="">--
        </option><option value="en_US" selected="on">en_US
        </option><option value="es_ES">es_ES
        </option><option value="de_DE">de_DE
        </option>
</select></form></body>
</html>}

test html-2.7 {HTML parsing} {
    set doc [dom parse -html {<html> <head><title></title></head><body>
        <form>
        <select id="L" name="nls_language">
        <option value="">--
        <option value="en_US" selected>en_US
        <option value="de_DE">de_DE
        </select>
        </form>
        </body></html>
    }]
    $doc asHTML
} {<html>
<head><title></title></head><body><form><select id="L" name="nls_language">
<option value="">--
        </option><option value="en_US" selected="selected">en_US
        </option><option value="de_DE">de_DE
        </option>
</select></form></body>
</html>}

test html-2.8 {HTML parsing} {
    set doc [dom parse -html {<html> <head><title></title></head><body>
        <form>
        <select id="L" name="nls_language">
        <option value="">--
        <option selected value="en_US">en_US
        <option value="de_DE">de_DE
        </select>
        </form>
        </body></html>
    }]
    $doc asHTML
} {<html>
<head><title></title></head><body><form><select id="L" name="nls_language">
<option value="">--
        </option><option selected="selected" value="en_US">en_US
        </option><option value="de_DE">de_DE
        </option>
</select></form></body>
</html>}

test html-3.1 {Bad data} {
    set data {line 6 column 17 - Warning: <script> lacks "type" attribute
line 10 column 17 - Warning: <script> lacks "type" attribute
        line 11 column 17 - Warning: <table> lacks "summary" attribute}
    set doc [dom parse -html $data]
    set result [$doc asHTML]
    $doc delete
    set result
} {<html><script></script></html>}

test html-3.2 {Bad data} {
    set doc [dom parse -html {<a>}]
    set result [$doc asHTML]
    $doc delete
    set result
} {<html><a></a></html>}
        
test html-4.1 {Tag name case normalization} {
    set doc [dom parse -html {<HtmL><boDY></BODy></HTml>}]
    set result [$doc asHTML]
    $doc delete
    set result
} {<html><body></body></html>}

test html-4.2 {Tag name case normalization} {knownBug} {
    set doc [dom parse -html {<HtmL><NotaHTML_Tag/></HTml>}]
    set result [$doc asHTML]
    $doc delete
    set result
} {<html><body></body></html>}

test html-4.3 {Attribute name case normalization} {
    set doc [dom parse -html {<HtmL><Body Id=3 FOO=Bar GriLL></body></html>}]
    set result [$doc asHTML]
    $doc delete
    set result
} {<html><body id="3" foo="Bar" grill="grill"></body></html>}

test html-4.4 {ID Attribute handling} {
    set doc [dom parse -html {<HtmL><p ID=1 f00=bar/><p id="2"/><p/></html>}]
    set result [[$doc getElementById 1] getAttribute id]
    $doc delete
    set result
} {1}


# cleanup
::tcltest::cleanupTests
return
