View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.xml;
16  
17  import java.net.URL;
18  
19  import org.htmlunit.MockWebConnection;
20  import org.htmlunit.WebDriverTestCase;
21  import org.htmlunit.junit.annotation.Alerts;
22  import org.htmlunit.junit.annotation.HtmlUnitNYI;
23  import org.htmlunit.util.MimeType;
24  import org.junit.jupiter.api.Test;
25  import org.openqa.selenium.WebDriver;
26  
27  /**
28   * Tests for {@link XMLSerializer}.
29   *
30   * @author Ahmed Ashour
31   * @author Darrell DeBoer
32   * @author Frank Danek
33   * @author Ronald Brill
34   * @author Michael Anstis
35   */
36  public class XMLSerializerTest extends WebDriverTestCase {
37  
38      /**
39       * @throws Exception if the test fails
40       */
41      @Test
42      @Alerts("<note>32<to>Tove</to>3210<from>Jani</from>321032<body>Do32not32forget32me32this32weekend!</body>"
43                      + "32<outer>10323232<inner>Some32Value</inner></outer>32</note>")
44      public void test() throws Exception {
45          final String expectedString = getExpectedAlerts()[0];
46          setExpectedAlerts();
47          final String serializationText =
48                  "<note> "
49                  + "<to>Tove</to> \\n"
50                  + "<from>Jani</from> \\n "
51                  + "<body>Do not forget me this weekend!</body> "
52                  + "<outer>\\n "
53                  + "  <inner>Some Value</inner>"
54                  + "</outer> "
55                  + "</note>";
56  
57          final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
58          verifyTextArea2(driver, expectedString);
59      }
60  
61      /**
62       * @throws Exception if the test fails
63       */
64      @Test
65      @Alerts("<a><!--32abc32--></a>")
66      public void comment() throws Exception {
67          final String expectedString = getExpectedAlerts()[0];
68          setExpectedAlerts();
69          final String serializationText = "<a><!-- abc --></a>";
70          final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
71          verifyTextArea2(driver, expectedString);
72      }
73  
74      /**
75       * @throws Exception if the test fails
76       */
77      @Test
78      @Alerts("<a>&lt;&gt;&amp;</a>")
79      public void xmlEntities() throws Exception {
80          final String expectedString = getExpectedAlerts()[0];
81          setExpectedAlerts();
82          final String serializationText = "<a>&lt;&gt;&amp;</a>";
83          final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
84          verifyTextArea2(driver, expectedString);
85      }
86  
87      /**
88       * @throws Exception if the test fails
89       */
90      @Test
91      @Alerts(DEFAULT = "<?xml32version=\"1.0\"32encoding=\"UTF-8\"?>1310<xsl:stylesheet32version=\"1.0\"32"
92                      + "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">103232<xsl:template32match=\"/\">103232<html>"
93                      + "1032323232<body>1032323232</body>103232</html>103232</xsl:template>10</xsl:stylesheet>",
94              CHROME = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><xsl:stylesheet32xmlns:xsl="
95                      + "\"http://www.w3.org/1999/XSL/Transform\"32version=\"1.0\">103232<xsl:template32"
96                      + "match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>103232"
97                      + "</xsl:template>10</xsl:stylesheet>",
98              EDGE = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><xsl:stylesheet32xmlns:xsl="
99                      + "\"http://www.w3.org/1999/XSL/Transform\"32version=\"1.0\">103232<xsl:template32"
100                     + "match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>103232"
101                     + "</xsl:template>10</xsl:stylesheet>")
102     @HtmlUnitNYI(CHROME = "<xsl:stylesheet32version=\"1.0\"32xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
103                     + "103232<xsl:template32match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>"
104                     + "103232</xsl:template>10</xsl:stylesheet>",
105             EDGE = "<xsl:stylesheet32version=\"1.0\"32xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
106                     + "103232<xsl:template32match=\"/\">103232<html>1032323232<body>1032323232</body>103232</html>"
107                     + "103232</xsl:template>10</xsl:stylesheet>",
108             FF_ESR = "<xsl:stylesheet32version=\"1.0\"32"
109                     + "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">103232<xsl:template32match=\"/\">103232<html>"
110                     + "1032323232<body>1032323232</body>103232</html>103232</xsl:template>10</xsl:stylesheet>",
111             FF = "<xsl:stylesheet32version=\"1.0\"32"
112                     + "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">103232<xsl:template32match=\"/\">103232<html>"
113                     + "1032323232<body>1032323232</body>103232</html>103232</xsl:template>10</xsl:stylesheet>")
114     public void nameSpaces() throws Exception {
115         final String expectedString = getExpectedAlerts()[0];
116         setExpectedAlerts();
117         final String serializationText =
118                 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\\n"
119                 + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\\n"
120                 + "  <xsl:template match=\"/\">\\n"
121                 + "  <html>\\n"
122                 + "    <body>\\n"
123                 + "    </body>\\n"
124                 + "  </html>\\n"
125                 + "  </xsl:template>\\n"
126                 + "</xsl:stylesheet>";
127 
128         final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
129         verifyTextArea2(driver, expectedString);
130     }
131 
132     /**
133      * @throws Exception if the test fails
134      */
135     @Test
136     @Alerts("<document32attrib=\"attribValue\"><outer32attrib=\"attribValue\">"
137                 + "<inner32attrib=\"attribValue\"/><meta32attrib=\"attribValue\"/></outer></document>")
138     public void attributes() throws Exception {
139         final String expectedString = getExpectedAlerts()[0];
140         setExpectedAlerts();
141         final String serializationText = "<document attrib=\"attribValue\">"
142                                             + "<outer attrib=\"attribValue\">"
143                                             + "<inner attrib=\"attribValue\"/>"
144                                             + "<meta attrib=\"attribValue\"/>"
145                                             + "</outer></document>";
146 
147         final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
148         verifyTextArea2(driver, expectedString);
149     }
150 
151     /**
152      * @throws Exception if the test fails
153      */
154     @Test
155     @Alerts(DEFAULT = "<?xml32version=\"1.0\"32encoding=\"UTF-8\"?>1310<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
156                     + "<head><title>html</title></head>"
157                     + "<body32id=\"bodyId\">"
158                     + "<span32class=\"spanClass\">foo</span>"
159                     + "</body>"
160                     + "</html>",
161             CHROME = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><html32xmlns=\"http://www.w3.org/1999/xhtml\">"
162                     + "<head><title>html</title></head>"
163                     + "<body32id=\"bodyId\">"
164                     + "<span32class=\"spanClass\">foo</span>"
165                     + "</body>"
166                     + "</html>",
167             EDGE = "<?xml32version=\"1.0\"32encoding=\"ISO-8859-1\"?><html32xmlns=\"http://www.w3.org/1999/xhtml\">"
168                     + "<head><title>html</title></head>"
169                     + "<body32id=\"bodyId\">"
170                     + "<span32class=\"spanClass\">foo</span>"
171                     + "</body>"
172                     + "</html>")
173     @HtmlUnitNYI(CHROME = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
174                     + "<head><title>html</title></head>"
175                     + "<body32id=\"bodyId\">"
176                     + "<span32class=\"spanClass\">foo</span>"
177                     + "</body>"
178                     + "</html>",
179             EDGE = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
180                     + "<head><title>html</title></head>"
181                     + "<body32id=\"bodyId\">"
182                     + "<span32class=\"spanClass\">foo</span>"
183                     + "</body>"
184                     + "</html>",
185             FF_ESR = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
186                     + "<head><title>html</title></head>"
187                     + "<body32id=\"bodyId\">"
188                     + "<span32class=\"spanClass\">foo</span>"
189                     + "</body>"
190                     + "</html>",
191             FF = "<html32xmlns=\"http://www.w3.org/1999/xhtml\">"
192                     + "<head><title>html</title></head>"
193                     + "<body32id=\"bodyId\">"
194                     + "<span32class=\"spanClass\">foo</span>"
195                     + "</body>"
196                     + "</html>")
197     public void htmlAttributes() throws Exception {
198         final String expectedString = getExpectedAlerts()[0];
199         setExpectedAlerts();
200         final String serializationText = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
201                                           + "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
202                                           + "<head><title>html</title></head>"
203                                           + "<body id=\"bodyId\">"
204                                           + "<span class=\"spanClass\">foo</span>"
205                                           + "</body>"
206                                           + "</html>";
207 
208         final WebDriver driver = loadPageVerifyTitle2(constructPageContent(serializationText));
209         verifyTextArea2(driver, expectedString);
210     }
211 
212     /**
213      * Constructs an HTML page that when loaded will parse and serialize the provided text.
214      * First the provided text is parsed into a Document. Then the Document is serialized (browser-specific).
215      * Finally the result is placed into the text area "myTextArea".
216      */
217     private static String constructPageContent(final String serializationText) {
218         final String escapedText = serializationText.replace("\n", "\\n");
219 
220         final StringBuilder builder = new StringBuilder();
221         builder.append(
222               "<html><head>\n"
223             + "<script>\n"
224             + LOG_TITLE_FUNCTION
225             + "  function test() {\n");
226 
227         builder.append("    var text = '").append(escapedText).append("';\n").append(
228               "    var doc = " + XMLDocumentTest.callLoadXMLDocumentFromString("text") + ";\n"
229             + "    var xml = " + XMLDocumentTest.callSerializeXMLDocumentToString("doc") + ";\n"
230             + "    var ta = document.getElementById('myLog');\n"
231             + "    for (var i = 0; i < xml.length; i++) {\n"
232             + "      if (xml.charCodeAt(i) < 33)\n"
233             + "        ta.value += xml.charCodeAt(i);\n"
234             + "      else\n"
235             + "        ta.value += xml.charAt(i);\n"
236             + "    }\n"
237             + "    ta.value += '\\u00a7';\n"
238             + "  }\n"
239             + XMLDocumentTest.LOAD_XML_DOCUMENT_FROM_STRING_FUNCTION
240             + XMLDocumentTest.SERIALIZE_XML_DOCUMENT_TO_STRING_FUNCTION
241             + "</script></head><body onload='test()'>\n"
242             + LOG_TEXTAREA
243             + "</body></html>");
244         return builder.toString();
245     }
246 
247     /**
248      * @throws Exception if the test fails
249      */
250     @Test
251     @Alerts({"<html xmlns=\"http://www.w3.org/1999/xhtml\"><body id=\"bodyId\"></body></html>",
252              "<html xmlns=\"http://www.w3.org/1999/xhtml\"><body id=\"bodyId\"></body></html>"})
253     @HtmlUnitNYI(CHROME = {"<html><body id=\"bodyId\"></body></html>",
254                            "<html><body id=\"bodyId\"></body></html>"},
255             EDGE = {"<html><body id=\"bodyId\"></body></html>",
256                     "<html><body id=\"bodyId\"></body></html>"},
257             FF = {"<html><body id=\"bodyId\"></body></html>",
258                   "<html><body id=\"bodyId\"></body></html>"},
259             FF_ESR = {"<html><body id=\"bodyId\"></body></html>",
260                       "<html><body id=\"bodyId\"></body></html>"})
261     public void xhtmlDocument() throws Exception {
262         final String html = DOCTYPE_HTML
263             + "<html><head>\n"
264             + "<script>\n"
265             + LOG_TITLE_FUNCTION
266             + "function test() {\n"
267             + "  var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);\n"
268             + "  var body = document.createElementNS('http://www.w3.org/1999/xhtml', 'body');\n"
269             + "  body.setAttribute('id', 'bodyId');\n"
270             + "  doc.documentElement.appendChild(body);"
271 
272             + "  log(new XMLSerializer().serializeToString(doc));\n"
273             + "  log(new XMLSerializer().serializeToString(doc.documentElement));\n"
274             + "}\n"
275             + "</script></head><body onload='test()'>\n"
276             + "</body></html>";
277         loadPageVerifyTitle2(html);
278     }
279 
280     /**
281      * @throws Exception if the test fails
282      */
283     @Test
284     @Alerts({"<html xmlns=\"http://www.w3.org/1999/xhtml\"><body xmlns=\"\" id=\"bodyId\"/></html>",
285              "<html xmlns=\"http://www.w3.org/1999/xhtml\"><body xmlns=\"\" id=\"bodyId\"/></html>"})
286     @HtmlUnitNYI(CHROME = {"<html><body id=\"bodyId\"></body></html>",
287                            "<html><body id=\"bodyId\"></body></html>"},
288             EDGE = {"<html><body id=\"bodyId\"></body></html>",
289                     "<html><body id=\"bodyId\"></body></html>"},
290             FF = {"<html><body id=\"bodyId\"></body></html>",
291                   "<html><body id=\"bodyId\"></body></html>"},
292             FF_ESR = {"<html><body id=\"bodyId\"></body></html>",
293                       "<html><body id=\"bodyId\"></body></html>"})
294     public void xhtmlDocumentBodyEmptyNamespace() throws Exception {
295         final String html = DOCTYPE_HTML
296             + "<html><head>\n"
297             + "<script>\n"
298             + LOG_TITLE_FUNCTION
299             + "function test() {\n"
300             + "  var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);\n"
301             + "  var body = document.createElementNS('', 'body');\n"
302             + "  body.setAttribute('id', 'bodyId');\n"
303             + "  doc.documentElement.appendChild(body);"
304 
305             + "  log(new XMLSerializer().serializeToString(doc));\n"
306             + "  log(new XMLSerializer().serializeToString(doc.documentElement));\n"
307             + "}\n"
308             + "</script></head><body onload='test()'>\n"
309             + "</body></html>";
310         loadPageVerifyTitle2(html);
311     }
312 
313 
314     /**
315      * @throws Exception if the test fails
316      */
317     @Test
318     @Alerts({"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body/></soap:Envelope>",
319              "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body/></soap:Envelope>"})
320     @HtmlUnitNYI(CHROME = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
321                            "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"},
322             EDGE = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
323                     "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"},
324             FF = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
325                   "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"},
326             FF_ESR = {"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>",
327                       "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><Body></Body></soap:Envelope>"})
328     public void soapTest() throws Exception {
329         final String html = DOCTYPE_HTML
330             + "<html><head>\n"
331             + "<script>\n"
332             + LOG_TITLE_FUNCTION
333             + "function test() {\n"
334             + "  var dom = document.implementation.createDocument('http://schemas.xmlsoap.org/soap/envelope/', 'soap:Envelope', null);\n"
335 
336             + "  var soapEnv = dom.documentElement;\n"
337             + "  soapBody = dom.createElementNS('http://schemas.xmlsoap.org/soap/envelope/', 'Body');\n"
338             + "  soapEnv.appendChild(soapBody);"
339 
340             + "  log(new XMLSerializer().serializeToString(dom));\n"
341             + "  log(new XMLSerializer().serializeToString(dom.documentElement));\n"
342             + "}\n"
343             + "</script></head><body onload='test()'>\n"
344             + "</body></html>";
345         loadPageVerifyTitle2(html);
346     }
347 
348     /**
349      * @throws Exception if the test fails
350      */
351     @Test
352     @Alerts({"<foo/>", "<foo/>"})
353     public void document() throws Exception {
354         final String html = DOCTYPE_HTML
355             + "<html><head>\n"
356             + "<script>\n"
357             + LOG_TITLE_FUNCTION
358             + "function test() {\n"
359             + "  var doc = document.implementation.createDocument('', 'foo', null);\n"
360             + "  log(new XMLSerializer().serializeToString(doc));\n"
361             + "  log(new XMLSerializer().serializeToString(doc.documentElement));\n"
362             + "}\n"
363             + "</script></head><body onload='test()'>\n"
364             + "</body></html>";
365         loadPageVerifyTitle2(html);
366     }
367 
368     /**
369      * @throws Exception if the test fails
370      */
371     @Test
372     @Alerts("#")
373     public void emptyDocumentFragment() throws Exception {
374         final String html = DOCTYPE_HTML
375             + "<html><head>\n"
376             + "<script>\n"
377             + LOG_TITLE_FUNCTION
378             + "function test() {\n"
379             + "  var fragment = document.createDocumentFragment();\n"
380             + "  log('#' + new XMLSerializer().serializeToString(fragment));\n"
381             + "}\n"
382             + "</script></head><body onload='test()'>\n"
383             + "</body></html>";
384         loadPageVerifyTitle2(html);
385     }
386 
387     /**
388      * @throws Exception if the test fails
389      */
390     @Test
391     @Alerts("<h1 xmlns=\"http://www.w3.org/1999/xhtml\">HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\">is great</h2>")
392     @HtmlUnitNYI(CHROME = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>",
393             EDGE = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>",
394             FF = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>",
395             FF_ESR = "<h1 xmlns=\"http://www.w3.org/1999/xhtml\" >HtmlUnit</h1><h2 xmlns=\"http://www.w3.org/1999/xhtml\" >is great</h2>")
396     public void documentFragment() throws Exception {
397         final String html = DOCTYPE_HTML
398             + "<html><head>\n"
399             + "<script>\n"
400             + LOG_TITLE_FUNCTION
401             + "function test() {\n"
402             + "  var fragment = document.createDocumentFragment();\n"
403 
404             + "  var heading = document.createElement('h1');\n"
405             + "  heading.textContent = 'HtmlUnit';\n"
406             + "  fragment.appendChild(heading);\n"
407 
408             + "  heading = document.createElement('h2');\n"
409             + "  heading.textContent = 'is great';\n"
410             + "  fragment.appendChild(heading);\n"
411 
412             + "  log(new XMLSerializer().serializeToString(fragment));\n"
413             + "}\n"
414             + "</script></head><body onload='test()'>\n"
415             + "</body></html>";
416         loadPageVerifyTitle2(html);
417     }
418 
419     /**
420      * @throws Exception if the test fails
421      */
422     @Test
423     @Alerts({"<img/>", "<img xmlns=\"http://www.w3.org/1999/xhtml\" />", "<?myTarget myData?>"})
424     public void xml() throws Exception {
425         final String html = DOCTYPE_HTML
426             + "<html><head>\n"
427             + "<script>\n"
428             + LOG_TITLE_FUNCTION
429             + "  function test() {\n"
430             + "    var doc = document.implementation.createDocument('', '', null);\n"
431             + "    testFragment(doc);\n"
432             + "    testFragment(document);\n"
433             + "    var pi = doc.createProcessingInstruction('myTarget', 'myData');\n"
434             + "    log(new XMLSerializer().serializeToString(pi));\n"
435             + "  }\n"
436             + "  function testFragment(doc) {\n"
437             + "    var fragment = doc.createDocumentFragment();\n"
438             + "    var img = doc.createElement('img');\n"
439             + "    fragment.appendChild(img);\n"
440             + "    log(new XMLSerializer().serializeToString(fragment));\n"
441             + "  }\n"
442             + "</script></head><body onload='test()'>\n"
443             + "</body></html>";
444         loadPageVerifyTitle2(html);
445     }
446 
447     /**
448      * @throws Exception if the test fails
449      */
450     @Test
451     @Alerts("<root><my:parent xmlns:my=\"myUri\"><my:child/><another_child/></my:parent></root>")
452     public void namespace() throws Exception {
453         final String html = DOCTYPE_HTML
454             + "<html><head>\n"
455             + "<script>\n"
456             + LOG_TITLE_FUNCTION
457             + "  function test() {\n"
458             + "    var doc = document.implementation.createDocument('', '', null);\n"
459             + "    var root = doc.createElement('root');\n"
460             + "    doc.appendChild(root);\n"
461             + "    var parent = createNS(doc, 'my:parent', 'myUri');\n"
462             + "    root.appendChild(parent);\n"
463             + "    parent.appendChild(createNS(doc, 'my:child', 'myUri'));\n"
464             + "    parent.appendChild(doc.createElement('another_child'));\n"
465             + "    log(" + XMLDocumentTest.callSerializeXMLDocumentToString("doc") + ");\n"
466             + "  }\n"
467             + "  function createNS(doc, name, uri) {\n"
468             + "    return typeof doc.createNode == 'function' || typeof doc.createNode == 'unknown' ? "
469             + "doc.createNode(1, name, uri) : doc.createElementNS(uri, name);\n"
470             + "  }\n"
471             + XMLDocumentTest.SERIALIZE_XML_DOCUMENT_TO_STRING_FUNCTION
472             + "</script></head><body onload='test()'>\n"
473             + "</body></html>";
474         loadPageVerifyTitle2(html);
475     }
476 
477     /**
478      * @throws Exception if the test fails
479      */
480     @Test
481     @Alerts("<textarea xmlns=\"http://www.w3.org/1999/xhtml\"></textarea>")
482     public void mixedCase() throws Exception {
483         final String html = DOCTYPE_HTML
484             + "<html><head>\n"
485             + "<script>\n"
486             + LOG_TITLE_FUNCTION
487             + "  function test() {\n"
488             + "    var t = document.createElement('teXtaREa');\n"
489             + "    log(new XMLSerializer().serializeToString(t));\n"
490             + "  }\n"
491             + "</script></head><body onload='test()'>\n"
492             + "</body></html>";
493         loadPageVerifyTitle2(html);
494     }
495 
496     /**
497      * @throws Exception if the test fails
498      */
499     @Test
500     @Alerts({"<area xmlns=\"http://www.w3.org/1999/xhtml\" />",
501              "<base xmlns=\"http://www.w3.org/1999/xhtml\" />",
502              "<basefont xmlns=\"http://www.w3.org/1999/xhtml\" />",
503              "<br xmlns=\"http://www.w3.org/1999/xhtml\" />",
504              "<hr xmlns=\"http://www.w3.org/1999/xhtml\" />",
505              "<input xmlns=\"http://www.w3.org/1999/xhtml\" />",
506              "<link xmlns=\"http://www.w3.org/1999/xhtml\" />",
507              "<meta xmlns=\"http://www.w3.org/1999/xhtml\" />"})
508     public void noClosingTag() throws Exception {
509         final String html = DOCTYPE_HTML
510             + "<html><head>\n"
511             + "<script>\n"
512             + LOG_TITLE_FUNCTION
513             + "  function test() {\n"
514             + "    var t = document.createElement('area');\n"
515             + "    log(new XMLSerializer().serializeToString(t));\n"
516             + "    var t = document.createElement('base');\n"
517             + "    log(new XMLSerializer().serializeToString(t));\n"
518             + "    var t = document.createElement('basefont');\n"
519             + "    log(new XMLSerializer().serializeToString(t));\n"
520             + "    var t = document.createElement('br');\n"
521             + "    log(new XMLSerializer().serializeToString(t));\n"
522             + "    var t = document.createElement('hr');\n"
523             + "    log(new XMLSerializer().serializeToString(t));\n"
524             + "    var t = document.createElement('input');\n"
525             + "    log(new XMLSerializer().serializeToString(t));\n"
526             + "    var t = document.createElement('link');\n"
527             + "    log(new XMLSerializer().serializeToString(t));\n"
528             + "    var t = document.createElement('meta');\n"
529             + "    log(new XMLSerializer().serializeToString(t));\n"
530             + "  }\n"
531             + "</script></head><body onload='test()'>\n"
532             + "</body></html>";
533         loadPageVerifyTitle2(html);
534     }
535 
536     /**
537      * There is a small difference between HtmlUnit and FF.
538      * HtmlUnit adds type=text per default to the input
539      * FF handles input without type as type=text
540      * the fix for this is too big, so i made this workaround
541      * and add another (not yet implemented) test
542      *
543      * @throws Exception if the test fails
544      */
545     @Test
546     @Alerts("<input xmlns=\"http://www.w3.org/1999/xhtml\" />")
547     public void inputTagWithoutType() throws Exception {
548         final String html = DOCTYPE_HTML
549             + "<html><head>\n"
550             + "<script>\n"
551             + LOG_TITLE_FUNCTION
552             + "  function test() {\n"
553             + "    var t = document.createElement('input');\n"
554             + "    log(new XMLSerializer().serializeToString(t));\n"
555             + "  }\n"
556             + "</script></head><body onload='test()'>\n"
557             + "</body></html>";
558         loadPageVerifyTitle2(html);
559     }
560 
561     /**
562      * Test for some not self closing tags.
563      *
564      * @throws Exception if the test fails
565      */
566     @Test
567     @Alerts({"<div xmlns=\"http://www.w3.org/1999/xhtml\"></div>",
568              "<h1 xmlns=\"http://www.w3.org/1999/xhtml\"></h1>",
569              "<p xmlns=\"http://www.w3.org/1999/xhtml\"></p>",
570              "<li xmlns=\"http://www.w3.org/1999/xhtml\"></li>",
571              "<textarea xmlns=\"http://www.w3.org/1999/xhtml\"></textarea>"})
572     public void otherTags() throws Exception {
573         final String html = DOCTYPE_HTML
574             + "<html><head>\n"
575             + "<script>\n"
576             + LOG_TITLE_FUNCTION
577             + "  function test() {\n"
578             + "    var t = document.createElement('div');\n"
579             + "    log(new XMLSerializer().serializeToString(t));\n"
580             + "    var t = document.createElement('h1');\n"
581             + "    log(new XMLSerializer().serializeToString(t));\n"
582             + "    var t = document.createElement('p');\n"
583             + "    log(new XMLSerializer().serializeToString(t));\n"
584             + "    var t = document.createElement('li');\n"
585             + "    log(new XMLSerializer().serializeToString(t));\n"
586             + "    var t = document.createElement('textarea');\n"
587             + "    log(new XMLSerializer().serializeToString(t));\n"
588             + "  }\n"
589             + "</script></head><body onload='test()'>\n"
590             + "</body></html>";
591         loadPageVerifyTitle2(html);
592     }
593 
594     /**
595      * @throws Exception if the test fails
596      */
597     @Test
598     @Alerts("<img xmlns=\"http://www.w3.org/1999/xhtml\" href=\"mypage.htm\" />")
599     public void noClosingTagWithAttribute() throws Exception {
600         final String html = DOCTYPE_HTML
601             + "<html><head>\n"
602             + "<script>\n"
603             + LOG_TITLE_FUNCTION
604             + "  function test() {\n"
605             + "    var t = document.createElement('img');\n"
606             + "    t.setAttribute('href', 'mypage.htm');\n"
607             + "    log(new XMLSerializer().serializeToString(t));\n"
608             + "  }\n"
609             + "</script></head><body onload='test()'>\n"
610             + "</body></html>";
611         loadPageVerifyTitle2(html);
612     }
613 
614     /**
615      * @throws Exception if the test fails
616      */
617     @Test
618     @Alerts(CHROME = "<catalog>\n"
619                     + "  <cd>\n"
620                     + "    <title>Empire Burlesque</title>\n"
621                     + "    <artist>Bob Dylan \u1042</artist>\n"
622                     + "  </cd>\n"
623                     + "</catalog>",
624             EDGE = "<catalog>\n"
625                     + "  <cd>\n"
626                     + "    <title>Empire Burlesque</title>\n"
627                     + "    <artist>Bob Dylan \u1042</artist>\n"
628                     + "  </cd>\n"
629                     + "</catalog>",
630             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
631                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
632             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
633                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
634     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
635             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
636     public void outputXmlIndent() throws Exception {
637         transform("<xsl:output method='xml' indent='yes' />");
638     }
639 
640     /**
641      * @throws Exception if the test fails
642      */
643     @Test
644     @Alerts(CHROME = "<catalog>\n"
645                     + "  <cd>\n"
646                     + "    <title>Empire Burlesque</title>\n"
647                     + "    <artist>Bob Dylan \u1042</artist>\n"
648                     + "  </cd>\n"
649                     + "</catalog>",
650             EDGE = "<catalog>\n"
651                     + "  <cd>\n"
652                     + "    <title>Empire Burlesque</title>\n"
653                     + "    <artist>Bob Dylan \u1042</artist>\n"
654                     + "  </cd>\n"
655                     + "</catalog>",
656             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
657                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
658             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
659                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
660     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
661             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
662     public void outputIndent() throws Exception {
663         transform("<xsl:output indent='yes' />");
664     }
665 
666     /**
667      * @throws Exception if the test fails
668      */
669     @Test
670     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
671             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
672             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
673                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
674             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
675                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
676     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
677             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
678     public void outputNoIndent() throws Exception {
679         transform("<xsl:output indent='no' />");
680     }
681 
682     /**
683      * @throws Exception if the test fails
684      */
685     @Test
686     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
687             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
688             FF = "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
689                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
690             FF_ESR = "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
691                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
692     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
693             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
694     public void outputEncoding1252() throws Exception {
695         transform("<xsl:output encoding='Windows-1252' />");
696     }
697 
698     /**
699      * @throws Exception if the test fails
700      */
701     @Test
702     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
703             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
704             FF = "<?xml version=\"1.0\" encoding=\"windows-1251\"?>\n"
705                 + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
706             FF_ESR = "<?xml version=\"1.0\" encoding=\"windows-1251\"?>\n"
707                 + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
708     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
709             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
710     public void outputEncoding1251() throws Exception {
711         transform("<xsl:output encoding='Windows-1251' />");
712     }
713 
714     /**
715      * @throws Exception if the test fails
716      */
717     @Test
718     @Alerts("<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
719     public void outputOmitXmlDeclaration() throws Exception {
720         transform("<xsl:output omit-xml-declaration='yes' />");
721     }
722 
723     /**
724      * @throws Exception if the test fails
725      */
726     @Test
727     @Alerts(CHROME = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
728             EDGE = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
729             FF = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
730                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
731             FF_ESR = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
732                     + "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
733     @HtmlUnitNYI(FF_ESR = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>",
734             FF = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan \u1042</artist></cd></catalog>")
735     public void noOutput() throws Exception {
736         transform("");
737     }
738 
739     private void transform(final String xslOutput) throws Exception {
740         final String xml
741                 = "<?xml version='1.0' encoding='ISO-8859-1'?>"
742                 + "<catalog><cd><title>Empire Burlesque</title>"
743                 + "<artist>Bob Dylan &#x1042;</artist>"
744                 + "</cd>"
745                 + "</catalog>";
746 
747         final String xsl
748                 = "<?xml version='1.0' encoding='ISO-8859-1'?>"
749                 + "<xsl:stylesheet version='1.0' "
750                 + "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' >"
751                 + "  " + xslOutput
752                 + "  <xsl:template match='@*|node()'>"
753                 + "    <xsl:copy>"
754                 + "      <xsl:apply-templates select='@*|node()'/>"
755                 + "    </xsl:copy>"
756                 + "  </xsl:template>"
757                 + "</xsl:stylesheet>";
758 
759         final String html = DOCTYPE_HTML
760                 + "<html><head><title>foo</title><script>\n"
761                 + "  function test() {\n"
762                 + "    var ta = document.getElementById('myLog');\n"
763                 + "    try {\n"
764                 + "      var xsltProcessor = new XSLTProcessor();\n"
765                 + "      var xmlDoc = new DOMParser().parseFromString(\"" + xml + "\", \"application/xml\");\n"
766                 + "      var xsltDoc = new DOMParser().parseFromString(\"" + xsl + "\", \"application/xml\");\n"
767                 + "      xsltProcessor.importStylesheet(xsltDoc);\n"
768                 + "      var resultDocument = xsltProcessor.transformToDocument(xmlDoc);\n"
769                 + "      var xml = new XMLSerializer().serializeToString(resultDocument);\n"
770                 + "      ta.value = xml + '\\u00a7';\n"
771                 + "    } catch(e) { ta.value = 'exception'; }\n"
772                 + "  }\n"
773                 + "</script></head>\n"
774                 + "<body onload='test()'>\n"
775                 + LOG_TEXTAREA
776                 + "</body></html>";
777 
778         final MockWebConnection conn = getMockWebConnection();
779         conn.setResponse(new URL(URL_SECOND, "1"), xml, MimeType.TEXT_XML);
780         conn.setResponse(new URL(URL_SECOND, "2"), xsl, MimeType.TEXT_XML);
781 
782         final WebDriver driver = loadPage2(html);
783 
784         verifyTextArea2(driver, getExpectedAlerts()[0]);
785     }
786 }