1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import static org.junit.jupiter.api.Assertions.fail;
18
19 import java.net.URL;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.htmlunit.CollectingAlertHandler;
24 import org.htmlunit.FailingHttpStatusCodeException;
25 import org.htmlunit.MockWebConnection;
26 import org.htmlunit.SimpleWebTestCase;
27 import org.htmlunit.WebClient;
28 import org.htmlunit.junit.annotation.Alerts;
29 import org.htmlunit.util.MimeType;
30 import org.junit.jupiter.api.Test;
31
32
33
34
35
36
37
38
39
40 public class HtmlScriptTest extends SimpleWebTestCase {
41
42
43
44
45
46
47
48
49
50 @Test
51 public void badExternalScriptReference() throws Exception {
52 final String html = DOCTYPE_HTML
53 + "<html><head><title>foo</title>\n"
54 + "<script src='inexistent.js'></script>\n"
55 + "</head><body></body></html>";
56
57 final WebClient client = getWebClient();
58
59 final MockWebConnection webConnection = new MockWebConnection();
60 webConnection.setDefaultResponse("inexistent", 404, "Not Found", MimeType.TEXT_HTML);
61 webConnection.setResponse(URL_FIRST, html);
62 client.setWebConnection(webConnection);
63
64 try {
65 client.getPage(URL_FIRST);
66 fail("Should throw.");
67 }
68 catch (final FailingHttpStatusCodeException e) {
69 final String url = URL_FIRST.toExternalForm();
70 assertTrue("exception contains URL of failing script", e.getMessage().indexOf(url) > -1);
71 assertEquals(404, e.getStatusCode());
72 assertEquals("Not Found", e.getStatusMessage());
73 }
74
75 client.getOptions().setThrowExceptionOnFailingStatusCode(false);
76
77 try {
78 client.getPage(URL_FIRST);
79 }
80 catch (final FailingHttpStatusCodeException e) {
81 fail("Should not throw.");
82 }
83 }
84
85
86
87
88 @Test
89 public void asNormalizedText() throws Exception {
90 final String html = DOCTYPE_HTML + "<html><body><script id='s'>var foo = 132;</script></body></html>";
91 final HtmlPage page = loadPage(html);
92 final HtmlScript script = page.getHtmlElementById("s");
93 assertEquals("", script.asNormalizedText());
94 }
95
96
97
98
99 @Test
100 @Alerts("hello")
101 public void asXml() throws Exception {
102 final String html = DOCTYPE_HTML
103 + "<html><head><title>foo</title></head><body>\n"
104 + "<script id='script1'>\n"
105 + " alert('hello');\n"
106 + "</script></body></html>";
107
108 final HtmlPage page = loadPageWithAlerts(html);
109
110
111 final String xml = page.asXml();
112 assertEquals("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n"
113 + "<html>\r\n"
114 + " <head>\r\n"
115 + " <title>foo</title>\r\n"
116 + " </head>\r\n"
117 + " <body>\r\n"
118 + " <script id=\"script1\">\r\n"
119 + "//<![CDATA[\r\n"
120 + "\n"
121 + " alert('hello');\n"
122 + "\r\n"
123 + "//]]>\r\n"
124 + " </script>\r\n"
125 + " </body>\r\n"
126 + "</html>",
127 xml);
128
129 loadPageWithAlerts(xml);
130 }
131
132
133
134
135 @Test
136 public void asXml_scriptNestedInCData() throws Exception {
137 final String script = "//<![CDATA[\n"
138 + "var foo = 132;\n"
139 + "//]]>";
140 final String html = DOCTYPE_HTML + "<html><body><script id='s'>" + script + "</script></body></html>";
141 final HtmlPage page = loadPage(html);
142 final HtmlScript scriptElement = page.getHtmlElementById("s");
143 assertEquals("<script id=\"s\">\r\n" + script + "\r\n</script>",
144 scriptElement.asXml());
145 }
146
147
148
149
150
151 @Test
152 @Alerts("loaded")
153 public void scriptCloneDoesNotReloadScript() throws Exception {
154 final String html = DOCTYPE_HTML + "<html><body><script src='" + URL_SECOND + "'></script></body></html>";
155 final String js = "alert('loaded')";
156
157 final WebClient client = getWebClient();
158
159 final MockWebConnection conn = new MockWebConnection();
160 conn.setResponse(URL_FIRST, html);
161 conn.setResponse(URL_SECOND, js, MimeType.TEXT_JAVASCRIPT);
162 client.setWebConnection(conn);
163
164 final List<String> actual = new ArrayList<>();
165 client.setAlertHandler(new CollectingAlertHandler(actual));
166
167 final HtmlPage page = client.getPage(URL_FIRST);
168 assertEquals(2, conn.getRequestCount());
169
170 page.cloneNode(true);
171 assertEquals(2, conn.getRequestCount());
172
173 assertEquals(getExpectedAlerts(), actual);
174 }
175
176
177
178
179 @Test
180 @Alerts({"c", "f"})
181 public void addEventListener_error_clientThrows() throws Exception {
182 addEventListener_error(true);
183 }
184
185
186
187
188 @Test
189 @Alerts({"c", "f"})
190 public void addEventListener_error_clientDoesNotThrow() throws Exception {
191 addEventListener_error(false);
192 }
193
194 private void addEventListener_error(final boolean throwOnFailingStatusCode) throws Exception {
195 final URL fourOhFour = new URL(URL_FIRST, "/404");
196 final String html = DOCTYPE_HTML
197 + "<html><head>\n"
198 + "<script>\n"
199 + " function test() {\n"
200 + " var s1 = document.createElement('script');\n"
201 + " s1.text = 'var foo';\n"
202 + " s1.addEventListener('error', function() {alert('a')}, false);\n"
203 + " document.body.insertBefore(s1, document.body.firstChild);\n"
204 + " \n"
205 + " var s2 = document.createElement('script');\n"
206 + " s2.text = 'varrrr foo';\n"
207 + " s2.addEventListener('error', function() {alert('b')}, false);\n"
208 + " document.body.insertBefore(s2, document.body.firstChild);\n"
209 + " \n"
210 + " var s3 = document.createElement('script');\n"
211 + " s3.src = '//:';\n"
212 + " s3.addEventListener('error', function() {alert('c')}, false);\n"
213 + " document.body.insertBefore(s3, document.body.firstChild);\n"
214 + " \n"
215 + " var s4 = document.createElement('script');\n"
216 + " s4.src = '" + URL_SECOND + "';\n"
217 + " s4.addEventListener('error', function() {alert('d')}, false);\n"
218 + " document.body.insertBefore(s4, document.body.firstChild);\n"
219 + " \n"
220 + " var s5 = document.createElement('script');\n"
221 + " s5.src = '" + URL_THIRD + "';\n"
222 + " s5.addEventListener('error', function() {alert('e')}, false);\n"
223 + " document.body.insertBefore(s5, document.body.firstChild);\n"
224 + " \n"
225 + " var s6 = document.createElement('script');\n"
226 + " s6.src = '" + fourOhFour + "';\n"
227 + " s6.addEventListener('error', function() {alert('f')}, false);\n"
228 + " document.body.insertBefore(s6, document.body.firstChild);\n"
229 + " }\n"
230 + "</script>\n"
231 + "</head>\n"
232 + "<body onload='test()'></body>\n"
233 + "</html>";
234 final WebClient client = getWebClient();
235 client.getOptions().setThrowExceptionOnFailingStatusCode(throwOnFailingStatusCode);
236 client.getOptions().setThrowExceptionOnScriptError(false);
237
238 final MockWebConnection conn = new MockWebConnection();
239 conn.setResponse(URL_FIRST, html);
240 conn.setResponse(URL_SECOND, "var foo;", MimeType.TEXT_JAVASCRIPT);
241 conn.setResponse(URL_THIRD, "varrrr foo;", MimeType.TEXT_JAVASCRIPT);
242 conn.setResponse(fourOhFour, "", 404, "Missing", MimeType.TEXT_JAVASCRIPT, new ArrayList<>());
243 client.setWebConnection(conn);
244 final List<String> actual = new ArrayList<>();
245 client.setAlertHandler(new CollectingAlertHandler(actual));
246 client.getPage(URL_FIRST);
247 assertEquals(getExpectedAlerts(), actual);
248 }
249
250
251
252
253 @Test
254 public void isDisplayed() throws Exception {
255 final String html = DOCTYPE_HTML
256 + "<html><head><title>Page A</title></head><body><script>var x = 1;</script></body></html>";
257 final HtmlPage page = loadPageWithAlerts(html);
258 final HtmlScript script = page.getFirstByXPath("//script");
259 assertFalse(script.isDisplayed());
260 }
261
262
263
264
265
266
267 @Test
268 @Alerts({"First script executes", "Second page loading"})
269 public void changingLocationSkipsFurtherScriptsOnPage() throws Exception {
270 final String html = DOCTYPE_HTML
271 + "<html><head></head>\n"
272 + "<body onload='alert(\"body onload executing but should be skipped\")'>\n"
273 + "<script>alert('First script executes')</script>\n"
274 + "<script>window.location.href='" + URL_SECOND + "'</script>\n"
275 + "<script>alert('Third script executing but should be skipped')</script>\n"
276 + "</body></html>";
277
278 final String secondPage = DOCTYPE_HTML
279 + "<html><head></head><body>\n"
280 + "<script>alert('Second page loading')</script>\n"
281 + "</body></html>";
282
283 getMockWebConnection().setResponse(URL_SECOND, secondPage);
284 loadPageWithAlerts(html);
285 }
286 }