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.html;
16  
17  import java.io.File;
18  import java.net.URL;
19  import java.util.Map;
20  
21  import org.htmlunit.HttpHeader;
22  import org.htmlunit.MockWebConnection;
23  import org.htmlunit.WebDriverTestCase;
24  import org.htmlunit.junit.annotation.Alerts;
25  import org.htmlunit.junit.annotation.HtmlUnitNYI;
26  import org.junit.jupiter.api.Test;
27  import org.openqa.selenium.By;
28  import org.openqa.selenium.WebDriver;
29  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
30  
31  /**
32   * Unit tests for {@link HtmlInlineFrame}.
33   *
34   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
35   * @author Ahmed Ashour
36   * @author Marc Guillemot
37   * @author Daniel Gredler
38   * @author Ronald Brill
39   * @author Frank Danek
40   */
41  public class HtmlInlineFrame2Test extends WebDriverTestCase {
42  
43      /**
44       * @throws Exception if the test fails
45       */
46      @Test
47      @Alerts("[object HTMLIFrameElement]")
48      public void simpleScriptable() throws Exception {
49          final String html = DOCTYPE_HTML
50              + "<html><head>\n"
51              + "<script>\n"
52              + LOG_TITLE_FUNCTION
53              + "  function test() {\n"
54              + "    log(document.getElementById('myId'));\n"
55              + "  }\n"
56              + "</script>\n"
57              + "</head><body onload='test()'>\n"
58              + "  <iframe id='myId'>\n"
59              + "</body></html>";
60  
61          final WebDriver webDriver = loadPageVerifyTitle2(html);
62          if (webDriver instanceof HtmlUnitDriver) {
63              final HtmlElement element = toHtmlElement(webDriver.findElement(By.id("myId")));
64              assertTrue(HtmlInlineFrame.class.isInstance(element));
65          }
66      }
67  
68      /**
69       * Self-closing iframe tag is accepted by IE but not by FF.
70       * @throws Exception if the test fails
71       */
72      @Test
73      @Alerts({"1", "[object HTMLIFrameElement]", "null"})
74      public void selfClosingIFrame() throws Exception {
75          final String html = DOCTYPE_HTML
76              + "<html><head>\n"
77              + "<script>\n"
78              + LOG_TITLE_FUNCTION
79              + "  function test() {\n"
80              + "    log(window.frames.length);\n"
81              + "    log(document.getElementById('frame1'));\n"
82              + "    log(document.getElementById('frame2'));\n"
83              + "  }\n"
84              + "</script>\n"
85              + "</head><body onload='test()'>\n"
86              + "  <iframe id='frame1'/>\n"
87              + "  <iframe id='frame2'/>\n"
88              + "</body></html>";
89  
90          loadPageVerifyTitle2(html);
91      }
92  
93      /**
94       * Test, the correct frame is used for a target, even if some frames
95       * have the same name.
96       *
97       * @throws Exception if the test fails
98       */
99      @Test
100     public void targetResolution() throws Exception {
101         final String framesContent = DOCTYPE_HTML
102                 + "<html><head><title>Top Page</title></head>\n"
103                 + "<body><div id='content'>Body of top frame</div>\n"
104                 + "  <iframe src='left.html' id='id-left' name='left'></iframe>\n"
105                 + "  <iframe src='right.html' id='id-right' name='right'></iframe>\n"
106                 + "</body>\n"
107                 + "</html>";
108 
109         final String rightFrame = DOCTYPE_HTML
110                 + "<html><head><title>Right Frame</title></head>\n"
111                 + "<body><div id='content'>Body of right frame</div></body>\n"
112                 + "</html>";
113 
114         final String leftFrame = DOCTYPE_HTML
115                 + "<html><head><title>Left Frame</title></head>\n"
116                 + "<body>\n"
117                 + "  <div id='content'>Body of left frame</div>\n"
118                 + "  <a id='link' name='link' href='new_inner.html' target='right'>Click link</a>\n"
119                 + "  <iframe id='id-inner' name='right' width='100' height='100' src='inner.html'></iframe>\n"
120                 + "</body>\n"
121                 + "</html>";
122 
123         final String innerFrame = DOCTYPE_HTML
124                 + "<html><head><title>Inner Frame</title></head>\n"
125                 + "<body><div id='content'>Body of inner frame</div></body>\n"
126                 + "</html>";
127 
128         final String newInnerFrame = DOCTYPE_HTML
129                 + "<html><head><title>New inner Frame</title></head>\n"
130                 + "<body><div id='content'>Body of new inner frame</div></body>\n"
131                 + "</html>";
132 
133         final String baseUrl = URL_FIRST.toString();
134 
135         final URL leftFrameUrl = new URL(baseUrl + "left.html");
136         final URL rightFrameUrl = new URL(baseUrl + "right.html");
137         final URL innerFrameURL = new URL(baseUrl + "inner.html");
138         final URL newInnerFrameURL = new URL(baseUrl + "new_inner.html");
139 
140         final MockWebConnection webConnection = getMockWebConnection();
141         webConnection.setResponse(leftFrameUrl, leftFrame);
142         webConnection.setResponse(rightFrameUrl, rightFrame);
143         webConnection.setResponse(innerFrameURL, innerFrame);
144         webConnection.setResponse(newInnerFrameURL, newInnerFrame);
145 
146         final WebDriver driver = loadPage2(framesContent);
147 
148         // top frame
149         assertTitle(driver, "Top Page");
150         assertEquals("Body of top frame", driver.findElement(By.id("content")).getText());
151 
152         // left frame
153         driver.switchTo().frame("id-left");
154         assertEquals("Body of left frame", driver.findElement(By.id("content")).getText());
155         // inner frame
156         driver.switchTo().frame("id-inner");
157         assertEquals("Body of inner frame", driver.findElement(By.id("content")).getText());
158         // right frame
159         driver.switchTo().defaultContent();
160         driver.switchTo().frame("id-right");
161         assertEquals("Body of right frame", driver.findElement(By.id("content")).getText());
162 
163         // clicking on a link which contains a target 'right'. But this target frame is defined two times.
164         driver.switchTo().defaultContent();
165         driver.switchTo().frame("id-left");
166         driver.findElement(By.id("link")).click();
167 
168         // left frame
169         driver.switchTo().defaultContent();
170         driver.switchTo().frame("id-left");
171         assertEquals("Body of left frame", driver.findElement(By.id("content")).getText());
172         // inner frame
173         driver.switchTo().frame("id-inner");
174         assertEquals("Body of new inner frame", driver.findElement(By.id("content")).getText());
175         // right frame
176         driver.switchTo().defaultContent();
177         driver.switchTo().frame("id-right");
178         assertEquals("Body of right frame", driver.findElement(By.id("content")).getText());
179     }
180 
181     /**
182      * @throws Exception if the test fails
183      */
184     @Test
185     @Alerts("2")
186     public void scriptUnderIFrame() throws Exception {
187         final String firstContent = DOCTYPE_HTML
188             + "<html><body>\n"
189             + "<iframe src='" + URL_SECOND + "'>\n"
190             + "  <div><script>alert(1);</script></div>\n"
191             + "  <script src='" + URL_THIRD + "'></script>\n"
192             + "</iframe>\n"
193             + "</body></html>";
194         final String secondContent = DOCTYPE_HTML
195             + "<html><body><script>alert(2);</script></body></html>";
196         final String thirdContent = "alert('3');";
197 
198         getMockWebConnection().setResponse(URL_SECOND, secondContent);
199         getMockWebConnection().setResponse(URL_THIRD, thirdContent, "text/javascript");
200 
201         loadPageWithAlerts2(firstContent);
202     }
203 
204     /**
205      * Looks like url's with the about schema are always behave
206      * like 'about:blank'.
207      *
208      * @throws Exception if the test fails
209      */
210     @Test
211     @Alerts(DEFAULT = "about:blank",
212             CHROME = "about://unsupported",
213             EDGE = "about://unsupported")
214     @HtmlUnitNYI(CHROME = "about:blank",
215             EDGE = "about:blank")
216     public void aboutSrc() throws Exception {
217         final String html = DOCTYPE_HTML
218             + "<html><head>\n"
219             + "<script>\n"
220             + LOG_TITLE_FUNCTION
221             + "  function test() {\n"
222             + "    var frame = document.getElementById('tstFrame');\n"
223             + "    try {"
224             + "      log(frame.contentWindow.location.href);\n"
225             + "    } catch(e) { logEx(e); }\n"
226             + "  }\n"
227             + "</script>\n"
228             + "</head>\n"
229             + "<body>\n"
230             + "  <iframe id='tstFrame' src='about://unsupported'></iframe>\n"
231             + "  <button id='test' onclick='test()'>Test</button>\n"
232             + "</body></html>";
233 
234         final WebDriver driver = loadPage2(html);
235         driver.findElement(By.id("test")).click();
236 
237         verifyTitle2(driver, getExpectedAlerts());
238     }
239 
240     /**
241      * See issue #1897.
242      * In the end the strict mode should not be used for the setup of
243      * the new window.
244      *
245      * @throws Exception if the test fails
246      */
247     @Test
248     @Alerts({"1:true", "2:false", "3:false", "4:false"})
249     @HtmlUnitNYI(CHROME = {"1:false", "2:false", "3:false", "4:false"},
250             EDGE = {"1:false", "2:false", "3:false", "4:false"},
251             FF = {"1:false", "2:false", "3:false", "4:false"},
252             FF_ESR = {"1:false", "2:false", "3:false", "4:false"})
253     public void createIframeFromStrictFunction() throws Exception {
254         final String html = DOCTYPE_HTML
255                 + "<html><head>\n"
256                 + "<script>\n"
257                 + LOG_TITLE_FUNCTION
258                 + "  function test() {\n"
259                 + "    'use strict';\n"
260                 + "    var iframe = document.createElement('iframe');\n"
261                 + "    log('1:' + !this);\n"
262                 + "    log('2:' + !iframe);\n"
263                 + "  }\n"
264                 + "  function test2() {\n"
265                 + "    var iframe = document.createElement('iframe');\n"
266                 + "    log('3:' + !this);\n"
267                 + "    log('4:' + !iframe);\n"
268                 + "  }\n"
269                 + "</script>\n"
270                 + "</head>\n"
271                 + "<body onload='test();test2()'>\n"
272                 + "</body></html>";
273 
274         loadPageVerifyTitle2(html);
275     }
276 
277     /**
278      * Check for the right referrer header.
279      *
280      * @throws Exception if the test fails
281      */
282     @Test
283     @Alerts("§§URL§§index.html?test")
284     public void referrer() throws Exception {
285         final String framesContent = DOCTYPE_HTML
286                 + "<html>\n"
287                 + "<head><title>Top Page</title></head>\n"
288                 + "<body>\n"
289                 + "  <iframe src='iframe.html'></iframe>\n"
290                 + "</body>\n"
291                 + "</html>";
292 
293         final String iFrame = DOCTYPE_HTML
294                 + "<html>\n"
295                 + "<head></head>\n"
296                 + "<body>Body</body>\n"
297                 + "</html>";
298 
299         expandExpectedAlertsVariables(URL_FIRST);
300 
301         final URL indexUrl = new URL(URL_FIRST.toString() + "index.html");
302         final URL iFrameUrl = new URL(URL_FIRST.toString() + "iframe.html");
303 
304         getMockWebConnection().setResponse(indexUrl, framesContent);
305         getMockWebConnection().setResponse(iFrameUrl, iFrame);
306 
307         loadPage2(framesContent, new URL(URL_FIRST.toString() + "index.html?test#ref"));
308         Thread.sleep(DEFAULT_WAIT_TIME.toMillis() / 10);
309         assertEquals(2, getMockWebConnection().getRequestCount());
310 
311         final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders();
312         assertEquals(getExpectedAlerts()[0], lastAdditionalHeaders.get(HttpHeader.REFERER));
313     }
314 
315     /**
316      * @throws Exception if the test fails
317      */
318     @Test
319     public void localFile() throws Exception {
320         final URL fileURL = getClass().getClassLoader().getResource("testfiles/xhtml.html");
321         final File file = new File(fileURL.toURI());
322         assertTrue("File '" + file.getAbsolutePath() + "' does not exist", file.exists());
323 
324         final String html = DOCTYPE_HTML
325                 + "<html>"
326                 + "<head><title>Top Page</title></head>\n"
327                 + "<body>\n"
328                 + "  <iframe id='myFrame' src='" + fileURL + "'></iframe>\n"
329                 + "  <div>HtmlUnit</div>\n"
330                 + "</body>\n"
331                 + "</html>";
332 
333         final WebDriver driver = loadPage2(html);
334         assertTitle(driver, "Top Page");
335         assertEquals("HtmlUnit", driver.findElement(By.tagName("body")).getText());
336 
337         driver.switchTo().frame("myFrame");
338         assertEquals("", driver.findElement(By.tagName("body")).getText());
339     }
340 }