1+ using Bunit . TestAssets . XunitExtensions ;
12using AngleSharp . Dom ;
3+ using AngleSharp . Html . Dom ;
24
35namespace Bunit . Rendering ;
46
@@ -9,26 +11,47 @@ public class BunitHtmlParserTest
911 /// <summary>
1012 /// All HTML5 elements according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element.
1113 /// </summary>
12- public static readonly IEnumerable < object [ ] > BodyHtmlElements = new [ ]
14+ public static readonly TheoryData < string > BodyHtmlElements = new TheoryData < string >
1315 {
14- "base" , "link" , "meta" , "style" , "title" ,
15- "address" , "article" , "aside" , "footer" , "header" , "h1" , "h2" , "h3" , "h4" , "h5" , "h6" , "hgroup" , "main" , "nav" , "section" ,
16- "blockquote" , "dd" , "div" , "dl" , "dt" , "figcaption" , "figure" , "hr" , "li" , "ol" , "p" , "pre" , "ul" ,
17- "a" , "abbr" , "b" , "bdi" , "bdo" , "br" , "cite" , "code" , "data" , "dfn" , "em" , "i" , "kbd" , "mark" , "q" , "rb" , "rp" , "rt" , "rtc" , "ruby" , "s" , "samp" , "small" , "span" , "strong" , "sub" , "sup" , "time" , "u" , "var" , "wbr" ,
18- "area" , "audio" , "img" , "map" , "track" , "video" ,
19- "embed" , "iframe" , "object" , "param" , "picture" , "source" ,
20- "canvas" , "noscript" , "script" ,
21- "del" , "ins" ,
22- "caption" , "col" , "colgroup" , "table" , "tbody" , "td" , "tfoot" , "th" , "thead" , "tr" ,
23- "button" , "datalist" , "fieldset" , "form" , "input" , "label" , "legend" , "meter" , "optgroup" , "option" , "output" , "progress" , "select" , "textarea" ,
24- "details" , "dialog" , "menu" , "summary" ,
25- "slot" , "template" ,
26- "acronym" , "applet" , "basefont" , "bgsound" , "big" , "blink" , "center" , "command" , "content" , "dir" , "element" , "font" , "keygen" , "listing" , "marquee" , "menuitem" , "multicol" , "nextid" , "nobr" , "noembed" , "noframes" , "plaintext" , "shadow" , "spacer" , "strike" , "tt" , "xmp" ,
27- // "frame","frameset","image","isindex" // not supported
28- } . Select ( x => new [ ] { x } ) ;
29-
30- public static readonly IEnumerable < object [ ] > BodyHtmlAndSpecialElements = BodyHtmlElements . Concat (
31- new [ ] { "html" , "head" , "body" , } . Select ( x => new [ ] { x } ) ) ;
16+ "base" , "link" , "meta" , "style" , "title" ,
17+ "address" , "article" , "aside" , "footer" , "header" , "h1" , "h2" , "h3" , "h4" , "h5" , "h6" , "hgroup" , "main" , "nav" , "section" ,
18+ "blockquote" , "dd" , "div" , "dl" , "dt" , "figcaption" , "figure" , "hr" , "li" , "ol" , "p" , "pre" , "ul" ,
19+ "a" , "abbr" , "b" , "bdi" , "bdo" , "br" , "cite" , "code" , "data" , "dfn" , "em" , "i" , "kbd" , "mark" , "q" , "rb" , "rp" , "rt" , "rtc" , "ruby" , "s" , "samp" , "small" , "span" , "strong" , "sub" , "sup" , "time" , "u" , "var" , "wbr" ,
20+ "area" , "audio" , "img" , "map" , "track" , "video" , "svg" ,
21+ "embed" , "iframe" , "object" , "param" , "picture" , "source" ,
22+ "canvas" , "noscript" , "script" ,
23+ "del" , "ins" ,
24+ "caption" , "col" , "colgroup" , "table" , "tbody" , "td" , "tfoot" , "th" , "thead" , "tr" ,
25+ "button" , "datalist" , "fieldset" , "form" , "input" , "label" , "legend" , "meter" , "optgroup" , "option" , "output" , "progress" , "select" , "textarea" ,
26+ "details" , "dialog" , "menu" , "summary" ,
27+ "slot" , "template" ,
28+ "acronym" , "applet" , "basefont" , "bgsound" , "big" , "blink" , "center" , "command" , "content" , "dir" , "element" , "font" , "keygen" , "listing" , "marquee" , "menuitem" , "multicol" , "nextid" , "nobr" , "noembed" , "noframes" , "plaintext" , "shadow" , "spacer" , "strike" , "tt" , "xmp" ,
29+ // "frame","frameset","image","isindex" // not supported
30+ } ;
31+
32+ public static readonly IEnumerable < object [ ] > BodyHtmlAndSpecialElements = BodyHtmlElements
33+ . Clone ( )
34+ . AddRange ( "html" , "head" , "body" ) ;
35+
36+ public static readonly TheoryData < string > SvgElements = new TheoryData < string >
37+ {
38+ "animate" , "animateMotion" , "animateTransform" ,
39+ "circle" , "clipPath" ,
40+ "defs" , "desc" , "discard" ,
41+ "ellipse" ,
42+ "feBlend" , "feColorMatrix" , "feComponentTransfer" , "feComposite" , "feConvolveMatrix" , "feDiffuseLighting" , "feDisplacementMap" , "feDistantLight" , "feDropShadow" , "feFlood" , "feFuncA" , "feFuncB" , "feFuncG" , "feFuncR" , "feGaussianBlur" , "feImage" , "feMerge" , "feMergeNode" , "feMorphology" , "feOffset" , "fePointLight" , "feSpecularLighting" , "feSpotLight" , "feTile" , "feTurbulence" , "filter" , "foreignObject" ,
43+ "g" ,
44+ "hatch" , "hatchpath" ,
45+ "line" , "linearGradient" ,
46+ "marker" , "mask" , "metadata" , "mpath" ,
47+ "path" , "pattern" , "polygon" , "polyline" ,
48+ "radialGradient" , "rect" ,
49+ "set" , "stop" , "switch" , "symbol" ,
50+ "text" , "textPath" , "tspan" ,
51+ "use" ,
52+ "view"
53+ // "a", "image", "script", "svg", "title", "style" removed since they overlap with HTML elements
54+ } ;
3255
3356 [ Fact ( DisplayName = "Parse() called with null" ) ]
3457 public void ParseCalledWithNull ( )
@@ -46,7 +69,7 @@ public void ParseWithWhitespaceOnly(string text)
4669 actual . ShouldHaveSingleItem ( ) . TextContent . ShouldBe ( text ) ;
4770 }
4871
49- [ Theory ( DisplayName = "Parse() passed <TAG id=TAG>" ) ]
72+ [ Theory ( DisplayName = "Parse() parses <TAG id=TAG>" ) ]
5073 [ MemberData ( nameof ( BodyHtmlAndSpecialElements ) ) ]
5174 public void Test001 ( string elementName )
5275 {
@@ -55,7 +78,7 @@ public void Test001(string elementName)
5578 VerifyElementParsedWithId ( elementName , actual ) ;
5679 }
5780
58- [ Theory ( DisplayName = "Parse() passed <TAG> with whitespace before" ) ]
81+ [ Theory ( DisplayName = "Parse() parses <TAG> with whitespace before" ) ]
5982 [ MemberData ( nameof ( BodyHtmlElements ) ) ]
6083 public void Test002 ( string elementName )
6184 {
@@ -64,7 +87,7 @@ public void Test002(string elementName)
6487 VerifyElementParsedWithId ( elementName , actual ) ;
6588 }
6689
67- [ Theory ( DisplayName = "Parse() passed <TAG>" ) ]
90+ [ Theory ( DisplayName = "Parse() parses <TAG>" ) ]
6891 [ MemberData ( nameof ( BodyHtmlElements ) ) ]
6992 public void Test003 ( string elementName )
7093 {
@@ -75,7 +98,7 @@ public void Test003(string elementName)
7598 . NodeName . ShouldBe ( elementName , StringCompareShould . IgnoreCase ) ;
7699 }
77100
78- [ Theory ( DisplayName = "Parse() passed <TAG/>" ) ]
101+ [ Theory ( DisplayName = "Parse() parses <TAG/>" ) ]
79102 [ MemberData ( nameof ( BodyHtmlElements ) ) ]
80103 public void Test004 ( string elementName )
81104 {
@@ -86,28 +109,43 @@ public void Test004(string elementName)
86109 . NodeName . ShouldBe ( elementName , StringCompareShould . IgnoreCase ) ;
87110 }
88111
89- [ Theory ( DisplayName = "Parse() passed <TAG ..." ) ]
112+ [ Theory ( DisplayName = "Parse() parses <TAG ..." ) ]
90113 [ MemberData ( nameof ( BodyHtmlElements ) ) ]
91114 public void Test005 ( string elementName )
92115 {
93116 var input = $@ " <{ elementName } foo bar { '\t ' } { Environment . NewLine } ";
94117 var actual = Parser . Parse ( input ) . ToList ( ) ;
95118
96119 actual . ShouldHaveSingleItem ( )
120+ . ShouldBeAssignableTo < IText > ( )
97121 . TextContent . ShouldBe ( " " ) ;
98122 }
99123
100- [ Theory ( DisplayName = "Parse() passed <TAG .../" ) ]
124+ [ Theory ( DisplayName = "Parse() parses <TAG .../" ) ]
101125 [ MemberData ( nameof ( BodyHtmlElements ) ) ]
102126 public void Test006 ( string elementName )
103127 {
104128 var input = $@ " <{ elementName } / ";
105129 var actual = Parser . Parse ( input ) . ToList ( ) ;
106130
107131 actual . ShouldHaveSingleItem ( )
132+ . ShouldBeAssignableTo < IText > ( )
108133 . TextContent . ShouldBe ( " " ) ;
109134 }
110135
136+ [ Theory ( DisplayName = "Parse() parses SVG element <TAG>" ) ]
137+ [ MemberData ( nameof ( SvgElements ) ) ]
138+ public void Test020 ( string elementName )
139+ {
140+ var actual = Parser . Parse ( $@ "<{ elementName } >") . ToList ( ) ;
141+
142+ // SVG elements that are parsed outside of a SVG parent element will
143+ // be returned as an IHtmlUnknownElement, which is precise enough for our need.
144+ actual . ShouldHaveSingleItem ( )
145+ . ShouldBeAssignableTo < IHtmlUnknownElement > ( )
146+ . NodeName . ShouldBe ( elementName , StringCompareShould . IgnoreCase ) ;
147+ }
148+
111149 private static void VerifyElementParsedWithId ( string expectedElementName , List < INode > actual )
112150 {
113151 var elm = actual . OfType < IElement > ( )
0 commit comments