From: <rb...@us...> - 2013-05-20 10:10:43
|
Revision: 8276 http://sourceforge.net/p/htmlunit/code/8276 Author: rbri Date: 2013-05-20 10:10:41 +0000 (Mon, 20 May 2013) Log Message: ----------- Use the correct frame/iframe for a given target if more than one exists for the given name. Issue 1488 Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/WebClient.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlInlineFrame2Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2013-05-20 09:52:14 UTC (rev 8275) +++ trunk/htmlunit/src/changes/changes.xml 2013-05-20 10:10:41 UTC (rev 8276) @@ -8,6 +8,9 @@ <body> <release version="2.13" date="???" description="Bugfixes"> + <action type="fix" dev="rbri" issue="1488"> + Use the correct frame/iframe for a given target if more than one exists for the given name. + </action> <action type="fix" dev="rbri"> The value of input controls changes when the defaultValue was changed in IE8ff. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/WebClient.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/WebClient.java 2013-05-20 09:52:14 UTC (rev 8275) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/WebClient.java 2013-05-20 10:10:41 UTC (rev 8276) @@ -857,14 +857,33 @@ return null; } - if (!name.isEmpty()) { - try { - return getWebWindowByName(name); + // first search for frame windows inside our window hierarchy + WebWindow window = opener; + while (true) { + final Page page = window.getEnclosedPage(); + if (page instanceof HtmlPage) { + try { + final FrameWindow frame = ((HtmlPage) page).getFrameByName(name); + return frame; + } + catch (final ElementNotFoundException e) { + // Fall through + } } - catch (final WebWindowNotFoundException e) { - // Fall through - a new window will be created below + + if (window == window.getParentWindow()) { + // TODO: should getParentWindow() return null on top windows? + break; } + window = window.getParentWindow(); } + + try { + return getWebWindowByName(name); + } + catch (final WebWindowNotFoundException e) { + // Fall through - a new window will be created below + } return null; } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlInlineFrame2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlInlineFrame2Test.java 2013-05-20 09:52:14 UTC (rev 8275) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlInlineFrame2Test.java 2013-05-20 10:10:41 UTC (rev 8276) @@ -14,6 +14,9 @@ */ package com.gargoylesoftware.htmlunit.html; +import java.net.URL; + +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.openqa.selenium.By; @@ -22,6 +25,7 @@ import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; +import com.gargoylesoftware.htmlunit.MockWebConnection; import com.gargoylesoftware.htmlunit.WebDriverTestCase; /** @@ -84,4 +88,103 @@ loadPageWithAlerts2(html); } + + /** + * Test, the right frame is used for a target, even if some frames + * have the same name. + * + * @throws Exception if the test fails + */ + @Test + public void targetResolution() throws Exception { + final String framesContent = "<html><head><title>Top Page</title></head>\n" + + "<body><div id='content'>Body of top frame</div>\n" + + " <iframe src='left.html' id='id-left' name='left'></iframe>\n" + + " <iframe src='right.html' id='id-right' name='right'></iframe>\n" + + "</body>\n" + + "</html>"; + + final String rightFrame = "<html><head><title>Right Frame</title></head>\n" + + "<body><div id='content'>Body of right frame</div></body>\n" + + "</html>"; + + final String leftFrame = "<html><head><title>Left Frame</title></head>\n" + + "<body>\n" + + " <div id='content'>Body of left frame</div>\n" + + " <a id='link' name='link' href='new_inner.html' target='right'>Click link</a>" + + " <iframe id='id-inner' name='right' width='100' height='100' src='inner.html'></iframe>" + + "</body>\n" + + "</html>"; + + final String innerFrame = "<html><head><title>Inner Frame</title></head>\n" + + "<body><div id='content'>Body of inner frame</div></body>\n" + + "</html>"; + + final String newInnerFrame = "<html><head><title>New inner Frame</title></head>\n" + + "<body><div id='content'>Body of new inner frame</div></body>\n" + + "</html>"; + + final String baseUrl = URL_FIRST.toString(); + + final URL leftFrameUrl = new URL(baseUrl + "left.html"); + final URL rightFrameUrl = new URL(baseUrl + "right.html"); + final URL innerFrameURL = new URL(baseUrl + "inner.html"); + final URL newInnerFrameURL = new URL(baseUrl + "new_inner.html"); + + final MockWebConnection webConnection = getMockWebConnection(); + webConnection.setResponse(leftFrameUrl, leftFrame); + webConnection.setResponse(rightFrameUrl, rightFrame); + webConnection.setResponse(innerFrameURL, innerFrame); + webConnection.setResponse(newInnerFrameURL, newInnerFrame); + + final WebDriver driver = loadPage2(framesContent); + + // top frame + assertEquals("Top Page", driver.getTitle()); + assertEquals("Body of top frame", driver.findElement(By.id("content")).getText()); + + // start REMOVE ME + // because of the return value change done for + // com.gargoylesoftware.htmlunit.html.BaseFrameElement.getEnclosedWindow() + // this test does not work with the current selenium driver + // this hack is only to inform us, if selenium uses the latest htmlunit + // then we can remove this + try { + driver.switchTo().frame("id-left"); + Assert.fail("Switching the frame seems to work now in selenium. Please remove this code."); + } + catch (final NoSuchMethodError e) { + // expected, no chance to implement the test without this + return; + } + // end REMOVE ME + + // left frame + driver.switchTo().frame("id-left"); + assertEquals("Body of left frame", driver.findElement(By.id("content")).getText()); + // inner frame + driver.switchTo().frame("id-inner"); + assertEquals("Body of inner frame", driver.findElement(By.id("content")).getText()); + // right frame + driver.switchTo().defaultContent(); + driver.switchTo().frame("id-right"); + assertEquals("Body of right frame", driver.findElement(By.id("content")).getText()); + + // clicking on a link which contains a target 'right'. But this target frame is defined two times. + driver.switchTo().defaultContent(); + driver.switchTo().frame("id-left"); + driver.findElement(By.id("link")).click(); + + // left frame + driver.switchTo().defaultContent(); + driver.switchTo().frame("id-left"); + assertEquals("Body of left frame", driver.findElement(By.id("content")).getText()); + // inner frame + driver.switchTo().frame("id-inner"); + assertEquals("Body of new inner frame", driver.findElement(By.id("content")).getText()); + // right frame + driver.switchTo().defaultContent(); + driver.switchTo().frame("id-right"); + assertEquals("Body of right frame", driver.findElement(By.id("content")).getText()); + } } |