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