KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > gargoylesoftware > htmlunit > WebTestCase


1 /*
2  * Copyright (c) 2002, 2005 Gargoyle Software Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12  * 3. The end-user documentation included with the redistribution, if any, must
13  * include the following acknowledgment:
14  *
15  * "This product includes software developed by Gargoyle Software Inc.
16  * (http://www.GargoyleSoftware.com/)."
17  *
18  * Alternately, this acknowledgment may appear in the software itself, if
19  * and wherever such third-party acknowledgments normally appear.
20  * 4. The name "Gargoyle Software" must not be used to endorse or promote
21  * products derived from this software without prior written permission.
22  * For written permission, please contact info@GargoyleSoftware.com.
23  * 5. Products derived from this software may not be called "HtmlUnit", nor may
24  * "HtmlUnit" appear in their name, without prior written permission of
25  * Gargoyle Software Inc.
26  *
27  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30  * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  */

38 package com.gargoylesoftware.htmlunit;
39
40 import java.io.BufferedInputStream;
41 import java.io.File;
42 import java.io.FileInputStream;
43 import java.io.FileNotFoundException;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.net.MalformedURLException;
47 import java.net.URL;
48 import java.util.List;
49 import java.util.ListIterator;
50
51 import junit.framework.AssertionFailedError;
52
53 import org.apache.commons.io.FileUtils;
54 import org.apache.commons.io.IOUtils;
55 import org.apache.commons.lang.StringUtils;
56 import org.apache.commons.logging.Log;
57 import org.apache.commons.logging.LogFactory;
58
59 import com.gargoylesoftware.base.testing.BaseTestCase;
60 import com.gargoylesoftware.htmlunit.html.HtmlPage;
61
62 /**
63  * Common superclass for HtmlUnit tests
64  *
65  * @version $Revision: 1.17 $
66  * @author <a HREF="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
67  * @author David D. Kilzer
68  * @author Marc Guillemot
69  * @author Chris Erskine
70  * @author Michael Ottati
71  */

72 public abstract class WebTestCase extends BaseTestCase {
73     /** Constant for the url http://first which is used in the tests. */
74     public static final URL URL_FIRST;
75
76     /** Constant for the url http://second which is used in the tests. */
77     public static final URL URL_SECOND;
78
79     /** Constant for the url http://third which is used in the tests. */
80     public static final URL URL_THIRD;
81
82     /** Constant for the url http://www.gargoylesoftware.com which is used in the tests. */
83     public static final URL URL_GARGOYLE;
84
85     /**
86      * The name of the system property used to determine if files should be generated
87      * or not in {@link #createTestPageForRealBrowserIfNeeded(String,List)}
88      */

89     public static final String PROPERTY_GENERATE_TESTPAGES
90         = "com.gargoylesoftware.htmlunit.WebTestCase.GenerateTestpages";
91
92     static {
93         try {
94             URL_FIRST = new URL("http://first");
95             URL_SECOND = new URL("http://second");
96             URL_THIRD = new URL("http://third");
97             URL_GARGOYLE = new URL("http://www.gargoylesoftware.com/");
98         }
99         catch( final MalformedURLException e ) {
100             // This is theoretically impossible.
101
throw new IllegalStateException("Unable to create url constants");
102         }
103     }
104     /**
105      * Create an instance.
106      * @param name The name of the test.
107      */

108     public WebTestCase( final String name ) {
109         super( name );
110     }
111
112
113     /**
114      * Load a page with the specified html.
115      * @param html The html to use.
116      * @return The new page.
117      * @throws Exception if something goes wrong.
118      */

119     protected static final HtmlPage loadPage( final String html ) throws Exception {
120         return loadPage(html, null);
121     }
122
123    /**
124      * Load a page with the specified html and collect alerts into the list.
125      * @param html The HTML to use.
126      * @param collectedAlerts The list to hold the alerts.
127      * @return The new page.
128      * @throws Exception If something goes wrong.
129      */

130     protected static final HtmlPage loadPage( final String html, final List collectedAlerts )
131         throws Exception {
132      return loadPage(html,collectedAlerts, URL_GARGOYLE);
133     }
134
135
136     /**
137      * Return the log that is being used for all testing objects
138      * @return The log.
139      */

140     protected final Log getLog() {
141         return LogFactory.getLog(getClass());
142     }
143
144
145     /**
146      * Load a page with the specified html and collect alerts into the list.
147      * @param html The HTML to use.
148      * @param collectedAlerts The list to hold the alerts.
149      * @param url The URL that will use as the document host for this page
150      * @return The new page.
151      * @throws Exception If something goes wrong.
152      */

153     protected static final HtmlPage loadPage( final String html, final List collectedAlerts, final URL url )
154
155         throws Exception {
156
157         final WebClient client = new WebClient();
158         if( collectedAlerts != null ) {
159             client.setAlertHandler( new CollectingAlertHandler(collectedAlerts) );
160         }
161
162         final MockWebConnection webConnection = new MockWebConnection( client );
163         webConnection.setDefaultResponse( html );
164         client.setWebConnection( webConnection );
165
166         final HtmlPage page = (HtmlPage) client.getPage(url);
167         return page;
168     }
169
170
171     /**
172      * Assert that the specified object is null.
173      * @param object The object to check.
174      */

175     public static void assertNull( final Object object ) {
176         if( object != null ) {
177             throw new AssertionFailedError("Expected null but found ["+object+"]");
178         }
179     }
180
181     /**
182      * Return an input stream for the specified file name. Refer to {@link #getFileObject(String)}
183      * for details on how the file is located.
184      * @param fileName The base file name.
185      * @return The input stream.
186      * @throws FileNotFoundException If the file cannot be found.
187      */

188     public static InputStream getFileAsStream( final String fileName ) throws FileNotFoundException {
189         return new BufferedInputStream(new FileInputStream(getFileObject(fileName)));
190     }
191
192     /**
193      * Return a File object for the specified file name. This is different from just
194      * <code>new File(fileName)</code> because it will adjust the location of the file
195      * depending on how the code is being executed.
196      *
197      * @param fileName The base filename.
198      * @return The new File object.
199      * @throws FileNotFoundException if !file.exists()
200      */

201     public static File getFileObject( final String fileName ) throws FileNotFoundException {
202         final String localizedName = fileName.replace( '/', File.separatorChar );
203
204         File file = new File(localizedName);
205         if( file.exists() == false ) {
206             file = new File("../../"+localizedName);
207         }
208
209         if( file.exists() == false ) {
210             try {
211                 System.out.println("currentDir="+new File(".").getCanonicalPath());
212             }
213             catch( final IOException e ) {
214                 e.printStackTrace();
215             }
216             throw new FileNotFoundException(localizedName);
217         }
218         return file;
219     }
220
221     /**
222      * Generates an instrumented html file in the temporary dir to easily make a manual test in a real browser.
223      * The file is generated only if the system property {@link #PROPERTY_GENERATE_TESTPAGES} is set.
224      * @param content the content of the html page
225      * @param expectedAlerts the expected alerts
226      * @throws IOException if writing file fails
227      */

228     protected void createTestPageForRealBrowserIfNeeded(final String content, final List expectedAlerts)
229         throws IOException {
230         final Log log = LogFactory.getLog(WebTestCase.class);
231         if (System.getProperty(PROPERTY_GENERATE_TESTPAGES) != null) {
232             // should be optimized....
233

234             // calls to alert() should be replaced by call to custom function
235
String newContent = StringUtils.replace(content,
236                     "alert(", "htmlunitReserved_catchedAlert(");
237             
238             final String instrumentationJS = createInstrumentationScript(expectedAlerts);
239             
240             // first version, we assume that there is a <head> and a </body> or a </frameset>
241
newContent = StringUtils.replaceOnce(newContent, "<head>", "<head>" + instrumentationJS);
242             final String endScript = "\n<script>htmlunitReserved_addSummaryAfterOnload();</script>\n";
243             if (newContent.indexOf("</body>") != -1) {
244                 newContent = StringUtils.replaceOnce(newContent, "</body>", endScript + "</body>");
245             }
246             else {
247                 throw new RuntimeException("Currently only content with a <head> and a </body> is supported");
248             }
249
250             final File f = File.createTempFile("test", ".html");
251             FileUtils.writeStringToFile(f, newContent, "ISO-8859-1");
252             log.info("Test file written: " + f.getAbsolutePath());
253         }
254         else {
255             log.debug("System property \"" + PROPERTY_GENERATE_TESTPAGES
256                     + "\" not set, don't generate test html page for real browser");
257         }
258     }
259
260     /**
261      * @param expectedAlerts the list of the expected alerts
262      * @return the script to be included at the beginning of the generated html file
263      * @throws IOException in case of problem
264      */

265     private String createInstrumentationScript(final List expectedAlerts) throws IOException {
266         // generate the js code
267
final InputStream is = getClass().getClassLoader().getResourceAsStream(
268                 "com/gargoylesoftware/htmlunit/alertVerifier.js");
269         final String baseJS = IOUtils.toString(is);
270         IOUtils.closeQuietly(is);
271         
272         final StringBuffer sb = new StringBuffer();
273         sb.append("\n<script type='text/javascript'>\n");
274         sb.append("var htmlunitReserved_tab = [");
275         for (final ListIterator iter = expectedAlerts.listIterator(); iter.hasNext();)
276         {
277             if (iter.hasPrevious()) {
278                 sb.append(", ");
279             }
280             final String message = (String) iter.next();
281             sb.append("{expected: \"").append(message).append("\"}");
282         }
283         sb.append("];\n\n");
284         sb.append(baseJS);
285         sb.append("</script>\n");
286         return sb.toString();
287     }
288     /**
289      * Convenience method to pull the MockWebConnection out of an HtmlPage created with
290      * the loadPage method.
291      * @param page HtmlPage to get the connection from
292      * @return the MockWebConnection that served this page
293      */

294     protected static final MockWebConnection getMockConnection(final HtmlPage page) {
295         return (MockWebConnection) page.getWebClient().getWebConnection();
296     }
297 }
298
299
Popular Tags