001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit.html;
039:
040: import java.util.ArrayList;
041: import java.util.Collections;
042: import java.util.List;
043: import java.util.Map;
044:
045: import com.gargoylesoftware.htmlunit.BrowserVersion;
046: import com.gargoylesoftware.htmlunit.CollectingAlertHandler;
047: import com.gargoylesoftware.htmlunit.MockWebConnection;
048: import com.gargoylesoftware.htmlunit.SubmitMethod;
049: import com.gargoylesoftware.htmlunit.TopLevelWindow;
050: import com.gargoylesoftware.htmlunit.WebClient;
051: import com.gargoylesoftware.htmlunit.WebTestCase;
052:
053: /**
054: * Unit tests for {@link HtmlAnchor}.
055: *
056: * @version $Revision: 2132 $
057: * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
058: * @author Marc Guillemot
059: * @author Stefan Anzinger
060: * @author Ahmed Ashour
061: */
062: public class HtmlAnchorTest extends WebTestCase {
063:
064: /**
065: * Create an instance
066: *
067: * @param name Name of the test
068: */
069: public HtmlAnchorTest(final String name) {
070: super (name);
071: }
072:
073: /**
074: * Verifies that anchor href attributes are trimmed of whitespace (bug 1658064),
075: * just like they are in IE and Firefox.
076: * @throws Exception If an error occurs.
077: */
078: public void testHrefTrimmed() throws Exception {
079: final String html = "<html><body onload='"
080: + "alert(document.getElementById(\"a\").href.length);\n"
081: + "alert(document.getElementById(\"b\").href.length);'>\n"
082: + "<a href=' http://a/ ' id='a'>a</a> "
083: + "<a href=' http://b/ ' id='b'>b</a>\n"
084: + "</body></html>";
085:
086: final List collectedAlerts = new ArrayList();
087: loadPage(html, collectedAlerts);
088:
089: final String[] expectedAlerts = { "9", "9" };
090: assertEquals(expectedAlerts, collectedAlerts);
091: }
092:
093: /**
094: * @throws Exception if the test fails
095: */
096: public void testClick() throws Exception {
097: final String htmlContent = "<html><head><title>foo</title></head><body>\n"
098: + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
099: + "<a href='http://www.foo2.com' id='a2'>link to foo2</a>\n"
100: + "<a href='http://www.foo3.com' id='a3'>link to foo3</a>\n"
101: + "</body></html>";
102:
103: final HtmlPage page = loadPage(htmlContent);
104: final HtmlAnchor anchor = (HtmlAnchor) page
105: .getHtmlElementById("a2");
106:
107: // Test that the correct value is being passed back up to the server
108: final HtmlPage secondPage = (HtmlPage) anchor.click();
109:
110: final List expectedParameters = Collections.EMPTY_LIST;
111: final MockWebConnection webConnection = getMockConnection(secondPage);
112:
113: assertEquals("url", "http://www.foo2.com", secondPage
114: .getWebResponse().getUrl());
115: assertEquals("method", SubmitMethod.GET, webConnection
116: .getLastMethod());
117: assertEquals("parameters", expectedParameters, webConnection
118: .getLastParameters());
119: assertNotNull(secondPage);
120: }
121:
122: /**
123: * @throws Exception if the test fails
124: */
125: public void testClickAnchorName() throws Exception {
126: final String htmlContent = "<html><head><title>foo</title></head><body>\n"
127: + "<a href='#clickedAnchor' id='a1'>link to foo1</a>\n"
128: + "</body></html>";
129:
130: final HtmlPage page = loadPage(htmlContent);
131:
132: final HtmlAnchor anchor = (HtmlAnchor) page
133: .getHtmlElementById("a1");
134:
135: // Test that the correct value is being passed back up to the server
136: final HtmlPage secondPage = (HtmlPage) anchor.click();
137:
138: // The url shouldn't contain the anchor since isn't sent to the server
139: assertEquals("url", URL_GARGOYLE, secondPage.getWebResponse()
140: .getUrl());
141: assertSame(page, secondPage);
142: }
143:
144: /**
145: * @throws Exception if the test fails
146: */
147: public void testClick_onClickHandler() throws Exception {
148: final String firstContent = "<html><head><title>First</title></head><body>\n"
149: + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
150: + "<a href='"
151: + URL_SECOND
152: + "' id='a2' "
153: + "onClick='alert(\"clicked\")'>link to foo2</a>\n"
154: + "<a href='http://www.foo3.com' id='a3'>link to foo3</a>\n"
155: + "</body></html>";
156: final String secondContent = "<html><head><title>Second</title></head><body></body></html>";
157:
158: final WebClient client = new WebClient();
159: final List collectedAlerts = new ArrayList();
160: client.setAlertHandler(new CollectingAlertHandler(
161: collectedAlerts));
162:
163: final MockWebConnection webConnection = new MockWebConnection(
164: client);
165: webConnection.setResponse(URL_FIRST, firstContent);
166: webConnection.setResponse(URL_SECOND, secondContent);
167: client.setWebConnection(webConnection);
168:
169: final HtmlPage page = (HtmlPage) client.getPage(URL_FIRST);
170: final HtmlAnchor anchor = (HtmlAnchor) page
171: .getHtmlElementById("a2");
172:
173: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
174:
175: final HtmlPage secondPage = (HtmlPage) anchor.click();
176:
177: assertEquals(new String[] { "clicked" }, collectedAlerts);
178: assertEquals("Second", secondPage.getTitleText());
179: }
180:
181: /**
182: * @throws Exception if the test fails
183: */
184: public void testClick_onClickHandler_returnFalse() throws Exception {
185: final String firstContent = "<html><head><title>First</title></head><body>\n"
186: + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
187: + "<a href='"
188: + URL_SECOND
189: + "' id='a2' "
190: + "onClick='alert(\"clicked\");return false;'>link to foo2</a>\n"
191: + "<a href='http://www.foo3.com' id='a3'>link to foo3</a>\n"
192: + "</body></html>";
193: final String secondContent = "<html><head><title>Second</title></head><body></body></html>";
194:
195: final WebClient client = new WebClient();
196: final List collectedAlerts = new ArrayList();
197: client.setAlertHandler(new CollectingAlertHandler(
198: collectedAlerts));
199:
200: final MockWebConnection webConnection = new MockWebConnection(
201: client);
202: webConnection.setResponse(URL_FIRST, firstContent);
203: webConnection.setResponse(URL_SECOND, secondContent);
204: client.setWebConnection(webConnection);
205:
206: final HtmlPage page = (HtmlPage) client.getPage(URL_FIRST);
207: final HtmlAnchor anchor = (HtmlAnchor) page
208: .getHtmlElementById("a2");
209:
210: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
211:
212: final HtmlPage secondPage = (HtmlPage) anchor.click();
213:
214: assertEquals(new String[] { "clicked" }, collectedAlerts);
215: assertSame(page, secondPage);
216: }
217:
218: /**
219: * @throws Exception if the test fails
220: */
221: public void testClick_onClickHandler_javascriptDisabled()
222: throws Exception {
223: final String htmlContent = "<html><head><title>foo</title></head><body>\n"
224: + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
225: + "<a href='http://www.foo2.com' id='a2' "
226: + "onClick='alert(\"clicked\")'>link to foo2</a>\n"
227: + "<a href='http://www.foo3.com' id='a3'>link to foo3</a>\n"
228: + "</body></html>";
229: final WebClient client = new WebClient();
230: client.setJavaScriptEnabled(false);
231:
232: final List collectedAlerts = new ArrayList();
233: client.setAlertHandler(new CollectingAlertHandler(
234: collectedAlerts));
235:
236: final MockWebConnection webConnection = new MockWebConnection(
237: client);
238: webConnection.setDefaultResponse(htmlContent);
239: client.setWebConnection(webConnection);
240:
241: final HtmlPage page = (HtmlPage) client.getPage(URL_GARGOYLE);
242: final HtmlAnchor anchor = (HtmlAnchor) page
243: .getHtmlElementById("a2");
244:
245: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
246:
247: final HtmlPage secondPage = (HtmlPage) anchor.click();
248:
249: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
250: final List expectedParameters = Collections.EMPTY_LIST;
251:
252: assertEquals("url", "http://www.foo2.com", secondPage
253: .getWebResponse().getUrl());
254: assertEquals("method", SubmitMethod.GET, webConnection
255: .getLastMethod());
256: assertEquals("parameters", expectedParameters, webConnection
257: .getLastParameters());
258: assertNotNull(secondPage);
259: }
260:
261: /**
262: * @throws Exception if the test fails
263: */
264: public void testClick_javascriptUrl() throws Exception {
265: final String htmlContent = "<html><head><title>foo</title></head><body>\n"
266: + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
267: + "<a href='javascript:alert(\"clicked\")' id='a2'>link to foo2</a>\n"
268: + "<a href='http://www.foo3.com' id='a3'>link to foo3</a>\n"
269: + "</body></html>";
270: final List collectedAlerts = new ArrayList();
271: final HtmlPage page = loadPage(htmlContent, collectedAlerts);
272:
273: final HtmlAnchor anchor = (HtmlAnchor) page
274: .getHtmlElementById("a2");
275:
276: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
277:
278: final HtmlPage secondPage = (HtmlPage) anchor.click();
279:
280: assertEquals(new String[] { "clicked" }, collectedAlerts);
281: assertSame(page, secondPage);
282: }
283:
284: /**
285: * @throws Exception if the test fails
286: */
287: public void testClick_javascriptUrl_javascriptDisabled()
288: throws Exception {
289: final String htmlContent = "<html><head><title>foo</title></head><body>\n"
290: + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
291: + "<a href='javascript:alert(\"clicked\")' id='a2'>link to foo2</a>\n"
292: + "<a href='http://www.foo3.com' id='a3'>link to foo3</a>\n"
293: + "</body></html>";
294: final WebClient client = new WebClient();
295: client.setJavaScriptEnabled(false);
296:
297: final List collectedAlerts = new ArrayList();
298: client.setAlertHandler(new CollectingAlertHandler(
299: collectedAlerts));
300:
301: final MockWebConnection webConnection = new MockWebConnection(
302: client);
303: webConnection.setDefaultResponse(htmlContent);
304: client.setWebConnection(webConnection);
305:
306: final HtmlPage page = (HtmlPage) client.getPage(URL_GARGOYLE);
307: final HtmlAnchor anchor = (HtmlAnchor) page
308: .getHtmlElementById("a2");
309:
310: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
311:
312: final HtmlPage secondPage = (HtmlPage) anchor.click();
313:
314: assertEquals(Collections.EMPTY_LIST, collectedAlerts);
315: assertSame(page, secondPage);
316: }
317:
318: /**
319: * @throws Exception if the test fails
320: */
321: public void testClick_javascriptUrl_InvalidReturn_RegressionTest()
322: throws Exception {
323: final String htmlContent = "<html><head><SCRIPT lang=\"JavaScript\">\n"
324: + "function doSubmit(formName){"
325: + " return false;\n"
326: + "}"
327: + "</SCRIPT></head><body>\n"
328: + "<form name='formName' method='POST' action='../foo'>\n"
329: + "<a href='.' id='testJavascript' name='testJavascript'"
330: + "onclick='return false'>Test Link </a>\n"
331: + "<input type='submit' value='Login' name='loginButton'>\n"
332: + "</form></body></html>";
333:
334: final HtmlPage page = loadPage(htmlContent);
335: final HtmlAnchor testAnchor = page
336: .getAnchorByName("testJavascript");
337: testAnchor.click(); // blows up here
338: }
339:
340: /**
341: * @throws Exception if the test fails
342: */
343: public void testClick_javascriptUrl_targetPageWithIframe()
344: throws Exception {
345: final String firstContent = " <html>\n"
346: + "<head><title>Page A</title></head>\n"
347: + "<body><a href='#' onclick=\"document.location.href='"
348: + URL_SECOND + "'\" id='link'>link</a></body>\n"
349: + "</html>";
350: final String secondContent = "<html>\n"
351: + "<head><title>Page B</title></head>\n"
352: + "<body><iframe src='" + URL_THIRD
353: + "'></iframe></body>\n" + "</html>";
354: final String thirdContent = "<html>\n"
355: + "<head><title>Page C</title></head>\n"
356: + "<body>test</body>\n" + "</html>";
357:
358: final WebClient client = new WebClient();
359: final MockWebConnection conn = new MockWebConnection(client);
360: conn.setResponse(URL_FIRST, firstContent);
361: conn.setResponse(URL_SECOND, secondContent);
362: conn.setResponse(URL_THIRD, thirdContent);
363: client.setWebConnection(conn);
364: final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST);
365: final HtmlAnchor a = (HtmlAnchor) firstPage
366: .getHtmlElementById("link");
367: final HtmlPage secondPage = (HtmlPage) a.click();
368: assertEquals("url", URL_SECOND, secondPage.getWebResponse()
369: .getUrl());
370: assertEquals("title", "Page B", secondPage.getTitleText());
371: }
372:
373: /**
374: * Test for new openLinkInNewWindow() method
375: * @throws Exception on test failure
376: */
377: public void testOpenLinkInNewWindow() throws Exception {
378: final String htmlContent = "<html><head><title>foo</title></head><body>\n"
379: + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
380: + "</body></html>";
381:
382: final HtmlPage page = loadPage(htmlContent);
383: final HtmlAnchor anchor = (HtmlAnchor) page
384: .getHtmlElementById("a1");
385:
386: assertEquals("size incorrect before test", 1, page
387: .getWebClient().getWebWindows().size());
388:
389: final HtmlPage secondPage = (HtmlPage) anchor
390: .openLinkInNewWindow();
391:
392: assertNotSame("new page not returned", page, secondPage);
393: assertInstanceOf("new page in wrong window type", secondPage
394: .getEnclosingWindow(), TopLevelWindow.class);
395: assertEquals("new window not created", 2, page.getWebClient()
396: .getWebWindows().size());
397: assertNotSame("new window not used", page.getEnclosingWindow(),
398: secondPage.getEnclosingWindow());
399: }
400:
401: /**
402: * Test the 'Referer' HTTP header
403: * @throws Exception on test failure
404: */
405: public void testClick_refererHeader() throws Exception {
406: final String firstContent = "<html><head><title>Page A</title></head>\n"
407: + "<body><a href='"
408: + URL_SECOND
409: + "' id='link'>link</a></body>\n" + "</html>";
410: final String secondContent = "<html><head><title>Page B</title></head>\n"
411: + "<body></body>\n" + "</html>";
412:
413: final WebClient client = new WebClient();
414: final MockWebConnection conn = new MockWebConnection(client);
415: conn.setResponse(URL_FIRST, firstContent);
416: conn.setResponse(URL_SECOND, secondContent);
417: client.setWebConnection(conn);
418: final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST);
419: final HtmlAnchor a = (HtmlAnchor) firstPage
420: .getHtmlElementById("link");
421: a.click();
422:
423: final Map lastAdditionalHeaders = conn
424: .getLastAdditionalHeaders();
425: assertEquals(URL_FIRST.toString(), lastAdditionalHeaders
426: .get("Referer"));
427: }
428:
429: /**
430: * https://sourceforge.net/tracker/index.php?func=detail&aid=1587110&group_id=47038&atid=448266
431: *
432: * Links with an href and a non-false returning onclick that opens a new window should still
433: * open the href in the first window.
434: *
435: * @throws Exception on test failure
436: */
437: public void testCorrectLinkTargetWhenOnclickOpensWindow()
438: throws Exception {
439: final String firstContent = "<html><head><title>First</title></head><body>\n"
440: + "<a href='"
441: + URL_SECOND
442: + "' id='clickme' onclick=\"window.open('', 'newWindow');\">X</a>\n"
443: + "</body></html>";
444: final String secondContent = "<html><head><title>Second</title></head><body></body></html>";
445:
446: final WebClient client = new WebClient();
447: final List collectedAlerts = new ArrayList();
448: client.setAlertHandler(new CollectingAlertHandler(
449: collectedAlerts));
450:
451: final MockWebConnection webConnection = new MockWebConnection(
452: client);
453: webConnection.setResponse(URL_FIRST, firstContent);
454: webConnection.setResponse(URL_SECOND, secondContent);
455: client.setWebConnection(webConnection);
456:
457: final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST);
458: final HtmlAnchor anchor = (HtmlAnchor) firstPage
459: .getHtmlElementById("clickme");
460: final HtmlPage secondPage = (HtmlPage) anchor.click();
461:
462: assertEquals("Second window did not open", 2, client
463: .getWebWindows().size());
464: assertNotSame("New Page was not returned", firstPage,
465: secondPage);
466: assertEquals("Wrong new Page returned", "Second", secondPage
467: .getTitleText());
468: assertSame("New Page not in correct WebWindow", firstPage
469: .getEnclosingWindow(), secondPage.getEnclosingWindow());
470: }
471:
472: /**
473: * @throws Exception if an error occurs
474: */
475: public void testPreventDefault() throws Exception {
476: testPreventDefault(BrowserVersion.FIREFOX_2);
477: testPreventDefault(BrowserVersion.INTERNET_EXPLORER_7_0);
478: }
479:
480: private void testPreventDefault(final BrowserVersion browserVersion)
481: throws Exception {
482: final String html = "<html><head><script>\n"
483: + " function handler(e) {\n"
484: + " if (e)\n"
485: + " e.preventDefault();\n"
486: + " else\n"
487: + " return false;\n"
488: + " }\n"
489: + " function init() {\n"
490: + " document.getElementById('a1').onclick = handler;\n"
491: + " }\n" + "</script></head>\n"
492: + "<body onload='init()'>\n" + "<a href='" + URL_SECOND
493: + "' id='a1'>Test</a>\n" + "</body></html>";
494:
495: final HtmlPage page = (HtmlPage) loadPage(browserVersion, html,
496: null);
497: final HtmlAnchor a1 = (HtmlAnchor) page
498: .getHtmlElementById("a1");
499: final HtmlPage secondPage = (HtmlPage) a1.click();
500: assertEquals(URL_GARGOYLE, secondPage.getWebResponse().getUrl());
501: }
502: }
|