View Javadoc

1   /**
2    * Copyright (c) 2002-2015, JWebUnit team.
3    *
4    * This file is part of JWebUnit.
5    *
6    * JWebUnit is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * JWebUnit is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public License
17   * along with JWebUnit.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package net.sourceforge.jwebunit.junit;
20  
21  import static org.hamcrest.CoreMatchers.equalTo;
22  import static org.hamcrest.CoreMatchers.not;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertFalse;
25  import static org.junit.Assert.assertNotNull;
26  import static org.junit.Assert.assertThat;
27  import static org.junit.Assert.assertTrue;
28  import static org.junit.Assert.fail;
29  
30  import java.awt.Image;
31  import java.awt.image.BufferedImage;
32  import java.io.BufferedOutputStream;
33  import java.io.File;
34  import java.io.FileOutputStream;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.OutputStream;
38  import java.io.PrintStream;
39  import java.net.MalformedURLException;
40  import java.net.URL;
41  import java.text.MessageFormat;
42  import java.util.Iterator;
43  import java.util.List;
44  import java.util.Locale;
45  import java.util.Map;
46  import java.util.ResourceBundle;
47  
48  import javax.imageio.ImageIO;
49  import javax.servlet.http.Cookie;
50  
51  import net.sourceforge.jwebunit.api.HttpHeader;
52  import net.sourceforge.jwebunit.api.IElement;
53  import net.sourceforge.jwebunit.api.ITestingEngine;
54  import net.sourceforge.jwebunit.exception.ExpectedJavascriptAlertException;
55  import net.sourceforge.jwebunit.exception.ExpectedJavascriptConfirmException;
56  import net.sourceforge.jwebunit.exception.ExpectedJavascriptPromptException;
57  import net.sourceforge.jwebunit.exception.TestingEngineResponseException;
58  import net.sourceforge.jwebunit.exception.UnableToSetFormException;
59  import net.sourceforge.jwebunit.html.Table;
60  import net.sourceforge.jwebunit.javascript.JavascriptAlert;
61  import net.sourceforge.jwebunit.javascript.JavascriptConfirm;
62  import net.sourceforge.jwebunit.javascript.JavascriptPrompt;
63  import net.sourceforge.jwebunit.util.TestContext;
64  import net.sourceforge.jwebunit.util.TestingEngineRegistry;
65  
66  import org.apache.regexp.RE;
67  import org.apache.regexp.RESyntaxException;
68  
69  /**
70   * Provides a high-level API for basic web application navigation and validation by providing
71   * JUnit assertions. It supports use of a property file for web resources (a la Struts), though a resource file for the
72   * app is not required.
73   *
74   * @author Julien Henry
75   * @author Jim Weaver
76   * @author Wilkes Joiner
77   */
78  public class WebTester {
79      private ITestingEngine testingEngine = null;
80  
81      private TestContext testContext = null;
82  
83      /**
84       * This is the testing engine key that the webtester will use to find the correct testing engine from the registry.
85       */
86      private String testingEngineKey = null;
87  
88      /**
89       * Provides access to the testing engine for subclasses - in case functionality not yet wrappered required by test.
90       *
91       * If the testing engine is not explicitly set the JWebUnit framework will default to using the orignal testing engine,
92       * which is, htmlunit.
93       *
94       * @return IJWebUnitDialog instance used to wrapper htmlunit conversation.
95       * @deprecated You should not use plugin specific functionality. Please ask for a new core feature instead.
96       */
97      public ITestingEngine getDialog() {
98          return getTestingEngine();
99      }
100 
101     /**
102      * Set the base url for the test context.
103      *
104      * @param url Base url value - A trailing "/" is appended if not provided.
105      */
106     public void setBaseUrl(String url) {
107       getTestContext().setBaseUrl(url);
108     }
109 
110     /**
111      * Set the base url for the test context.
112      *
113      * @param url Base url value - A trailing "/" is appended if not provided.
114      */
115     public void setBaseUrl(URL url) {
116       getTestContext().setBaseUrl(url);
117     }
118 
119     /**
120      * Protected version of deprecated getDialog(). Not deprecated for internal use.
121      *
122      * @return IJWebUnitDialog instance.
123      */
124     public ITestingEngine getTestingEngine() {
125         if (testingEngine == null) {
126             // defaulting to the HtmlUnitDialog implementation.
127             testingEngine = initializeDialog();
128         }
129         return testingEngine;
130     }
131 
132     /**
133      * Initializes the IJWebUnitDialog when the testing engine is null. This will construct a new instance of the testing engine based
134      * on the specified testing engine key.
135      */
136     protected ITestingEngine initializeDialog() {
137         ITestingEngine theIJWebUnitDialog = null;
138         String theTestingEngineKey = getTestingEngineKey();
139         Class<?> theClass;
140         try {
141             theClass = TestingEngineRegistry
142                     .getTestingEngineClass(theTestingEngineKey);
143         } catch (ClassNotFoundException e1) {
144             throw new RuntimeException(e1);
145         }
146         try {
147             theIJWebUnitDialog = (ITestingEngine) theClass.newInstance();
148         } catch (InstantiationException e) {
149             e.printStackTrace();
150             throw new RuntimeException(
151                     "Can't Instantiate Testing Engine with class [" + theClass
152                             + "] with key [" + theTestingEngineKey + "].", e);
153         } catch (IllegalAccessException e) {
154             e.printStackTrace();
155             throw new RuntimeException("IllegalAccessException using class ["
156                     + theClass + "] with key [" + theTestingEngineKey + "].", e);
157         }
158 
159         return theIJWebUnitDialog;
160     }
161 
162     /**
163      * Close the current conversation.
164      */
165     public void closeBrowser() {
166         try {
167             getTestingEngine().closeBrowser();
168         } catch (ExpectedJavascriptAlertException e) {
169             fail("You previously tell that alert with message ["
170                     + e.getAlertMessage()
171                     + "] was expected, but nothing appeared.");
172         } catch (ExpectedJavascriptConfirmException e) {
173             fail("You previously tell that confirm with message ["
174                     + e.getConfirmMessage()
175                     + "] was expected, but nothing appeared.");
176         } catch (ExpectedJavascriptPromptException e) {
177             fail("You previously tell that prompt with message ["
178                     + e.getPromptMessage()
179                     + "] was expected, but nothing appeared.");
180         }
181     }
182 
183     /**
184      * Close the current window.
185      */
186     public void closeWindow() {
187         getTestingEngine().closeWindow();
188     }
189 
190     /**
191      * Set the testing engine.
192      *
193      * @param aIJWebUnitDialog Testing engine.
194      */
195     public void setDialog(ITestingEngine aIJWebUnitDialog) {
196         testingEngine = aIJWebUnitDialog;
197     }
198 
199     /**
200      * Provide access to test testContext.
201      *
202      * @return TestContext
203      */
204     public TestContext getTestContext() {
205         if (testContext == null) {
206             // defaulting to the original implementation.
207             testContext = new TestContext();
208         }
209         return testContext;
210     }
211 
212     /**
213      * Allows setting an external test testContext class that might be extended from TestContext. Example:
214      * setTestContext(new CompanyATestContext());
215      *
216      * CompanyATestContext extends TestContext.
217      *
218      * @param aTestContext
219      */
220     public void setTestContext(TestContext aTestContext) {
221         testContext = aTestContext;
222     }
223 
224     /**
225      * Begin conversation at a URL absolute or relative to base URL. Use
226      * {@link TestContext#setBaseUrl(String) getTestContext().setBaseUrl(String)} to define base URL. Absolute URL
227      * should start with "http://", "https://" or "www.".
228      *
229      * @param url absolute or relative URL (relative to base URL).
230      * @throws TestingEngineResponseException If something bad happend (404)
231      */
232     public void beginAt(String aRelativeURL) throws TestingEngineResponseException {
233         try {
234             getTestingEngine().beginAt(createUrl(aRelativeURL, getTestContext().getBaseUrl()), testContext);
235         } catch (MalformedURLException e) {
236             fail(e.getLocalizedMessage());
237         }
238 
239     }
240 
241     /**
242      * This way of creating URL is not standard as absolute path are not correctly handled. We have to keep this
243      * non standard method for {@link #beginAt(String)} that advertise a bad usage for a long time.
244      * @param url Absolute or relative URL. If start with '/', then it is incorrectly appended to baseURL.
245      * @param baseURL Base URL of the page
246      * @return Final absolute URL.
247      * @throws MalformedURLException
248      */
249     @Deprecated
250     private URL createUrl(String url, URL baseURL) throws MalformedURLException {
251         if (url.startsWith("http://") || url.startsWith("https://")
252                 || url.startsWith("file://")) {
253             return new URL(url);
254         } else if (url.startsWith("www.")) {
255             return new URL("http://" + url);
256         } else {
257             url = url.startsWith("/") ? url.substring(1) : url;
258             return new URL(baseURL, url);
259         }
260     }
261 
262     /**
263      *
264      * @param url Absolute or relative URL
265      * @param baseURL Base URL of the page
266      * @return Final absolute URL.
267      * @throws MalformedURLException
268      */
269     private URL createUrlFixed(String url, URL baseURL) throws MalformedURLException {
270         if (url.startsWith("http://") || url.startsWith("https://") //Absolute URL
271                 || url.startsWith("file://")) {
272             return new URL(url);
273         } else if (url.startsWith("www.")) { //Absolute URL with missing scheme (accepted by some browsers)
274             return new URL("http://" + url);
275         } else { //Relative path
276             return new URL(baseURL, url);
277         }
278     }
279 
280     /**
281      * Return the value of a web resource based on its key. This translates to a property file lookup with the locale
282      * based on the current TestContext.
283      *
284      * @param key name of the web resource.
285      * @return value of the web resource, encoded according to TestContext.
286      */
287     public String getMessage(String key) {
288         String message = "";
289         Locale locale = testContext.getLocale();
290         try {
291             message = ResourceBundle.getBundle(
292                     getTestContext().getResourceBundleName(), locale)
293                     .getString(key);
294         } catch (Exception e) {
295             e.printStackTrace();
296             throw new RuntimeException("No message found for key [" + key
297                     + "].", e);
298         }
299         return message;
300     }
301 
302     /**
303      * Return the value of a web resource based on its key, using MessageFormat
304      * to perform parametric substitution with formatting.
305      *
306      * @see MessageFormat
307      * @param key
308      *            name of the web resource.
309      * @param args
310      *            array of arguments to be formatted into message
311      * @return value of the web resource after formatting
312      */
313     public String getMessage(String key, Object[] args) {
314         String message = getMessage(key);
315 
316         // TODO: Struts escapes single quotes... maybe this should too
317 
318         MessageFormat format = new MessageFormat(message, getTestContext().getLocale());
319 
320         return format.format(args);
321     }
322 
323     // Assertions
324 
325     /**
326      * Assert that the page response has a particular code.
327      *
328      * @param status the expected status code
329      */
330     public void assertResponseCode(int status) {
331       assertEquals( status, getTestingEngine().getServerResponseCode() );
332     }
333 
334     /**
335      * Assert that the page response has a particular code between lower and higher
336      * (<code>lower <= status <= higher</code>).
337      *
338      * @param lower the lower bound for the expected status code
339      * @param higher the upper bound for the expected status code
340      */
341     public void assertResponseCodeBetween(int lower, int higher) {
342       assertTrue( getTestingEngine().getServerResponseCode() >= lower && getTestingEngine().getServerResponseCode() <= higher );
343     }
344 
345   /**
346    * Should the tester ignore failing status codes (300+)? Otherwise,
347    * failing status codes will throw an exception.
348    *
349    * @param ignore
350    */
351     public void setIgnoreFailingStatusCodes(boolean ignore) {
352       getTestingEngine().setIgnoreFailingStatusCodes(ignore);
353     }
354 
355     /**
356      * Assert a header is present.
357      *
358      * @param name The header to find
359      */
360     public void assertHeaderPresent(String name) {
361       assertFalse( "header '" + name + "' not present", getTestingEngine().getHeader(name) == null );
362     }
363 
364     /**
365      * Assert a header is NOT present.
366      *
367      * @param name The header to find
368      */
369     public void assertHeaderNotPresent(String name) {
370       assertTrue( "header '" + name + "' present", getTestingEngine().getHeader(name) == null );
371     }
372 
373     /**
374      * Assert a header is equal to a particular value.
375      *
376      * @param name Header to find
377      * @param value Value to compare against
378      */
379     public void assertHeaderEquals(String name, String value) {
380       assertEquals( value, getTestingEngine().getHeader(name) );
381     }
382 
383     /**
384      * Assert a header matches a particular pattern.
385      *
386      * @param name Header to find
387      * @param regexp Pattern to compare against
388      */
389     public void assertHeaderMatches(String name, String regexp) {
390       assertMatch("Unable to match [" + regexp + "] in header [" + name + "]", regexp, getTestingEngine().getHeader(name));
391     }
392 
393     /**
394      * Get a particular header value.
395      *
396      * @param name Header to find
397      * @return The found header value, or null
398      */
399     public String getHeader(String name) {
400       return getTestingEngine().getHeader(name);
401     }
402 
403     /**
404      * Get all response headers.
405      *
406      * @return A map of response headers
407      * @deprecated This method do not deal with several headers with same name. Use {@link #getResponseHeaders()} instead.
408      */
409     @Deprecated
410     public Map<String, String> getAllHeaders() {
411         return getTestingEngine().getAllHeaders();
412     }
413 
414     /**
415      * Return all HTTP headers that are in last response. It is possible to have several headers with same name.
416      *
417      * @return A list of {@link HttpHeader} elements.
418      */
419     public List<HttpHeader> getResponseHeaders() {
420         return getTestingEngine().getResponseHeaders();
421     }
422 
423     /**
424      * Assert title of current html page in conversation matches an expected
425      * value.
426      *
427      * @param title
428      *            expected title value
429      */
430     public void assertTitleEquals(String title) {
431         assertEquals(title, getTestingEngine().getPageTitle());
432     }
433 
434     /**
435      * Assert title of current html page in conversation is not
436      * equal to another value.
437      *
438      * @param title
439      *            unexpected title value
440      * @deprecated Replaced by {@link #assertTitleNotEquals(String)}
441      */
442     @Deprecated
443     public void assertTitleNotSame(String title) {
444       assertTitleNotEquals(title);
445     }
446 
447     /**
448      * Assert title of current html page in conversation is not
449      * equal to another value.
450      *
451      * @param title
452      *            unexpected title value
453      */
454     public void assertTitleNotEquals(String title) {
455       assertThat(title, not(equalTo(getTestingEngine().getPageTitle())));
456     }
457 
458     /**
459      * Assert title of current html page in conversation matches an expected regexp.
460      *
461      * @param regexp expected title regexp
462      */
463     public void assertTitleMatch(String regexp) {
464       assertMatch("Unable to match [" + regexp + "] in title", regexp, getTestingEngine().getPageTitle());
465     }
466 
467     /**
468      * Assert title of current html page matches the value of a specified web
469      * resource.
470      *
471      * @param titleKey
472      *            web resource key for title
473      */
474     public void assertTitleEqualsKey(String titleKey) {
475         assertEquals(getMessage(titleKey), getTestingEngine().getPageTitle());
476     }
477 
478     /**
479      * Assert title of current page matches formatted message resource
480      *
481      * @param titleKey
482      * @param args
483      */
484     public void assertTitleEqualsKey(String titleKey, Object[] args) {
485         assertEquals(getMessage(titleKey, args), getTestingEngine().getPageTitle());
486     }
487 
488     /**
489      * Assert that a web resource's value is present.
490      *
491      * @param key
492      *            web resource name
493      */
494     public void assertKeyPresent(String key) {
495         assertTextPresent(getMessage(key));
496     }
497 
498     /**
499      * Assert that a web resource's value (with formatting) is present
500      *
501      * @param key
502      * @param args
503      */
504     public void assertKeyPresent(String key, Object[] args) {
505         assertTextPresent(getMessage(key, args));
506     }
507 
508     /**
509      * Assert that supplied text is present.
510      *
511      * @param text
512      */
513     public void assertTextPresent(String text) {
514         if (!(getTestingEngine().getPageText().contains(text)))
515             fail("Expected text not found in current page: [" + text
516                     + "]\n Page content was: ["
517                     + getTestingEngine().getPageText() + "]");
518     }
519 
520     /**
521      * Assert that supplied regexp is matched in the text of a page.
522      *
523      * @param regexp
524      */
525     public void assertMatch(String regexp) {
526         RE re = getRE(regexp);
527         if (!re.match(getTestingEngine().getPageText()))
528             fail("Expected rexexp not matched in response: [" + regexp
529                     + "]");
530     }
531 
532     /**
533      * Assert a given string matches a given regular expression.
534      *
535      * @param regexp
536      * @param text
537      */
538     public void assertMatch(String regexp, String text) {
539       assertMatch("Expected rexexp '" + regexp + "' not matched in text '" + text + "'", regexp, text);
540     }
541 
542     /**
543      * Assert a given string does not match a given regular expression.
544      *
545      * @param regexp
546      * @param text
547      */
548     public void assertNotMatch(String regexp, String text) {
549       assertNotMatch("Expected rexexp '" + regexp + "' matched in text '" + text + "'", regexp, text);
550     }
551 
552 
553     /**
554      * Assert a given string matches a given regular expression.
555      *
556      * @param regexp
557      * @param text
558      */
559     public void assertMatch(String message, String regexp, String text) {
560         RE re = getRE(regexp);
561         if (!re.match(text))
562             fail(message);
563     }
564 
565     /**
566      * Assert a given string does not match a given regular expression.
567      *
568      * @param regexp
569      * @param text
570      */
571     public void assertNotMatch(String message, String regexp, String text) {
572         RE re = getRE(regexp);
573         if (re.match(text))
574             fail(message);
575     }
576 
577     /**
578      * Assert that a web resource's value is not present.
579      *
580      * @param key web resource name
581      */
582     public void assertKeyNotPresent(String key) {
583         assertTextNotPresent(getMessage(key));
584     }
585 
586     /**
587      * Assert that a web resource's formatted value is not present.
588      *
589      * @param key
590      *            web resource name
591      */
592     public void assertKeyNotPresent(String key, Object[] args) {
593         assertTextNotPresent(getMessage(key, args));
594     }
595 
596     /**
597      * Assert that supplied text is not present.
598      *
599      * @param text
600      */
601     public void assertTextNotPresent(String text) {
602         if (getTestingEngine().getPageText().contains(text))
603             fail("Text found in response when not expected: [" + text
604                     + "]");
605     }
606 
607     /**
608      * Assert that supplied regexp is not present.
609      *
610      * @param regexp
611      */
612     public void assertNoMatch(String regexp) {
613       assertNotMatch("Regexp matched in response when not expected: [" + regexp + "]",
614         regexp,
615          getTestingEngine().getPageText());
616     }
617 
618     /**
619      *
620      * @param tableSummaryNameOrId
621      * @return Object that represent a html table in a way independent from plugin.
622      */
623     public Table getTable(String tableSummaryNameOrId) {
624         return getTestingEngine().getTable(tableSummaryNameOrId);
625     }
626 
627     /**
628      * Assert that a table with a given summary or id value is present.
629      *
630      * @param tableSummaryNameOrId summary, name or id attribute value of table
631      */
632     public void assertTablePresent(String tableSummaryNameOrId) {
633         if (!getTestingEngine().hasTable(tableSummaryNameOrId))
634             fail("Unable to locate table \"" + tableSummaryNameOrId
635                     + "\"");
636     }
637 
638     /**
639      * Assert that a table with a given summary or id value is not present.
640      *
641      * @param tableSummaryNameOrId summary, name or id attribute value of table
642      */
643     public void assertTableNotPresent(String tableSummaryNameOrId) {
644         if (getTestingEngine().hasTable(tableSummaryNameOrId))
645             fail("Located table \"" + tableSummaryNameOrId + "\"");
646     }
647 
648     /**
649      * Assert that the value of a given web resource is present in a specific table.
650      *
651      * @param tableSummaryOrId summary or id attribute value of table
652      * @param key web resource name
653      */
654     public void assertKeyInTable(String tableSummaryOrId, String key) {
655         assertTextInTable(tableSummaryOrId, getMessage(key));
656     }
657 
658     /**
659      * Assert that the value of a given web resource is present in a specific
660      * table.
661      *
662      * @param tableSummaryOrId
663      *            summary or id attribute value of table
664      * @param key
665      *            web resource name
666      */
667     public void assertKeyInTable(String tableSummaryOrId, String key, Object[] args) {
668         assertTextInTable(tableSummaryOrId, getMessage(key, args));
669     }
670 
671     /**
672      * Assert that supplied text is present in a specific table.
673      *
674      * @param tableSummaryNameOrId
675      *            summary, name or id attribute value of table
676      * @param text
677      */
678     public void assertTextInTable(String tableSummaryNameOrId, String text) {
679         assertTablePresent(tableSummaryNameOrId);
680         assertTrue("Could not find: [" + text + "]" + "in table ["
681                 + tableSummaryNameOrId + "]", getTestingEngine().getTable(
682                 tableSummaryNameOrId).hasText(text));
683     }
684 
685     /**
686      * Assert that supplied regexp is matched in a specific table.
687      *
688      * @param tableSummaryNameOrId summary, name or id attribute value of table
689      * @param regexp
690      */
691     public void assertMatchInTable(String tableSummaryNameOrId, String regexp) {
692         assertTablePresent(tableSummaryNameOrId);
693         assertTrue("Could not match: [" + regexp + "]" + "in table ["
694                 + tableSummaryNameOrId + "]", getTestingEngine().getTable(
695                 tableSummaryNameOrId).hasMatch(regexp));
696     }
697 
698     /**
699      * Assert that the values of a set of web resources are all present in a specific table.
700      *
701      * @param tableSummaryOrId summary, name or id attribute value of table
702      * @param keys Array of web resource names.
703      */
704     public void assertKeysInTable(String tableSummaryOrId, String[] keys) {
705         for (int i = 0; i < keys.length; i++) {
706             assertKeyInTable(tableSummaryOrId, keys[i]);
707         }
708     }
709 
710     /**
711      * Assert that the values of a set of web resources are all present in a
712      * specific table.
713      *
714      * @param tableSummaryOrId
715      *            summary or id attribute value of table
716      * @param keys
717      *            Array of web resource names.
718      */
719     public void assertKeysInTable(String tableSummaryOrId, String[] keys, Object[][] args) {
720         for (int i = 0; i < keys.length; i++) {
721             assertKeyInTable(tableSummaryOrId, keys[i], args[i]);
722         }
723     }
724 
725     /**
726      * Assert that a set of text values are all present in a specific table.
727      *
728      * @param tableSummaryOrId
729      *            summary, name or id attribute value of table
730      * @param text
731      *            Array of expected text values.
732      */
733     public void assertTextInTable(String tableSummaryOrId, String[] text) {
734         for (int i = 0; i < text.length; i++) {
735             assertTextInTable(tableSummaryOrId, text[i]);
736         }
737     }
738 
739     /**
740      * Assert that a set of regexp values are all matched in a specific table.
741      *
742      * @param tableSummaryOrId summary, name or id attribute value of table
743      * @param text Array of expected regexps to match.
744      */
745     public void assertMatchInTable(String tableSummaryOrId, String[] regexp) {
746         for (int i = 0; i < regexp.length; i++) {
747             assertMatchInTable(tableSummaryOrId, regexp[i]);
748         }
749     }
750 
751     /**
752      * Assert that the value of a given web resource is not present in a specific table.
753      *
754      * @param tableSummaryOrId summary, name or id attribute value of table
755      * @param key web resource name
756      */
757     public void assertKeyNotInTable(String tableSummaryOrId, String key) {
758         assertTextNotInTable(tableSummaryOrId, getMessage(key));
759     }
760 
761     /**
762      * Assert that supplied text is not present in a specific table.
763      *
764      * @param tableSummaryNameOrId summary, name or id attribute value of table
765      * @param text
766      */
767     public void assertTextNotInTable(String tableSummaryNameOrId, String text) {
768         assertTablePresent(tableSummaryNameOrId);
769         assertTrue("Found text: [" + text + "] in table ["
770                 + tableSummaryNameOrId + "]", !getTestingEngine().getTable(
771                 tableSummaryNameOrId).hasText(text));
772     }
773 
774     /**
775      * Assert that none of a set of text values are present in a specific table.
776      *
777      * @param tableSummaryNameOrId summary, name or id attribute value of table
778      * @param text Array of text values
779      */
780     public void assertTextNotInTable(String tableSummaryNameOrId, String[] text) {
781         for (int i = 0; i < text.length; i++) {
782             assertTextNotInTable(tableSummaryNameOrId, text[i]);
783         }
784     }
785 
786     /**
787      * Assert that supplied regexp is not present in a specific table.
788      *
789      * @param tableSummaryNameOrId summary, name or id attribute value of table
790      * @param text
791      */
792     public void assertNoMatchInTable(String tableSummaryNameOrId, String regexp) {
793         assertTablePresent(tableSummaryNameOrId);
794         assertTrue("Found regexp: [" + regexp + "] in table ["
795                 + tableSummaryNameOrId + "]", !getTestingEngine().getTable(
796                 tableSummaryNameOrId).hasMatch(regexp));
797     }
798 
799     /**
800      * Assert that none of a set of regexp values are present in a specific table.
801      *
802      * @param tableSummaryNameOrId summary, name or id attribute value of table
803      * @param text Array of text values
804      */
805     public void assertNoMatchInTable(String tableSummaryNameOrId,
806             String[] regexp) {
807         for (int i = 0; i < regexp.length; i++) {
808             assertNoMatchInTable(tableSummaryNameOrId, regexp[i]);
809         }
810     }
811 
812     /**
813      * Assert that a specific table matches an ExpectedTable.
814      *
815      * @param tableSummaryNameOrId summary, name or id attribute value of table
816      * @param expectedTable represents expected values (colspan supported).
817      */
818     public void assertTableEquals(String tableSummaryNameOrId,
819             Table expectedTable) {
820         getTestingEngine().getTable(tableSummaryNameOrId).assertEquals(
821                 expectedTable);
822     }
823 
824     /**
825      * Assert that a specific table matches a matrix of supplied text values.
826      *
827      * @param tableSummaryNameOrId summary, name or id attribute value of table
828      * @param expectedCellValues double dimensional array of expected values
829      */
830     public void assertTableEquals(String tableSummaryNameOrId,
831             String[][] expectedCellValues) {
832         getTestingEngine().getTable(tableSummaryNameOrId).assertEquals(
833                 new Table(expectedCellValues));
834     }
835 
836     /**
837      * Assert that a range of rows for a specific table matches a matrix of supplied text values.
838      *
839      * @param tableSummaryNameOrId summary, name or id attribute value of table
840      * @param startRow index of start row for comparison
841      * @param expectedTable represents expected values (colspan and rowspan supported).
842      */
843     public void assertTableRowsEqual(String tableSummaryNameOrId, int startRow,
844             Table expectedTable) {
845         getTestingEngine().getTable(tableSummaryNameOrId).assertSubTableEquals(
846                 startRow, expectedTable);
847     }
848 
849     /**
850      * Assert that a range of rows for a specific table matches a matrix of supplied text values.
851      *
852      * @param tableSummaryNameOrId summary, name or id attribute value of table
853      * @param startRow index of start row for comparison
854      * @param expectedTable represents expected values (colspan and rowspan supported).
855      */
856     public void assertTableRowsEqual(String tableSummaryNameOrId, int startRow,
857             String[][] expectedTable) {
858         getTestingEngine().getTable(tableSummaryNameOrId).assertSubTableEquals(
859                 startRow, new Table(expectedTable));
860     }
861 
862     /**
863      * Assert that the number of rows for a specific table equals expected value.
864      *
865      * @param tableSummaryNameOrId summary, name or id attribute value of table
866      * @param expectedRowCount expected row count.
867      */
868     public void assertTableRowCountEquals(String tableSummaryNameOrId,
869             int expectedRowCount) {
870         assertTablePresent(tableSummaryNameOrId);
871         int actualRowCount = getTestingEngine().getTable(tableSummaryNameOrId)
872                 .getRowCount();
873         assertTrue("Expected row count was " + expectedRowCount
874                 + " but actual row count is " + actualRowCount,
875                 actualRowCount == expectedRowCount);
876     }
877 
878     /**
879      * Assert that a specific table matches an ExpectedTable.
880      *
881      * @param tableSummaryOrId summary or id attribute value of table
882      * @param expectedTable represents expected regexps (colspan supported).
883      */
884     public void assertTableMatch(String tableSummaryOrId, Table expectedTable) {
885         getTestingEngine().getTable(tableSummaryOrId)
886                 .assertMatch(expectedTable);
887     }
888 
889     /**
890      * Assert that a specific table matches a matrix of supplied regexps.
891      *
892      * @param tableSummaryOrId summary or id attribute value of table
893      * @param expectedCellValues double dimensional array of expected regexps
894      */
895     public void assertTableMatch(String tableSummaryOrId,
896             String[][] expectedCellValues) {
897         getTestingEngine().getTable(tableSummaryOrId).assertMatch(
898                 new Table(expectedCellValues));
899     }
900 
901     /**
902      * Assert that a range of rows for a specific table matches a matrix of supplied regexps.
903      *
904      * @param tableSummaryOrId summary or id attribute value of table
905      * @param startRow index of start row for comparison
906      * @param expectedTable represents expected regexps (colspan and rowspan supported).
907      */
908     public void assertTableRowsMatch(String tableSummaryOrId, int startRow,
909             Table expectedTable) {
910         getTestingEngine().getTable(tableSummaryOrId).assertSubTableMatch(
911                 startRow, expectedTable);
912     }
913 
914     /**
915      * Assert that a range of rows for a specific table matches a matrix of supplied regexps.
916      *
917      * @param tableSummaryOrId summary or id attribute value of table
918      * @param startRow index of start row for comparison
919      * @param expectedTable represents expected regexps (colspan and rowspan not supported).
920      */
921     public void assertTableRowsMatch(String tableSummaryOrId, int startRow,
922             String[][] expectedTable) {
923         getTestingEngine().getTable(tableSummaryOrId).assertSubTableMatch(
924                 startRow, new Table(expectedTable));
925     }
926 
927     /**
928      * Assert that a form input element with a given name is present.
929      *
930      * @param formElementName
931      */
932     public void assertFormElementPresent(String formElementName) {
933         assertTrue("Did not find form element with name ["
934                 + formElementName + "].", getTestingEngine()
935                 .hasFormParameterNamed(formElementName));
936     }
937 
938     /**
939      * Assert that a form input element with a given name is not present.
940      *
941      * @param formElementName
942      */
943     public void assertFormElementNotPresent(String formElementName) {
944         try {
945             assertTrue("Found form element with name ["
946                     + formElementName + "] when not expected.", !getTestingEngine()
947                     .hasFormParameterNamed(formElementName));
948         } catch (UnableToSetFormException e) {
949             // assertFormControlNotPresent
950         }
951     }
952 
953     /**
954      * Assert that a form checkbox with a given name is present.
955      *
956      * @param checkboxName checkbox name.
957      */
958     public void assertCheckboxPresent(String checkboxName) {
959         assertTrue("Did not find form checkbox with name ["
960                 + checkboxName + "].", getTestingEngine().hasElementByXPath(
961                 "//input[lower-case(@type)='checkbox' and @name='" + checkboxName + "']"));
962     }
963 
964     /**
965      * Assert that a given checkbox is present.
966      *
967      * @param checkboxName checkbox name attribut.
968      * @param checkboxValue checkbox value attribut.
969      */
970     public void assertCheckboxPresent(String checkboxName, String checkboxValue) {
971         assertTrue("Did not find form checkbox with name ["
972                 + checkboxName + "] and value [" + checkboxValue + "].",
973                 getTestingEngine().hasElementByXPath(
974                         "//input[lower-case(@type)='checkbox' and @name='" + checkboxName
975                                 + "' and @value='" + checkboxValue + "']"));
976     }
977 
978     /**
979      * Assert that a form checkbox with a given name is not present.
980      *
981      * @param checkboxName checkbox name.
982      */
983     public void assertCheckboxNotPresent(String checkboxName) {
984         assertFalse("Found form checkbox with name [" + checkboxName
985                 + "] when not expected.", getTestingEngine().hasElementByXPath(
986                 "//input[lower-case(@type)='checkbox' and @name='" + checkboxName + "']"));
987     }
988 
989     /**
990      * Assert that a given checkbox is not present.
991      *
992      * @param checkboxName checkbox name.
993      * @param checkboxValue checkbox value attribut.
994      */
995     public void assertCheckboxNotPresent(String checkboxName,
996             String checkboxValue) {
997         assertFalse("Found form checkbox with name [" + checkboxName
998                 + "] and value [" + checkboxValue + "] when not expected.",
999                 getTestingEngine().hasElementByXPath(
1000                         "//input[lower-case(@type)='checkbox' and @name='" + checkboxName
1001                                 + "' and @value='" + checkboxValue + "']"));
1002     }
1003 
1004     /**
1005      * Assert that there is a form present.
1006      *
1007      */
1008     public void assertFormPresent() {
1009         assertTrue("No form present", getTestingEngine().hasForm());
1010     }
1011 
1012     /**
1013      * Assert that there is a form with the specified name or id present.
1014      *
1015      * @param nameOrID
1016      */
1017     public void assertFormPresent(String nameOrID) {
1018         assertTrue("No form present with name or id [" + nameOrID + "]",
1019                 getTestingEngine().hasForm(nameOrID));
1020     }
1021 
1022     /**
1023      * Assert that there is a form with the specified name or id and the given index present.
1024      *
1025      * @param nameOrID
1026      * @param index The 0-based index, when more than one form with the same name is expected.
1027      */
1028     public void assertFormPresent(String nameOrID, int index) {
1029         assertTrue("No form present with name or id [" + nameOrID + "] at index " + index,
1030                 getTestingEngine().hasForm(nameOrID, index));
1031     }
1032 
1033     /**
1034      * Assert that there is not a form present.
1035      *
1036      */
1037     public void assertFormNotPresent() {
1038         assertFalse("A form is present", getTestingEngine().hasForm());
1039     }
1040 
1041     /**
1042      * Assert that there is not a form with the specified name or id present.
1043      *
1044      * @param nameOrID
1045      */
1046     public void assertFormNotPresent(String nameOrID) {
1047         assertFalse("Form present with name or id [" + nameOrID + "]",
1048                 getTestingEngine().hasForm(nameOrID));
1049     }
1050 
1051     /**
1052      * Assert that a specific form element has an expected value. Can be used to check hidden input.
1053      *
1054      * @param formElementName
1055      * @param expectedValue
1056      * @see #assertTextFieldEquals(String, String)
1057      * @deprecated use an explicit testing method, e.g. {@link #assertTextFieldEquals(String, String)}
1058      */
1059     public void assertFormElementEquals(String formElementName,
1060             String expectedValue) {
1061         assertFormElementPresent(formElementName);
1062         assertEquals(expectedValue, getTestingEngine()
1063                 .getElementAttributByXPath(
1064                         "//input[@name='" + formElementName + "']", "value"));
1065     }
1066 
1067     /**
1068      * Assert that a specific form element matches an expected regexp.
1069      *
1070      * @param formElementName
1071      * @param regexp
1072      */
1073     public void assertFormElementMatch(String formElementName, String regexp) {
1074       // how can we @deprecate this if there is no available alternative?
1075         assertFormElementPresent(formElementName);
1076         RE re = null;
1077         try {
1078             re = new RE(regexp, RE.MATCH_SINGLELINE);
1079         } catch (RESyntaxException e) {
1080             fail(e.toString());
1081         }
1082         assertTrue("Unable to match [" + regexp + "] in form element \""
1083                 + formElementName + "\"", re.match(getTestingEngine()
1084                 .getElementAttributByXPath(
1085                         "//input[@name='" + formElementName + "']", "value")));
1086     }
1087 
1088     /**
1089      * Assert that a form element had no value / is empty.
1090      *
1091      * @param formElementName
1092      * @see #setTextField(String, String)
1093      * @see #setHiddenField(String, String)
1094      * @deprecated use an explicit testing method, e.g. {@link #setTextField(String, String)} or {@link #setHiddenField(String, String)}
1095      */
1096     public void assertFormElementEmpty(String formElementName) {
1097         assertFormElementPresent(formElementName);
1098         assertEquals("", getTestingEngine().getElementAttributByXPath(
1099                 "//input[@name='" + formElementName + "']", "value"));
1100     }
1101 
1102     /**
1103      * Assert that an input text element with name <code>formElementName</code> has the <code>expectedValue</code>
1104      * value.
1105      *
1106      * @param formElementName the value of the name attribute of the element
1107      * @param expectedValue the expected value of the given input element
1108      */
1109     public void assertTextFieldEquals(String formElementName,
1110             String expectedValue) {
1111         assertFormElementPresent(formElementName);
1112         assertEquals(expectedValue, getTestingEngine()
1113                 .getTextFieldValue(formElementName));
1114     }
1115 
1116     /**
1117      * Assert that an input hidden element with name <code>formElementName</code> has the <code>expectedValue</code>
1118      * value.
1119      *
1120      * @param formElementName the value of the name attribute of the element
1121      * @param expectedValue the expected value of the given input element
1122      */
1123     public void assertHiddenFieldPresent(String formElementName,
1124             String expectedValue) {
1125         assertFormElementPresent(formElementName);
1126         assertEquals(expectedValue, getTestingEngine()
1127                 .getHiddenFieldValue(formElementName));
1128     }
1129 
1130     /**
1131      * Assert that a specific checkbox is selected.
1132      *
1133      * @param checkBoxName
1134      */
1135     public void assertCheckboxSelected(String checkBoxName) {
1136         assertCheckboxPresent(checkBoxName);
1137         if (!getTestingEngine().isCheckboxSelected(checkBoxName)) {
1138             fail("Checkbox with name [" + checkBoxName
1139                     + "] was not found selected.");
1140         }
1141     }
1142 
1143     /**
1144      * Assert that a specific checkbox is selected.
1145      *
1146      * @param checkBoxName
1147      * @param checkBoxValue
1148      */
1149     public void assertCheckboxSelected(String checkBoxName, String checkBoxValue) {
1150         assertCheckboxPresent(checkBoxName, checkBoxValue);
1151         if (!getTestingEngine().isCheckboxSelected(checkBoxName, checkBoxValue)) {
1152             fail("Checkbox with name [" + checkBoxName + "] and value ["
1153                     + checkBoxValue + "] was not found selected.");
1154         }
1155     }
1156 
1157     /**
1158      * Assert that a specific checkbox is not selected.
1159      *
1160      * @param checkBoxName
1161      */
1162     public void assertCheckboxNotSelected(String checkBoxName) {
1163         assertCheckboxPresent(checkBoxName);
1164         if (getTestingEngine().isCheckboxSelected(checkBoxName)) {
1165             fail("Checkbox with name [" + checkBoxName
1166                     + "] was found selected.");
1167         }
1168     }
1169 
1170     /**
1171      * Assert that a specific checkbox is not selected.
1172      *
1173      * @param checkBoxName
1174      * @param checkBoxValue
1175      */
1176     public void assertCheckboxNotSelected(String checkBoxName,
1177             String checkBoxValue) {
1178         assertCheckboxPresent(checkBoxName, checkBoxValue);
1179         if (getTestingEngine().isCheckboxSelected(checkBoxName, checkBoxValue)) {
1180             fail("Checkbox with name [" + checkBoxName + "] and value ["
1181                     + checkBoxValue + "] was found selected.");
1182         }
1183     }
1184 
1185     /**
1186      * Assert that a specific option is present in a radio group.
1187      *
1188      * @param name radio group name.
1189      * @param radioOption option to test for.
1190      */
1191     public void assertRadioOptionPresent(String name, String radioOption) {
1192         assertFormElementPresent(name);
1193         if (!getTestingEngine().hasRadioOption(name, radioOption)) {
1194             fail("Unable to find option [" + radioOption
1195                     + "] in radio group [" + name + "]");
1196         }
1197     }
1198 
1199     /**
1200      * Assert that a specific option is not present in a radio group.
1201      *
1202      * @param name radio group name.
1203      * @param radioOption option to test for.
1204      */
1205     public void assertRadioOptionNotPresent(String name, String radioOption) {
1206         assertFormElementPresent(name);
1207         if (getTestingEngine().hasRadioOption(name, radioOption))
1208             fail("Found option [" + radioOption + "] in radio group ["
1209                     + name + "]");
1210     }
1211 
1212     /**
1213      * Assert that a specific option is selected in a radio group.
1214      *
1215      * @param name radio group name.
1216      * @param radioOption option to test for selection.
1217      */
1218     public void assertRadioOptionSelected(String name, String radioOption) {
1219         assertRadioOptionPresent(name, radioOption);
1220         assertEquals(radioOption, getTestingEngine()
1221             .getSelectedRadio(name));
1222     }
1223 
1224     /**
1225      * Assert that a specific option is not selected in a radio group.
1226      *
1227      * @param name radio group name.
1228      * @param radioOption option to test for selection.
1229      */
1230     public void assertRadioOptionNotSelected(String name, String radioOption) {
1231         assertRadioOptionPresent(name, radioOption);
1232         assertFalse("Radio option [" + radioOption + "] is selected.",
1233                 radioOption.equals(getTestingEngine()
1234                         .getSelectedRadio(name)));
1235     }
1236 
1237     /**
1238      * Assert that given options are present in a select box (by label).
1239      *
1240      * @param selectName name of the select element.
1241      * @param optionLabels option labels.
1242      */
1243     public void assertSelectOptionsPresent(String selectName,
1244             String[] optionLabels) {
1245         assertFormElementPresent(selectName);
1246         for (int i = 0; i < optionLabels.length; i++)
1247             assertTrue("Option [" + optionLabels[i]
1248                     + "] not found in select element " + selectName,
1249                     getTestingEngine().hasSelectOption(selectName,
1250                             optionLabels[i]));
1251     }
1252 
1253     /**
1254      * Assert that a specific option is present in a select box (by label).
1255      *
1256      * @param selectName name of the select element.
1257      * @param optionLabel option label.
1258      */
1259     public void assertSelectOptionPresent(String selectName, String optionLabel) {
1260         assertSelectOptionsPresent(selectName, new String[] { optionLabel });
1261     }
1262 
1263     /**
1264      * Assert that given options are present in the Nth select box (by label).
1265      *
1266      * @param selectName name of the select element.
1267      * @param index the 0-based index of the select element when multiple
1268      * select elements are expected.
1269      * @param optionLabels option labels.
1270      */
1271     public void assertSelectOptionsPresent(String selectName, int index,
1272             String[] optionLabels) {
1273         assertFormElementPresent(selectName);
1274         for (int i = 0; i < optionLabels.length; i++)
1275             assertTrue("Option [" + optionLabels[i]
1276                     + "] not found in select element " + selectName,
1277                     getTestingEngine().hasSelectOption(selectName, index,
1278                             optionLabels[i]));
1279     }
1280 
1281     /**
1282      * Assert that a specific option is present in the Nth select box (by label).
1283      *
1284      * @param selectName name of the select element.
1285      * @param index the 0-based index of the select element when multiple
1286      * select elements are expected.
1287      * @param optionLabel option label.
1288      */
1289     public void assertSelectOptionPresent(String selectName, int index, String optionLabel) {
1290         assertSelectOptionsPresent(selectName, index, new String[] { optionLabel });
1291     }
1292 
1293 
1294     /**
1295      * Assert that given options are present in a select box (by value).
1296      *
1297      * @param selectName name of the select element.
1298      * @param optionValues option labels.
1299      */
1300     public void assertSelectOptionValuesPresent(String selectName,
1301             String[] optionValues) {
1302         assertFormElementPresent(selectName);
1303         for (int i = 0; i < optionValues.length; i++)
1304             assertTrue("Option [" + optionValues[i]
1305                     + "] not found in select element " + selectName,
1306                     getTestingEngine().hasSelectOptionValue(selectName,
1307                             optionValues[i]));
1308     }
1309 
1310     /**
1311      * Assert that a specific option is present in a select box (by value).
1312      *
1313      * @param selectName name of the select element.
1314      * @param optionValue option value.
1315      */
1316     public void assertSelectOptionValuePresent(String selectName,
1317             String optionValue) {
1318         assertSelectOptionValuesPresent(selectName,
1319                 new String[] { optionValue });
1320     }
1321 
1322     /**
1323      * Assert that given options are present in the Nth select box (by value).
1324      *
1325      * @param selectName name of the select element.
1326      * @param index the 0-based index of the select element when multiple
1327      * select elements are expected.
1328      * @param optionValues option labels.
1329      */
1330     public void assertSelectOptionValuesPresent(String selectName,
1331                           int index,
1332                           String[] optionValues) {
1333         assertFormElementPresent(selectName);
1334         for (int i = 0; i < optionValues.length; i++)
1335             assertTrue("Option [" + optionValues[i]
1336                     + "] not found in select element " + selectName,
1337                     getTestingEngine().hasSelectOptionValue(selectName,
1338                                                             index,
1339                                                             optionValues[i]));
1340     }
1341 
1342     /**
1343      * Assert that a specific option is present in the Nth select box (by value).
1344      *
1345      * @param selectName name of the select element.
1346      * @param index the 0-based index of the select element when multiple
1347      * select elements are expected.
1348      * @param optionValue option value.
1349      */
1350     public void assertSelectOptionValuePresent(String selectName,
1351                            int index,
1352                            String optionValue) {
1353         assertSelectOptionValuesPresent(selectName, index,
1354                 new String[] { optionValue });
1355     }
1356 
1357     /**
1358      * Assert that a specific option value is not present in a select box.
1359      *
1360      * @param selectName name of the select element.
1361      * @param optionValue option value.
1362      */
1363     public void assertSelectOptionValueNotPresent(String selectName,
1364             String optionValue) {
1365         try {
1366             assertSelectOptionValuePresent(selectName, optionValue);
1367         } catch (AssertionError e) {
1368             return;
1369         }
1370         fail("Option value" + optionValue + " found in select element "
1371                 + selectName + " when not expected.");
1372     }
1373 
1374     /**
1375      * Assert that a specific option is not present in a select box.
1376      *
1377      * @param selectName name of the select element.
1378      * @param expectedOption option label.
1379      */
1380     public void assertSelectOptionNotPresent(String selectName,
1381             String optionLabel) {
1382         try {
1383             assertSelectOptionPresent(selectName, optionLabel);
1384         } catch (AssertionError e) {
1385             return;
1386         }
1387         fail("Option " + optionLabel + " found in select element "
1388                 + selectName + " when not expected.");
1389     }
1390 
1391     /**
1392      * Assert that a specific option value is not present in a select box.
1393      *
1394      * @param selectName name of the select element.
1395      * @param optionValue option value.
1396      */
1397     public void assertSelectOptionValueNotPresent(String selectName,
1398             int index, String optionValue) {
1399         try {
1400             assertSelectOptionValuePresent(selectName, index, optionValue);
1401         } catch (AssertionError e) {
1402             return;
1403         }
1404         fail("Option value" + optionValue + " found in select element "
1405                 + selectName + " when not expected.");
1406     }
1407 
1408     /**
1409      * Assert that a specific option is not present in a select box.
1410      *
1411      * @param selectName name of the select element.
1412      * @param expectedOption option label.
1413      */
1414     public void assertSelectOptionNotPresent(String selectName,
1415             int index, String optionLabel) {
1416         try {
1417             assertSelectOptionPresent(selectName, index, optionLabel);
1418         } catch (AssertionError e) {
1419             return;
1420         }
1421         fail("Option " + optionLabel + " found in select element "
1422                 + selectName + " when not expected.");
1423     }
1424 
1425     /**
1426      * Assert that the display values of a select element's options match a given array of strings.
1427      *
1428      * @param selectName name of the select element.
1429      * @param expectedOptions expected labels for the select box.
1430      */
1431     public void assertSelectOptionsEqual(String selectName,
1432             String[] expectedOptions) {
1433         assertFormElementPresent(selectName);
1434         assertArraysEqual(expectedOptions, getOptionsFor(selectName));
1435     }
1436 
1437     /**
1438      * Assert that the display values of
1439      * the Nth select element's options match a given array of strings.
1440      *
1441      * @param selectName name of the select element.
1442      * @param index the 0-based index of the select element when multiple
1443      * select elements are expected.
1444      * @param expectedOptions expected labels for the select box.
1445      */
1446     public void assertSelectOptionsEqual(String selectName, int index,
1447             String[] expectedOptions) {
1448         assertFormElementPresent(selectName);
1449         assertArraysEqual(expectedOptions, getOptionsFor(selectName, index));
1450     }
1451 
1452 
1453     /**
1454      * Assert that the display values of a select element's options do not match a given array of strings.
1455      *
1456      * @param selectName name of the select element.
1457      * @param expectedOptions expected display values for the select box.
1458      */
1459     public void assertSelectOptionsNotEqual(String selectName,
1460             String[] expectedOptions) {
1461         assertFormElementPresent(selectName);
1462         try {
1463             assertSelectOptionsEqual(selectName, expectedOptions);
1464         } catch (AssertionError e) {
1465             return;
1466         }
1467         fail("Options not expected to be equal");
1468     }
1469 
1470     /**
1471      * Assert that the display values of the Nth select element's
1472      * options do not match a given array of strings.
1473      *
1474      * @param selectName name of the select element.
1475      * @param index the 0-based index of the select element when multiple
1476      * select elements are expected.
1477      * @param expectedOptions expected display values for the select box.
1478      */
1479     public void assertSelectOptionsNotEqual(String selectName, int index,
1480             String[] expectedOptions) {
1481         assertFormElementPresent(selectName);
1482         try {
1483             assertSelectOptionsEqual(selectName, index, expectedOptions);
1484         } catch (AssertionError e) {
1485             return;
1486         }
1487         fail("Options not expected to be equal");
1488     }
1489 
1490 
1491     /**
1492      * Assert that the values of the Nth select element's options match
1493      * a given array of strings.
1494      *
1495      * @param selectName name of the select element.
1496      * @param index the 0-based index of the select element when multiple
1497      * select elements are expected.
1498      * @param expectedValues expected values for the select box.
1499      */
1500     public void assertSelectOptionValuesEqual(String selectName, int index,
1501             String[] expectedValues) {
1502         assertFormElementPresent(selectName);
1503         assertArraysEqual(expectedValues, getTestingEngine()
1504                 .getSelectOptionValues(selectName, index));
1505 
1506     }
1507 
1508     /**
1509      * Assert that the values of a select element's options match a given array of strings.
1510      *
1511      * @param selectName name of the select element.
1512      * @param expectedValues expected values for the select box.
1513      */
1514     public void assertSelectOptionValuesEqual(String selectName,
1515             String[] expectedValues) {
1516         assertFormElementPresent(selectName);
1517         assertArraysEqual(expectedValues, getTestingEngine()
1518                 .getSelectOptionValues(selectName));
1519 
1520     }
1521 
1522 
1523     /**
1524      * Assert that the values of a select element's options do not match a given array of strings.
1525      *
1526      * @param selectName name of the select element.
1527      * @param optionValues expected values for the select box.
1528      */
1529     public void assertSelectOptionValuesNotEqual(String selectName,
1530             String[] optionValues) {
1531         assertFormElementPresent(selectName);
1532         try {
1533             assertSelectOptionValuesEqual(selectName, optionValues);
1534         } catch (AssertionError e) {
1535             return;
1536         }
1537         fail("Values not expected to be equal");
1538     }
1539 
1540     /**
1541      * Assert that the values of the Nth select element's options do not match a
1542      * given array of strings.
1543      *
1544      * @param selectName name of the select element.
1545      * @param index the 0-based index of the select element when multiple
1546      * select elements are expected.
1547      * @param optionValues expected values for the select box.
1548      */
1549     public void assertSelectOptionValuesNotEqual(String selectName, int index,
1550             String[] optionValues) {
1551         assertFormElementPresent(selectName);
1552         try {
1553             assertSelectOptionValuesEqual(selectName, index, optionValues);
1554         } catch (AssertionError e) {
1555             return;
1556         }
1557         fail("Values not expected to be equal");
1558     }
1559 
1560 
1561     /**
1562      * Assert that the currently selected display label(s) of a select box matches given label(s).
1563      *
1564      * @param selectName name of the select element.
1565      * @param labels expected display label(s) of the selected option.
1566      */
1567     public void assertSelectedOptionsEqual(String selectName, String[] labels) {
1568         assertFormElementPresent(selectName);
1569         assertEquals(labels.length, getTestingEngine()
1570                 .getSelectedOptions(selectName).length);
1571         for (int i = 0; i < labels.length; i++)
1572             assertEquals(labels[i],
1573                     getTestingEngine()
1574                             .getSelectOptionLabelForValue(
1575                                     selectName,
1576                                     getTestingEngine().getSelectedOptions(
1577                                             selectName)[i]));
1578     }
1579 
1580     /**
1581      * Assert that the currently selected display label(s) of a select box matches given label(s).
1582      *
1583      * @param selectName name of the select element.
1584      * @param index the 0-based index used when more than one select element
1585      * with the same name is expected.
1586      * @param labels expected display label(s) of the selected option.
1587      */
1588     public void assertSelectedOptionsEqual(String selectName, int index, String[] labels) {
1589         assertFormElementPresent(selectName);
1590         assertEquals(labels.length, getTestingEngine()
1591                 .getSelectedOptions(selectName, index).length);
1592         for (int i = 0; i < labels.length; i++)
1593             assertEquals(labels[i],
1594                     getTestingEngine()
1595                             .getSelectOptionLabelForValue(
1596                                     selectName, index,
1597                                     getTestingEngine().getSelectedOptions(
1598                                             selectName, index)[i]));
1599     }
1600 
1601 
1602 
1603     /**
1604      * Assert that the label of the current selected option matches
1605      * the provided value.
1606      * @param selectName name of the select element
1607      * @param optionLabel expected value of the option label
1608      */
1609     public void assertSelectedOptionEquals(String selectName, String optionLabel) {
1610         assertSelectedOptionsEqual(selectName, new String[] { optionLabel });
1611     }
1612 
1613     /**
1614      * Assert that the label of the current selected option matches
1615      * the provided value in the Nth select element with the specified name.
1616      * @param selectName name of the select element
1617      * @param index the 0-based index used when more than one select element
1618      * with the same name is expected.
1619      * @param optionLabel expected value of the option label
1620      */
1621     public void assertSelectedOptionEquals(String selectName, int index, String option) {
1622         assertSelectedOptionsEqual(selectName, index, new String[] { option });
1623     }
1624 
1625 
1626     /**
1627      * Assert that the currently selected value(s) of a select box matches given value(s).
1628      *
1629      * @param selectName name of the select element.
1630      * @param values expected value(s) of the selected option.
1631      */
1632     public void assertSelectedOptionValuesEqual(String selectName,
1633             String[] values) {
1634         assertFormElementPresent(selectName);
1635         assertEquals(values.length, getTestingEngine()
1636                 .getSelectedOptions(selectName).length);
1637         for (int i = 0; i < values.length; i++)
1638             assertEquals(values[i], getTestingEngine()
1639                     .getSelectedOptions(selectName)[i]);
1640     }
1641 
1642     /**
1643      * Assert that the currently selected value(s) of the Nth
1644      * select box with the specified name matches given value(s).
1645      *
1646      * @param selectName name of the select element.
1647      * @param index the 0-based index used when more than one select element
1648      * with the same name is expected.
1649      * @param values expected value(s) of the selected option.
1650      */
1651     public void assertSelectedOptionValuesEqual(String selectName,
1652             int index, String[] values) {
1653         assertFormElementPresent(selectName);
1654         assertEquals(values.length, getTestingEngine()
1655                 .getSelectedOptions(selectName, index).length);
1656         for (int i = 0; i < values.length; i++)
1657             assertEquals(values[i], getTestingEngine()
1658                     .getSelectedOptions(selectName, index)[i]);
1659     }
1660 
1661 
1662     /**
1663      * Assert that the currently selected value of a select box matches given value.
1664      *
1665      * @param selectName name of the select element.
1666      * @param value expected value of the selected option.
1667      */
1668     public void assertSelectedOptionValueEquals(String selectName, String value) {
1669         assertSelectedOptionValuesEqual(selectName, new String[] { value });
1670     }
1671 
1672     /**
1673      * Assert that the currently selected value of a select box matches given value.
1674      *
1675      * @param selectName name of the select element.
1676      * @param index the 0-based index used when more than one select element
1677      * with the same name is expected.
1678      * @param value expected value of the selected option.
1679      */
1680     public void assertSelectedOptionValueEquals(String selectName, int index, String value) {
1681         assertSelectedOptionValuesEqual(selectName, index, new String[] { value });
1682     }
1683 
1684 
1685 
1686     /**
1687      * Assert that the currently selected display value(s) of a select box matches a given value(s).
1688      *
1689      * @param selectName name of the select element.
1690      * @param regexps expected display value of the selected option.
1691      */
1692     public void assertSelectedOptionsMatch(String selectName, String[] regexps) {
1693         assertFormElementPresent(selectName);
1694         assertEquals(regexps.length, getTestingEngine()
1695                 .getSelectedOptions(selectName).length);
1696         for (int i = 0; i < regexps.length; i++) {
1697             RE re = getRE(regexps[i]);
1698             assertTrue("Unable to match [" + regexps[i]
1699                     + "] in option \""
1700                     + getTestingEngine().getSelectedOptions(selectName)[i]
1701                     + "\"", re.match(getTestingEngine().getSelectedOptions(
1702                     selectName)[i]));
1703         }
1704     }
1705 
1706     /**
1707      * Assert that the currently selected display value(s) of a select box matches a given value(s).
1708      *
1709      * @param selectName name of the select element.
1710      * @param index the 0-based index used when more than one select element
1711      * with the same name is expected.
1712      * @param regexps expected display value of the selected option.
1713      */
1714     public void assertSelectedOptionsMatch(String selectName, int index, String[] regexps) {
1715         assertFormElementPresent(selectName);
1716         assertEquals(regexps.length, getTestingEngine()
1717                 .getSelectedOptions(selectName, index).length);
1718         for (int i = 0; i < regexps.length; i++) {
1719             RE re = getRE(regexps[i]);
1720             assertTrue("Unable to match [" + regexps[i]
1721                     + "] in option \""
1722                     + getTestingEngine().getSelectedOptions(selectName, index)[i]
1723                     + "\" at index " + index, re.match(getTestingEngine().getSelectedOptions(
1724                     selectName, index)[i]));
1725         }
1726     }
1727 
1728 
1729 
1730     /**
1731      * Assert that the label of the current selected option matches
1732      * the provided regular expression value.
1733      * @param selectName name of the select element
1734      * @param regexp the regular expression to match
1735      */
1736     public void assertSelectedOptionMatches(String selectName, String regexp) {
1737         assertSelectedOptionsMatch(selectName, new String[] { regexp });
1738     }
1739 
1740     /**
1741      * Assert that the label of the current selected option matches
1742      * the provided regular expression in the Nth select element with the specified name.
1743      * @param selectName name of the select element
1744      * @param index the 0-based index used when more than one select element
1745      * with the same name is expected.
1746      * @param regexp the regular expression to match
1747      */
1748     public void assertSelectedOptionMatches(String selectName, int index, String regexp) {
1749         assertSelectedOptionsMatch(selectName, index, new String[] { regexp });
1750     }
1751 
1752 
1753     /**
1754      * Assert that a submit button is present. <br/> A submit button can be the following HTML elements:
1755      * <ul>
1756      * <li>submit input
1757      * <li>image input
1758      * <li>submit button
1759      * </ul>
1760      *
1761      */
1762     public void assertSubmitButtonPresent() {
1763         assertTrue("no submit button found.", getTestingEngine()
1764                 .hasSubmitButton());
1765     }
1766 
1767     /**
1768      * Assert that a submit button with a given name is present. <br/> A submit button can be the following HTML
1769      * elements:
1770      * <ul>
1771      * <li>submit input
1772      * <li>image input
1773      * <li>submit button
1774      * </ul>
1775      *
1776      * @param buttonName
1777      */
1778     public void assertSubmitButtonPresent(String buttonName) {
1779         assertTrue("Submit Button [" + buttonName + "] not found.",
1780                 getTestingEngine().hasSubmitButton(buttonName));
1781     }
1782 
1783     /**
1784      * Assert that no submit button is present in the current form. <br/> A submit button can be the following HTML
1785      * elements:
1786      * <ul>
1787      * <li>submit input
1788      * <li>image input
1789      * <li>submit button
1790      * </ul>
1791      *
1792      * @param buttonName
1793      */
1794     public void assertSubmitButtonNotPresent() {
1795         assertFalse("Submit Button found.", getTestingEngine()
1796                 .hasSubmitButton());
1797     }
1798 
1799     /**
1800      * Assert that a submit button with a given name is not present. <br/> A submit button can be the following HTML
1801      * elements:
1802      * <ul>
1803      * <li>submit input
1804      * <li>image input
1805      * <li>submit button
1806      * </ul>
1807      *
1808      * @param buttonName
1809      */
1810     public void assertSubmitButtonNotPresent(String buttonName) {
1811         assertFalse("Submit Button [" + buttonName + "] found.",
1812                 getTestingEngine().hasSubmitButton(buttonName));
1813     }
1814 
1815     /**
1816      * Assert that a submit button with a given name and value is present. <br/> A submit button can be the following
1817      * HTML elements:
1818      * <ul>
1819      * <li>submit input
1820      * <li>image input
1821      * <li>submit button
1822      * </ul>
1823      *
1824      * @param buttonName
1825      * @param buttonValue
1826      */
1827     public void assertSubmitButtonPresent(String buttonName, String buttonValue) {
1828         assertTrue("Submit Button [" + buttonName + "] with value ["
1829                 + buttonValue + "] not found.", getTestingEngine()
1830                 .hasSubmitButton(buttonName, buttonValue));
1831     }
1832 
1833     /**
1834      * Assert that a reset button is present. <br/> A reset button can be the following HTML elements:
1835      * <ul>
1836      * <li>reset input
1837      * <li>reset button
1838      * </ul>
1839      *
1840      */
1841     public void assertResetButtonPresent() {
1842         assertTrue("no reset button found.", getTestingEngine()
1843                 .hasResetButton());
1844     }
1845 
1846     /**
1847      * Assert that a reset button with a given name is present.<br/> A reset button can be the following HTML elements:
1848      * <ul>
1849      * <li>reset input
1850      * <li>reset button
1851      * </ul>
1852      *
1853      * @param buttonName
1854      */
1855     public void assertResetButtonPresent(String buttonName) {
1856         assertTrue("Reset Button [" + buttonName + "] not found.",
1857                 getTestingEngine().hasResetButton(buttonName));
1858     }
1859 
1860     /**
1861      * Assert that no reset button is present in the current form.<br/> A reset button can be the following HTML
1862      * elements:
1863      * <ul>
1864      * <li>reset input
1865      * <li>reset button
1866      * </ul>
1867      *
1868      * @param buttonName
1869      */
1870     public void assertResetButtonNotPresent() {
1871         assertFalse("Reset Button found.", getTestingEngine()
1872                 .hasResetButton());
1873     }
1874 
1875     /**
1876      * Assert that a reset button with a given name is not present.<br/> A reset button can be the following HTML
1877      * elements:
1878      * <ul>
1879      * <li>reset input
1880      * <li>reset button
1881      * </ul>
1882      *
1883      * @param buttonName
1884      */
1885     public void assertResetButtonNotPresent(String buttonName) {
1886         assertFalse("Reset Button [" + buttonName + "] found.",
1887                 getTestingEngine().hasResetButton(buttonName));
1888     }
1889 
1890     /**
1891      * Assert that a button with a given id is present in the current window.<br/> A button can be the following HTML
1892      * elements:
1893      * <ul>
1894      * <li>button input
1895      * <li>button button
1896      * </ul>
1897      *
1898      * @param buttonId
1899      */
1900     public void assertButtonPresent(String buttonId) {
1901         assertTrue("Button [" + buttonId + "] not found.", getTestingEngine()
1902                 .hasButton(buttonId));
1903     }
1904 
1905     /**
1906      * Assert that a button with a given text is present in the current window.
1907      *
1908      * @param text Text representation of button content.
1909      */
1910     public void assertButtonPresentWithText(String text) {
1911         assertTrue("Did not find button with text [" + text + "].",
1912                 getTestingEngine().hasButtonWithText(text));
1913     }
1914 
1915     /**
1916      * Assert that a button with a given text is not present in the current window.
1917      *
1918      * @param text Text representation of button content.
1919      */
1920     public void assertButtonNotPresentWithText(String text) {
1921         assertFalse("Found button with text [" + text + "].",
1922                 getTestingEngine().hasButtonWithText(text));
1923     }
1924 
1925     /**
1926      * Assert that a button with a given id is not present in the current window.
1927      *
1928      * @param buttonId
1929      */
1930     public void assertButtonNotPresent(String buttonId) {
1931         assertFalse(
1932                 "Button [" + buttonId + "] found when not expected.",
1933                 getTestingEngine().hasButton(buttonId));
1934     }
1935 
1936     /**
1937      * Assert that a link with a given id is present in the response.
1938      *
1939      * @param linkId
1940      */
1941     public void assertLinkPresent(String linkId) {
1942         assertTrue("Unable to find link with id [" + linkId + "]",
1943                 getTestingEngine().hasLink(linkId));
1944     }
1945 
1946     /**
1947      * Assert that no link with the given id is present in the response.
1948      *
1949      * @param linkId
1950      */
1951     public void assertLinkNotPresent(String linkId) {
1952         assertTrue("link with id [" + linkId + "] found in response",
1953                 !getTestingEngine().hasLink(linkId));
1954     }
1955 
1956     /**
1957      * Assert that a link containing the supplied text is present.
1958      *
1959      * @param linkText
1960      */
1961     public void assertLinkPresentWithText(String linkText) {
1962         assertTrue("Link with text [" + linkText
1963                 + "] not found in response.", getTestingEngine()
1964                 .hasLinkWithText(linkText, 0));
1965     }
1966 
1967     /**
1968      * Assert that no link containing the supplied text is present.
1969      *
1970      * @param linkText
1971      */
1972     public void assertLinkNotPresentWithText(String linkText) {
1973         assertTrue("Link with text [" + linkText
1974                 + "] found in response.", !getTestingEngine().hasLinkWithText(
1975                 linkText, 0));
1976     }
1977 
1978     /**
1979      * Assert that a link containing the supplied text is present.
1980      *
1981      * @param linkText
1982      * @param index The 0-based index, when more than one link with the same text is expected.
1983      */
1984     public void assertLinkPresentWithText(String linkText, int index) {
1985         assertTrue("Link with text [" + linkText + "] and index ["
1986                 + index + "] not found in response.", getTestingEngine()
1987                 .hasLinkWithText(linkText, index));
1988     }
1989 
1990     /**
1991      * Assert that no link containing the supplied text is present.
1992      *
1993      * @param linkText
1994      * @param index The 0-based index, when more than one link with the same text is expected.
1995      */
1996     public void assertLinkNotPresentWithText(String linkText, int index) {
1997         assertTrue("Link with text [" + linkText + "] and index "
1998                 + index + " found in response.", !getTestingEngine()
1999                 .hasLinkWithText(linkText, index));
2000     }
2001 
2002     // BEGIN RFE 996031...
2003 
2004     /**
2005      * Assert that a link containing the Exact text is present.
2006      *
2007      * @param linkText
2008      */
2009     public void assertLinkPresentWithExactText(String linkText) {
2010         assertTrue("Link with Exact text [" + linkText
2011                 + "] not found in response.", getTestingEngine()
2012                 .hasLinkWithExactText(linkText, 0));
2013     }
2014 
2015     /**
2016      * Assert that no link containing the Exact text is present.
2017      *
2018      * @param linkText
2019      */
2020     public void assertLinkNotPresentWithExactText(String linkText) {
2021         assertTrue("Link with Exact text [" + linkText
2022                 + "] found in response.", !getTestingEngine()
2023                 .hasLinkWithExactText(linkText, 0));
2024     }
2025 
2026     /**
2027      * Assert that a link containing the Exact text is present.
2028      *
2029      * @param linkText
2030      * @param index The 0-based index, when more than one link with the same text is expected.
2031      */
2032     public void assertLinkPresentWithExactText(String linkText, int index) {
2033         assertTrue("Link with Exact text [" + linkText + "] and index ["
2034                 + index + "] not found in response.", getTestingEngine()
2035                 .hasLinkWithExactText(linkText, index));
2036     }
2037 
2038     /**
2039      * Assert that no link containing the Exact text is present.
2040      *
2041      * @param linkText
2042      * @param index The 0-based index, when more than one link with the same text is expected.
2043      */
2044     public void assertLinkNotPresentWithExactText(String linkText, int index) {
2045         assertTrue("Link with Exact text [" + linkText + "] and index "
2046                 + index + " found in response.", !getTestingEngine()
2047                 .hasLinkWithExactText(linkText, index));
2048     }
2049 
2050     // END RFE 996031...
2051 
2052     /**
2053      * Assert that a link containing a specified image is present.
2054      *
2055      * @param imageFileName A suffix of the image's filename; for example, to match <tt>"images/my_icon.png"</tt>,
2056      *            you could just pass in <tt>"my_icon.png"</tt>.
2057      */
2058     public void assertLinkPresentWithImage(String imageFileName) {
2059         assertTrue("Link with image file [" + imageFileName
2060                 + "] not found in response.", getTestingEngine()
2061                 .hasLinkWithImage(imageFileName, 0));
2062     }
2063 
2064     /**
2065      * Assert that a link containing a specified image is present.
2066      *
2067      * @param imageFileName A suffix of the image's filename; for example, to match <tt>"images/my_icon.png"</tt>,
2068      *            you could just pass in <tt>"my_icon.png"</tt>.
2069      * @param index The 0-based index, when more than one link with the same image is expected.
2070      */
2071     public void assertLinkPresentWithImage(String imageFileName, int index) {
2072         assertTrue("Link with image file [" + imageFileName
2073                 + "] and index " + index + " not found in response.", getTestingEngine()
2074                 .hasLinkWithImage(imageFileName, index));
2075     }
2076 
2077     /**
2078      * Assert that a link containing a specified image is not present.
2079      *
2080      * @param imageFileName A suffix of the image's filename; for example, to match <tt>"images/my_icon.png"</tt>,
2081      *            you could just pass in <tt>"my_icon.png"</tt>.
2082      */
2083     public void assertLinkNotPresentWithImage(String imageFileName) {
2084         assertFalse("Link with image file [" + imageFileName
2085                 + "] found in response.", getTestingEngine().hasLinkWithImage(
2086                 imageFileName, 0));
2087     }
2088 
2089     /**
2090      * Assert that a link containing a specified image is not present.
2091      *
2092      * @param imageFileName A suffix of the image's filename; for example, to match <tt>"images/my_icon.png"</tt>,
2093      *            you could just pass in <tt>"my_icon.png"</tt>.
2094      * @param index The 0-based index, when more than one link with the same image is expected.
2095      */
2096     public void assertLinkNotPresentWithImage(String imageFileName, int index) {
2097         assertFalse("Link with image file [" + imageFileName
2098                 + "] and index " + index + " found in response.",
2099                 getTestingEngine().hasLinkWithImage(imageFileName, index));
2100     }
2101 
2102     /**
2103      * Assert that an element with a given id is present.
2104      *
2105      * @param anID element id to test for.
2106      */
2107     public void assertElementPresent(String anID) {
2108         assertTrue("Unable to locate element with id \"" + anID + "\"",
2109                 getTestingEngine().hasElement(anID));
2110     }
2111 
2112     /**
2113      * Assert that an element with a given id is not present.
2114      *
2115      * @param anID element id to test for.
2116      */
2117     public void assertElementNotPresent(String anID) {
2118         assertFalse("Located element with id \"" + anID + "\"",
2119                 getTestingEngine().hasElement(anID));
2120     }
2121 
2122     /**
2123      * Assert that an element with a given xpath is present.
2124      *
2125      * @param xpath element xpath to test for.
2126      */
2127     public void assertElementPresentByXPath(String xpath) {
2128         assertTrue("Unable to locate element with xpath \"" + xpath
2129                 + "\"", getTestingEngine().hasElementByXPath(xpath));
2130     }
2131 
2132     /**
2133      * Assert that an element with a given xpath is not present.
2134      *
2135      * @param xpath element xpath to test for.
2136      */
2137     public void assertElementNotPresentByXPath(String xpath) {
2138         assertFalse("Located element with xpath \"" + xpath + "\"",
2139                 getTestingEngine().hasElementByXPath(xpath));
2140     }
2141 
2142     /**
2143      * Get all the comments in a document, as a list of strings.
2144      */
2145     public List<String> getComments() {
2146       return getTestingEngine().getComments();
2147     }
2148 
2149     /**
2150      * Assert that a comment is present.
2151      *
2152      * @param comment
2153      */
2154     public void assertCommentPresent(String comment) {
2155       assertTrue("Comment present: '" + comment + "'", getComments().contains(comment.trim()));
2156     }
2157 
2158     /**
2159      * Assert that a comment is not present.
2160      *
2161      * @param comment
2162      */
2163     public void assertCommentNotPresent(String comment) {
2164       assertFalse("Comment not present: '" + comment + "'", getComments().contains(comment.trim()));
2165     }
2166 
2167     /**
2168      * Assert that a given element contains specific text.
2169      *
2170      * @param elementID id of element to be inspected.
2171      * @param text to check for.
2172      */
2173     public void assertTextInElement(String elementID, String text) {
2174         assertTrue("Unable to locate element with id \"" + elementID
2175                 + "\"", getTestingEngine().hasElement(elementID));
2176         assertTrue("Unable to locate [" + text + "] in element \""
2177                 + elementID + "\"", getTestingEngine()
2178                 .isTextInElement(elementID, text));
2179     }
2180 
2181     public void assertTextNotInElement(String elementID, String text) {
2182         assertElementPresent(elementID);
2183         assertTrue("Unable to locate element with id \"" + elementID
2184                 + "\"", getTestingEngine().hasElement(elementID));
2185         assertFalse("Text [" + text + "] found in element [" + elementID
2186                 + "] when not expected", getTestingEngine().isTextInElement(
2187                 elementID, text));
2188     }
2189 
2190     /**
2191      * Assert that a given element matches a specific regexp.
2192      *
2193      * @param elementID id of element to be inspected.
2194      * @param regexp to match.
2195      */
2196     public void assertMatchInElement(String elementID, String regexp) {
2197         assertTrue("Unable to locate element with id \"" + elementID
2198                 + "\"", getTestingEngine().hasElement(elementID));
2199         assertTrue("Unable to match [" + regexp + "] in element \""
2200                 + elementID + "\"", getTestingEngine().isMatchInElement(
2201                 elementID, regexp));
2202     }
2203 
2204     /**
2205      * Assert that a given element does not match a specific regexp.
2206      *
2207      * @param elementID id of element to be inspected.
2208      * @param regexp to match.
2209      */
2210     public void assertNoMatchInElement(String elementID, String regexp) {
2211         assertElementPresent(elementID);
2212         assertTrue("Unable to locate element with id \"" + elementID
2213                 + "\"", getTestingEngine().hasElement(elementID));
2214         assertFalse("Regexp [" + regexp + "] matched in element ["
2215                 + elementID + "] when not expected", getTestingEngine()
2216                 .isMatchInElement(elementID, regexp));
2217     }
2218 
2219     /**
2220      * Assert that a window with the given name is open.
2221      *
2222      * @param windowName
2223      */
2224     public void assertWindowPresent(String windowName) {
2225         assertTrue("Unable to locate window [" + windowName + "].",
2226                 getTestingEngine().hasWindow(windowName));
2227     }
2228 
2229     /**
2230      * Assert that a window with the given ID is open.
2231      *
2232      * @param windowID Javascript window ID.
2233      */
2234     public void assertWindowPresent(int windowID) {
2235         assertTrue("There is no window with index [" + windowID + "].",
2236                 getTestingEngine().getWindowCount() > windowID);
2237     }
2238 
2239     /**
2240      * Assert that at least one window with the given title is open.
2241      *
2242      * @param title
2243      */
2244     public void assertWindowPresentWithTitle(String title) {
2245         assertTrue(
2246                 "Unable to locate window with title [" + title + "].",
2247                 getTestingEngine().hasWindowByTitle(title));
2248     }
2249 
2250     /**
2251      * Assert that the number of opened windows equals given value.
2252      *
2253      * @param windowCount Window count
2254      */
2255     public void assertWindowCountEquals(int windowCount) {
2256         assertTrue("Window count is "
2257                         + getTestingEngine().getWindowCount() + " but "
2258                         + windowCount + " was expected.", getTestingEngine()
2259                         .getWindowCount() == windowCount);
2260     }
2261 
2262     /**
2263      * Assert that a frame with the given name or ID is present.
2264      *
2265      * @param frameNameOrId Name or ID of the frame. ID is checked first.
2266      */
2267     public void assertFramePresent(String frameNameOrId) {
2268         assertTrue("Unable to locate frame with name or ID ["
2269                 + frameNameOrId + "].", getTestingEngine().hasFrame(
2270                 frameNameOrId));
2271     }
2272 
2273     /**
2274      * Checks to see if a cookie is present in the response.
2275      *
2276      * @param cookieName The cookie name
2277      */
2278     public void assertCookiePresent(String cookieName) {
2279         List<?> cookies = getTestingEngine().getCookies();
2280         for (Iterator<?> i = cookies.iterator(); i.hasNext();) {
2281             if (((Cookie) i.next()).getName().equals(cookieName)) {
2282                 return;
2283             }
2284         }
2285         fail("Could not find Cookie with name [" + cookieName + "]");
2286     }
2287 
2288     /**
2289      * Check to see if a cookie has the given value.
2290      *
2291      * @param cookieName The cookie name
2292      * @param expectedValue The cookie value
2293      */
2294     public void assertCookieValueEquals(String cookieName, String expectedValue) {
2295         assertCookiePresent(cookieName);
2296         List<?> cookies = getTestingEngine().getCookies();
2297         for (Iterator<?> i = cookies.iterator(); i.hasNext();) {
2298             Cookie c = (Cookie) i.next();
2299             if (c.getName().equals(cookieName) && c.getValue().equals(expectedValue)) {
2300                 return;
2301             }
2302         }
2303         fail("Could not find cookie with name [" + cookieName + "] and value [" + expectedValue + "]");
2304     }
2305 
2306     /**
2307      * Check to see if a cookie value match the given regexp.
2308      *
2309      * @param cookieName The cookie name
2310      * @param regexp The regexp
2311      */
2312     public void assertCookieValueMatch(String cookieName, String regexp) {
2313         assertCookiePresent(cookieName);
2314         RE re = null;
2315         try {
2316             re = new RE(regexp, RE.MATCH_SINGLELINE);
2317         } catch (RESyntaxException e) {
2318             fail(e.getMessage());
2319         }
2320         List<?> cookies = getTestingEngine().getCookies();
2321         for (Iterator<?> i = cookies.iterator(); i.hasNext();) {
2322             Cookie c = (Cookie) i.next();
2323             if (c.getName().equals(cookieName) &&
2324                     re.match(c.getValue())) {
2325                 return;
2326             }
2327         }
2328         fail("Could not find cookie with name [" + cookieName + "] with value matching [" + regexp + "]");
2329     }
2330 
2331     // Form interaction methods
2332 
2333     /**
2334      * @deprecated Use {@link WebTester#getElementAttributeByXPath(String, String)}
2335      */
2336     public String getFormElementValue(String formElementName) {
2337         assertFormElementPresent(formElementName);
2338         return getTestingEngine().getElementAttributByXPath(
2339                 "//input[@name='" + formElementName + "']", "value");
2340     }
2341 
2342     /**
2343      * Begin interaction with a specified form. If form interaction methods are called without explicitly calling this
2344      * method first, JWebUnit will attempt to determine itself which form is being manipulated.
2345      *
2346      * It is not necessary to call this method if their is only one form on the current page.
2347      *
2348      * @param index 0-based index of the form to work with.
2349      */
2350     public void setWorkingForm(int index) {
2351         getTestingEngine().setWorkingForm(index);
2352     }
2353 
2354     /**
2355      * Begin interaction with a specified form. If form interaction methods are called without explicitly calling this
2356      * method first, JWebUnit will attempt to determine itself which form is being manipulated.
2357      *
2358      * It is not necessary to call this method if their is only one form on the current page.
2359      *
2360      * @param nameOrId name or id of the form to work with.
2361      */
2362     public void setWorkingForm(String nameOrId) {
2363         assertFormPresent(nameOrId);
2364         getTestingEngine().setWorkingForm(nameOrId, 0);
2365     }
2366 
2367     /**
2368      * Begin interaction with a specified form. If form interaction methods are called without explicitly calling this
2369      * method first, JWebUnit will attempt to determine itself which form is being manipulated.
2370      *
2371      * It is not necessary to call this method if their is only one form on the current page.
2372      *
2373      * @param nameOrId name or id of the form to work with.
2374      * @param index The 0-based index, when more than one form with the same name is expected.
2375      */
2376     public void setWorkingForm(String nameOrId, int index) {
2377         assertFormPresent(nameOrId, index);
2378         getTestingEngine().setWorkingForm(nameOrId, index);
2379     }
2380 
2381     /**
2382      * Set the value of a text or password input field.
2383      *
2384      * @param inputName name of form element.
2385      * @param value value to set.
2386      */
2387     public void setTextField(String inputName, String value) {
2388         assertFormElementPresent(inputName);
2389         getTestingEngine().setTextField(inputName, value);
2390     }
2391 
2392     /**
2393      * Set the value of an hidden input field.
2394      *
2395      * @param inputName name of form element.
2396      * @param value value to set.
2397      */
2398     public void setHiddenField(String inputName, String value) {
2399         assertFormElementPresent(inputName);
2400         getTestingEngine().setHiddenField(inputName, value);
2401     }
2402 
2403     /**
2404      * Select a specified checkbox. If the checkbox is already checked then the checkbox will stay checked.
2405      *
2406      * @param checkBoxName name of checkbox to be selected.
2407      */
2408     public void checkCheckbox(String checkBoxName) {
2409         assertCheckboxPresent(checkBoxName);
2410         getTestingEngine().checkCheckbox(checkBoxName);
2411     }
2412 
2413     /**
2414      * Select a specified checkbox. If the checkbox is already checked then the checkbox will stay checked.
2415      *
2416      * @param checkBoxName name of checkbox to be selected.
2417      * @param value value of checkbox to be selected.
2418      */
2419     public void checkCheckbox(String checkBoxName, String value) {
2420         assertCheckboxPresent(checkBoxName);
2421         getTestingEngine().checkCheckbox(checkBoxName, value);
2422     }
2423 
2424     /**
2425      * Deselect a specified checkbox. If the checkbox is already unchecked then the checkbox will stay unchecked.
2426      *
2427      * @param checkBoxName name of checkbox to be deselected.
2428      */
2429     public void uncheckCheckbox(String checkBoxName) {
2430         assertFormElementPresent(checkBoxName);
2431         getTestingEngine().uncheckCheckbox(checkBoxName);
2432     }
2433 
2434     /**
2435      * Deselect a specified checkbox. If the checkbox is already unchecked then the checkbox will stay unchecked.
2436      *
2437      * @param checkBoxName name of checkbox to be deselected.
2438      * @param value value of checkbox to be deselected.
2439      */
2440     public void uncheckCheckbox(String checkBoxName, String value) {
2441         assertFormElementPresent(checkBoxName);
2442         getTestingEngine().uncheckCheckbox(checkBoxName, value);
2443     }
2444 
2445     /**
2446      * Select options with given display labels in a select element.
2447      *
2448      * @param selectName name of select element.
2449      * @param labels labels of options to be selected.
2450      */
2451     public void selectOptions(String selectName, String[] labels) {
2452         assertSelectOptionsPresent(selectName, labels);
2453         selectOptionsByLabel(selectName, labels);
2454     }
2455 
2456     /**
2457      * Select an option with a given display label in a select element.
2458      *
2459      * @param selectName name of select element.
2460      * @param label label of option to be selected.
2461      */
2462     public void selectOption(String selectName, String label) {
2463         selectOptions(selectName, new String[] { label });
2464     }
2465 
2466     /**
2467      * Select an option with a given display label in Nth select element.
2468      *
2469      * @param selectName name of select element.
2470      * @param index the 0-based index of the select element when multiple
2471      * select elements are expected.
2472      * @param label label of option to be selected.
2473      */
2474     public void selectOption(String selectName, int index, String label) {
2475         selectOptions(selectName, index, new String[] { label });
2476     }
2477 
2478     /**
2479      * Select options with given display labels in the Nth select element.
2480      *
2481      * @param selectName name of select element.
2482      * @param index the 0-based index of the select element when multiple
2483      * select elements are expected.
2484      * @param labels labels of options to be selected.
2485      */
2486     public void selectOptions(String selectName, int index, String[] labels) {
2487         assertSelectOptionsPresent(selectName, index, labels);
2488         selectOptionsByLabel(selectName, index, labels);
2489     }
2490 
2491 
2492     /**
2493      * Select options with given values in a select element.
2494      *
2495      * @param selectName name of select element.
2496      * @param values values of options to be selected.
2497      */
2498     public void selectOptionsByValues(String selectName, String[] values) {
2499         assertSelectOptionValuesPresent(selectName, values);
2500         getTestingEngine().selectOptions(selectName, values);
2501     }
2502 
2503     /**
2504      * Select an option with a given value in the Nth select element.
2505      *
2506      * @param selectName name of select element.
2507      * @param index the 0-based index of the select element when multiple
2508      * select elements are expected.
2509      * @param values values of options to be selected.
2510      */
2511     public void selectOptionByValue(String selectName, String value) {
2512         selectOptionsByValues(selectName, new String[] { value });
2513     }
2514 
2515     /**
2516      * Select options with given values in the Nth select element.
2517      *
2518      * @param selectName name of select element.
2519      * @param index the 0-based index of the select element when multiple
2520      * select elements are expected.
2521      * @param values values of options to be selected.
2522      */
2523     public void selectOptionsByValues(String selectName, int index, String[] values) {
2524         assertSelectOptionValuesPresent(selectName, index, values);
2525         getTestingEngine().selectOptions(selectName, index, values);
2526     }
2527 
2528     /**
2529      * Select an option with a given value in a select element.
2530      *
2531      * @param selectName name of select element.
2532      * @param values values of options to be selected.
2533      */
2534     public void selectOptionByValue(String selectName, int index, String value) {
2535         selectOptionsByValues(selectName, index, new String[] { value });
2536     }
2537 
2538 
2539     // Form submission and link navigation methods
2540 
2541     /**
2542      * Submit form - default submit button will be used (unnamed submit button, or named button if there is only one on
2543      * the form.
2544      */
2545     public void submit() {
2546         assertSubmitButtonPresent();
2547         getTestingEngine().submit();
2548     }
2549 
2550     /**
2551      * Submit form by pressing named button.
2552      *
2553      * @param buttonName Submit button name attribut value.
2554      */
2555     public void submit(String buttonName) {
2556         assertSubmitButtonPresent(buttonName);
2557         getTestingEngine().submit(buttonName);
2558     }
2559 
2560     /**
2561      * Submit the form by pressing the named button with the given value (label). Useful if you have more than one
2562      * submit button with same name.
2563      *
2564      * @param buttonName Submit button name attribut value.
2565      * @param buttonValue Submit button value attribut value.
2566      */
2567     public void submit(String buttonName, String buttonValue) {
2568         assertSubmitButtonPresent(buttonName, buttonValue);
2569         getTestingEngine().submit(buttonName, buttonValue);
2570     }
2571 
2572     /**
2573      * Reset the current form using the default reset button. See {@link #getForm}for an explanation of how the current
2574      * form is established.
2575      */
2576     public void reset() {
2577         assertResetButtonPresent();
2578         getTestingEngine().reset();
2579     }
2580 
2581     /**
2582      * Navigate by selection of a link containing given text.
2583      *
2584      * @param linkText Text in the link.
2585      */
2586     public void clickLinkWithText(String linkText) {
2587         assertLinkPresentWithText(linkText);
2588         getTestingEngine().clickLinkWithText(linkText, 0);
2589     }
2590 
2591     /**
2592      * Navigate by selecting Nth link containing given text.
2593      *
2594      * @param linkText Text in the link.
2595      * @param index The 0-based index, when more than one link with the same text is expected.
2596      */
2597     public void clickLinkWithText(String linkText, int index) {
2598         assertLinkPresentWithText(linkText, index);
2599         getTestingEngine().clickLinkWithText(linkText, index);
2600     }
2601 
2602     /**
2603      * Navigate by selection of a link with the exact given text.
2604      *
2605      * @param linkText Text of the link.
2606      */
2607     public void clickLinkWithExactText(String linkText) {
2608         assertLinkPresentWithExactText(linkText);
2609         getTestingEngine().clickLinkWithExactText(linkText, 0);
2610     }
2611 
2612     /**
2613      * Navigate by selecting Nth link with the exact given text.
2614      *
2615      * @param linkText Text of the link.
2616      * @param index The 0-based index, when more than one link with the same text is expected.
2617      */
2618     public void clickLinkWithExactText(String linkText, int index) {
2619         assertLinkPresentWithExactText(linkText, index);
2620         getTestingEngine().clickLinkWithExactText(linkText, index);
2621     }
2622 
2623     /**
2624      * Click the button with the given id.
2625      *
2626      * @param buttonId Button ID attribut value.
2627      */
2628     public void clickButton(String buttonId) {
2629         assertButtonPresent(buttonId);
2630         getTestingEngine().clickButton(buttonId);
2631     }
2632 
2633     /**
2634      * Clicks a button with <code>text</code> of the value attribute.
2635      *
2636      * @param buttonValueText The text of the button (contents of the value attribute).
2637      */
2638     public void clickButtonWithText(String buttonValueText) {
2639         assertButtonPresentWithText(buttonValueText);
2640         getTestingEngine().clickButtonWithText(buttonValueText);
2641     }
2642 
2643     /**
2644      * Navigate by selection of a link with a given image.
2645      *
2646      * @param imageFileName A suffix of the image's filename; for example, to match <tt>"images/my_icon.png"</tt>,
2647      *            you could just pass in <tt>"my_icon.png"</tt>.
2648      */
2649     public void clickLinkWithImage(String imageFileName) {
2650         assertLinkPresentWithImage(imageFileName);
2651         getTestingEngine().clickLinkWithImage(imageFileName, 0);
2652     }
2653 
2654     /**
2655      * Navigate by selection of a link with a given image.
2656      *
2657      * @param imageFileName A suffix of the image's filename; for example, to match <tt>"images/my_icon.png"</tt>,
2658      *            you could just pass in <tt>"my_icon.png"</tt>.
2659      * @param index The 0-based index, when more than one link with the same image is expected.
2660      */
2661     public void clickLinkWithImage(String imageFileName, int index) {
2662         assertLinkPresentWithImage(imageFileName, index);
2663         getTestingEngine().clickLinkWithImage(imageFileName, index);
2664     }
2665 
2666     /**
2667      * Navigate by selection of a link with given id.
2668      *
2669      * @param linkId id of link
2670      */
2671     public void clickLink(String linkId) {
2672         assertLinkPresent(linkId);
2673         getTestingEngine().clickLink(linkId);
2674     }
2675 
2676     /**
2677      * Clicks a radio option. Asserts that the radio option exists first. *
2678      *
2679      * @param radioGroup name of the radio group.
2680      * @param radioOption value of the option to check for.
2681      */
2682     public void clickRadioOption(String radioGroup, String radioOption) {
2683         assertRadioOptionPresent(radioGroup, radioOption);
2684         getTestingEngine().clickRadioOption(radioGroup, radioOption);
2685     }
2686 
2687     /**
2688      * Click element with given xpath.
2689      *
2690      * @param xpath xpath of the element.
2691      */
2692     public void clickElementByXPath(String xpath) {
2693         assertElementPresentByXPath(xpath);
2694         getTestingEngine().clickElementByXPath(xpath);
2695     }
2696 
2697     /**
2698      * Get the attribute value of the given element.
2699      * For example, if you have an element <code>&lt;img src="test.gif" alt="picture"&gt;</code>
2700      * getElementAttributeByXPath("//img[@src='test.gif']", "alt") returns "picture".
2701      *
2702      * @param xpath XPath of the element
2703      * @param attribute Name of the attribute
2704      * @return The value of the attribute
2705      */
2706     public String getElementAttributeByXPath(String xpath, String attribute) {
2707         assertElementPresentByXPath(xpath);
2708         return getTestingEngine().getElementAttributByXPath(xpath, attribute);
2709     }
2710 
2711     /**
2712      * @deprecated Use {@link #getElementAttributeByXPath(String, String)}
2713      */
2714     public String getElementAttributByXPath(String xpath, String attribute) {
2715       return getElementAttributeByXPath(xpath, attribute);
2716     }
2717 
2718     /**
2719      * Get text of the given element.
2720      *
2721      * @param xpath xpath of the element.
2722      */
2723     public String getElementTextByXPath(String xpath){
2724         assertElementPresentByXPath(xpath);
2725       return getTestingEngine().getElementTextByXPath(xpath);
2726     }
2727 
2728     /**
2729      * Get an element for a particular xpath.
2730      *
2731      * @param xpath XPath to search
2732      * @return the requested element
2733    * @throws AssertionError if the element xpath is not found
2734      */
2735     public IElement getElementByXPath(String xpath) {
2736       assertElementPresentByXPath(xpath);
2737       return getTestingEngine().getElementByXPath(xpath);
2738     }
2739 
2740     /**
2741      * Return {@code true} if the given element by XPath exists.
2742      *
2743      * @param xpath XPath to search
2744      * @return {@code true} if the the requested element
2745      * @throws AssertionError if the element xpath is not found
2746      */
2747     public boolean hasElementByXPath(String xpath) {
2748       return getTestingEngine().getElementByXPath(xpath) != null;
2749     }
2750 
2751     /**
2752      * Get an element for a particular ID.
2753      *
2754      * @param id element ID to find
2755      * @return the requested element
2756    * @throws AssertionError if the element is not found
2757      */
2758     public IElement getElementById(String id) {
2759       assertElementPresent(id);
2760       return getTestingEngine().getElementByID(id);
2761     }
2762     
2763     /**
2764      * Returns {@code true} if an element with the given ID exists.
2765      * 
2766      * @param id element ID to find
2767      * @return {@code true} if the element ID exists, {@code false} otherwise
2768      */
2769     public boolean hasElementById(String id) {
2770     	return getTestingEngine().getElementByID(id) != null;
2771     }
2772 
2773     /**
2774      * Get elements for a particular xpath.
2775      *
2776      * @param xpath XPath to search
2777      * @return the requested elements found
2778      */
2779     public List<IElement> getElementsByXPath(String xpath) {
2780       return getTestingEngine().getElementsByXPath(xpath);
2781     }
2782 
2783     /**
2784      * Return {@code true} if the given elements by XPath exists.
2785      *
2786      * @param xpath XPath to search
2787      * @return {@code true} if the given elements by XPath exist
2788      */
2789     public boolean hasElementsByXPath(String xpath) {
2790     	List<IElement> list = getTestingEngine().getElementsByXPath(xpath);
2791     	return list != null && !list.isEmpty();
2792     }
2793 
2794     // label methods
2795     /**
2796      * Assert a label for a given ID exists.
2797      */
2798     public void assertLabelPresent(String id) {
2799       assertNotNull("No label found with id [" + id + "]", getLabel(id));
2800     }
2801 
2802     /**
2803      * Get a label for a particular ID.
2804      *
2805      * @param id
2806      * @return
2807      */
2808     private IElement getLabel(String id) {
2809       // get all labels
2810       for (IElement e : getTestingEngine().getElementsByXPath("//label")) {
2811         if (id.equals(e.getAttribute("id")))
2812           return e;	// label found
2813       }
2814       return null;
2815     }
2816 
2817     /**
2818      * Find a particular element with given text
2819      *
2820      * @param elementName the element type e.g. "input", "label"
2821      * @param text the text to search for
2822      * @return the found element, or null
2823      */
2824     private IElement getElementWithText(String elementName, String text) {
2825       for (IElement e : getTestingEngine().getElementsByXPath("//" + elementName)) {
2826         if (elementName.equals(e.getName()) && text.equals(e.getTextContent())) {
2827           return e;
2828         }
2829       }
2830       return null;
2831     }
2832 
2833     /**
2834      * Assert a label exists.
2835      */
2836     public void assertLabelMatches(String regexp) {
2837       // get regexp
2838         RE re = null;
2839         try {
2840             re = new RE(regexp, RE.MATCH_SINGLELINE);
2841         } catch (RESyntaxException e) {
2842             fail(e.toString());
2843         }
2844 
2845         // get all labels
2846       for (IElement e : getTestingEngine().getElementsByXPath("//label")) {
2847         if (e.getName().equals("label") && re.match( e.getTextContent() ))
2848           return;	// label found
2849       }
2850       fail("No label found with text matching [" + regexp + "]");
2851     }
2852 
2853     /**
2854      * Get all the fields of type <code>input</code>, <code>textarea</code> or <code>select</code>
2855      * that are referenced or contained in a particular label.
2856      *
2857      * @param label The label to consider
2858      * @return A list of all fields contained or referenced in this label
2859      */
2860     public List<IElement> getFieldsForLabel(IElement label) {
2861       List<IElement> fields = new java.util.ArrayList<IElement>();
2862       // a direct "for" attribute
2863       if (label.getAttribute("for") != null) {
2864         IElement e = getTestingEngine().getElementByID(label.getAttribute("for"));
2865         if (e != null)
2866           fields.add(e);
2867       }
2868 
2869       // implicitly the elements inside the label
2870       if (fields.isEmpty()) {
2871         // get elements inside the label
2872         for (IElement e : label.getChildren()) {
2873           if (e.getName().equals("input") || e.getName().equals("textarea") || e.getName().equals("select")) {
2874             fields.add(e);
2875           }
2876         }
2877       }
2878 
2879       return fields;
2880     }
2881 
2882 
2883     /**
2884      * Private method - test the value of a field connected to a particular IElement label.
2885      *
2886      * @param identifier the HTML ID for the given labelled field
2887      * @param label the label found for the given HTML field
2888      * @param fieldText the value to check is equal
2889      */
2890     private void assertLabeledFieldEquals(String identifier, IElement label, String fieldText) {
2891       String value = getLabeledFieldValue(identifier, label);
2892       assertEquals("unexpected value of field for label [" + identifier + "]", fieldText, value == null ? "" : value);
2893     }
2894 
2895     /**
2896      * Get the current value of a given labelled field.
2897      *
2898      * @param identifier the HTML ID for the given labelled field
2899      * @param label the label found for the given HTML ID
2900      * @return the value found in a field for the given label/ID, or
2901      * 		<code>null</code> if none was found
2902      */
2903     public String getLabeledFieldValue(String identifier, IElement label) {
2904       List<IElement> fields = getFieldsForLabel(label);
2905 
2906       assertFalse("No field found for label [" + identifier + "]", fields.isEmpty());
2907       String value = null;
2908       // cycle through all fields trying to find value
2909       for (IElement field : fields) {
2910         if (value != null)	// stop at first correct value found
2911           break;
2912         if (field == null)
2913           throw new RuntimeException("unexpected null field");
2914 
2915         if ("input".equals(field.getName())) {
2916           if (field.getAttribute("type") != null) {
2917             if (field.getAttribute("type").toLowerCase().equals("checkbox")) {
2918               if (field.getAttribute("checked") != null) {
2919                 value = field.getAttribute("value");
2920               }
2921             } else if (field.getAttribute("type").toLowerCase().equals("radio")) {
2922               if (field.getAttribute("checked") != null) {
2923                 value = field.getAttribute("value");
2924               }
2925             } else {
2926               // any other input type
2927               value = field.getAttribute("value");
2928             }
2929           } else {
2930             // unspecified input type, default = text
2931             value = field.getAttribute("value");
2932           }
2933         } else if ("textarea".equals(field.getName())) {
2934           value = field.getTextContent();
2935         } else if ("select".equals(field.getName())) {
2936           // get the selected option
2937                 for (IElement child : field.getChildren()) {
2938                     if (child.getName().equals("option") && child.getAttribute("selected") != null) {
2939                         value = child.getAttribute("value");
2940                         break;
2941                     }
2942                     if (child.getName().equals("optgroup")) {
2943                         for (IElement subchild : child.getChildren()) {
2944                             if (subchild.getName().equals("option") && subchild.getAttribute("selected") != null) {
2945                                 value = child.getAttribute("value");
2946                                 break;
2947                             }
2948                         }
2949                     }
2950                 }
2951         } else {
2952           throw new RuntimeException("Unexpected field type " + field.getName());
2953         }
2954       }
2955 
2956       return value;
2957     }
2958 
2959     /**
2960      * Assert that a labeled field exists (for the given ID) and the
2961      * field that it labels equals the given text
2962      *
2963      * @param id the HTML ID for the given labelled field
2964      * @param fieldText the text that the field's value should equal
2965      * @see #getLabeledFieldValue(String, IElement, String)
2966      * @see #getLabel(String)
2967      */
2968     public void assertLabeledFieldEquals(String id, String fieldText) {
2969       IElement label = getLabel(id);
2970       assertNotNull("no label for id [" + id + "] found", label);
2971 
2972       assertLabeledFieldEquals(id, label, fieldText);
2973     }
2974 
2975     public void setLabeledFormElementField(String id, String value) {
2976       IElement label = getLabel(id);
2977       assertNotNull("no label for id [" + id + "] found", label);
2978 
2979       List<IElement> fields = getFieldsForLabel(label);
2980       assertFalse("there should be at least one element referenced for label [" + id + "]", fields.size()==0);
2981 
2982       // find the first element that we can change
2983       for (IElement field : fields) {
2984         if (field == null)
2985           throw new RuntimeException("unexpected null field");
2986 
2987         if ("input".equals(field.getName())) {
2988           if (field.getAttribute("type") != null) {
2989             if (field.getAttribute("type").toLowerCase().equals("checkbox")) {
2990               if (value.equals(field.getAttribute("value"))) {
2991                 field.setAttribute("checked");
2992                 return;
2993               }
2994             } else if (field.getAttribute("type").toLowerCase().equals("radio")) {
2995               if (value.equals(field.getAttribute("value"))) {
2996                 field.setAttribute("checked");
2997                 return;
2998               }
2999             } else {
3000               // any other input type
3001               field.setAttribute("value", value);
3002               return;
3003             }
3004           } else {
3005             // unspecified input type, default = text
3006             field.setAttribute("value", value);
3007             return;
3008           }
3009         } else if ("textarea".equals(field.getName())) {
3010           field.setTextContent(value);
3011           return;
3012         } else if ("select".equals(field.getName())) {
3013           // get the selected option
3014           for (IElement children : field.getChildren()) {
3015             // find the option which matches the given value (we can't specify random values)
3016             if (children.getName().equals("option") && value.equals(children.getAttribute("value"))) {
3017               children.setAttribute("selected");
3018               return;
3019             }
3020           }
3021         } else {
3022           throw new RuntimeException("Unexpected field type " + field.getName());
3023         }
3024       }
3025 
3026       fail("could not find any fields for label [" + id + "] to set.");
3027     }
3028 
3029     // Window and Frame Navigation Methods
3030 
3031     /**
3032      * Make a given window active.
3033      *
3034      * @param windowName Name of the window.
3035      */
3036     public void gotoWindow(String windowName) {
3037         assertWindowPresent(windowName);
3038         getTestingEngine().gotoWindow(windowName);
3039     }
3040 
3041     /**
3042      * Make a given window active.
3043      *
3044      * @param windowID Javascript ID of the window
3045      * @deprecated Javascript ID does'nt not exists. Currently this is an index
3046      * in the list of available windows, but this is not portable (and probably not stable).
3047      * Use {@link #gotoWindow(String)} or {@link #gotoWindowByTitle(String)} instead.
3048      */
3049     @Deprecated
3050     public void gotoWindow(int windowID) {
3051         assertWindowPresent(windowID);
3052         getTestingEngine().gotoWindow(windowID);
3053     }
3054 
3055     /**
3056      * Make the root window active. Used to reset the effect of {@link ITestingEngine#gotoFrame(String)}.
3057      */
3058     public void gotoRootWindow() {
3059         getTestingEngine().gotoRootWindow();
3060     }
3061 
3062     /**
3063      * Make first window with the given title active.
3064      *
3065      * @param title Title of the window.
3066      */
3067     public void gotoWindowByTitle(String title) {
3068         assertWindowPresentWithTitle(title);
3069         getTestingEngine().gotoWindowByTitle(title);
3070     }
3071 
3072     /**
3073      * Make the given frame active.
3074      *
3075      * @param frameNameOrId Name or ID of the frame. ID is checked first.
3076      */
3077     public void gotoFrame(String frameNameOrId) {
3078         getTestingEngine().gotoFrame(frameNameOrId);
3079     }
3080 
3081     /**
3082      * Go to the given page like if user has typed the URL manually in the browser. Use
3083      * {@link TestContext#setBaseUrl(String) getTestContext().setBaseUrl(String)} to define base URL. Absolute URL
3084      * should start with "http://", "https://" or "www.".
3085      *
3086      * @param url absolute or relative URL (relative to base URL).
3087      * @throws TestingEngineResponseException If something bad happend (404)
3088      */
3089     public void gotoPage(String url) throws TestingEngineResponseException {
3090         try {
3091             getTestingEngine().gotoPage(createUrl(url, getTestContext().getBaseUrl()));
3092         } catch (MalformedURLException e) {
3093             fail(e.getLocalizedMessage());
3094         }
3095     }
3096 
3097     /**
3098      * Print all the cookies to stdout.
3099      *
3100      */
3101     public void dumpCookies() {
3102         List<?> cookies = getTestingEngine().getCookies();
3103         for (Iterator<?> i = cookies.iterator(); i.hasNext();) {
3104             Cookie c = (Cookie) i.next();
3105             System.out.println("Name=" + c.getName() + "; Value="
3106                     + c.getValue() + "; Domain=" + c.getDomain() + "; Comment="
3107                     + c.getComment() + "; MaxAge=" + c.getMaxAge() + "; Path="
3108                     + c.getPath() + "; Version=" + c.getVersion());
3109         }
3110     }
3111 
3112     /**
3113      * Get the source of the HTML page (like in a real browser), or HTTP body for a non HTML content.
3114      *
3115      * @return The HTML content.
3116      */
3117     public String getPageSource() {
3118         return getTestingEngine().getPageSource();
3119     }
3120 
3121     /**
3122      * Get the last data sent by the server.
3123      *
3124      * @return HTTP server response.
3125      */
3126     public String getServerResponse() {
3127         return getTestingEngine().getServerResponse();
3128     }
3129 
3130     /**
3131      * @deprecated use {@link #getServerResponse()}
3132      * @return
3133      */
3134     public String getServeurResponse() {
3135       return getServerResponse();
3136     }
3137 
3138     /**
3139      * Save the last downloaded page (or file) to the disk.
3140      *
3141      * @param f The file name.
3142      */
3143     public void saveAs(File f) {
3144         InputStream in = getTestingEngine().getInputStream();
3145         int c=0;
3146         try {
3147             f.createNewFile();
3148             OutputStream out = new BufferedOutputStream(new FileOutputStream(f));
3149             while ((c=in.read()) != -1) out.write(c);
3150             in.close();
3151             out.close();
3152         } catch (IOException e) {
3153             throw new RuntimeException("Error when writing to file", e);
3154         }
3155 
3156     }
3157 
3158     /**
3159      * Download the current page (or file) and compare it with the given file.
3160      *
3161      * @param expected Expected file URL.
3162      */
3163     public void assertDownloadedFileEquals(URL expected) {
3164         try {
3165             File tmp = File.createTempFile("jwebunit", null);
3166             tmp.deleteOnExit();
3167             saveAs(tmp);
3168             assertTrue("Files are not binary equals.", areFilesEqual(
3169                     expected, tmp.toURI().toURL()));
3170         } catch (IOException e) {
3171             e.printStackTrace();
3172             fail(e.toString());
3173         }
3174     }
3175 
3176     // Debug methods
3177 
3178     /**
3179      * Dump html of current response to System.out - for debugging purposes.
3180      *
3181      * @param stream
3182      * @deprecated Use {@link WebTester#getPageSource()}
3183      */
3184     public void dumpHtml() {
3185         dumpHtml(System.out);
3186     }
3187 
3188     /**
3189      * Dump html of current response to a specified stream - for debugging purposes.
3190      *
3191      * @param stream
3192      * @deprecated Use {@link WebTester#getPageSource()}
3193      */
3194     public void dumpHtml(PrintStream stream) {
3195         stream.println(getTestingEngine().getPageSource());
3196     }
3197 
3198     /**
3199      * Dump the table as the 2D array that is used for assertions - for debugging purposes.
3200      *
3201      * @param tableNameOrId
3202      * @param stream
3203      */
3204     public void dumpTable(String tableNameOrId) {
3205         dumpTable(tableNameOrId, System.out);
3206     }
3207 
3208     /**
3209      * Dump the table as the 2D array that is used for assertions - for debugging purposes.
3210      *
3211      * @param tableNameOrId
3212      * @param table
3213      * @param stream
3214      */
3215     public void dumpTable(String tableNameOrId, PrintStream stream) {
3216         // String[][] table = getDialogInternal().getTable(tableNameOrId).getStrings();
3217         // //TODO Print correctly cells with colspan
3218         // stream.print("\n" + tableNameOrId + ":");
3219         // for (int i = 0; i < table.length; i++) {
3220         // String[] cell = table[i];
3221         // stream.print("\n\t");
3222         // for (int j = 0; j < cell.length; j++) {
3223         // stream.print("[" + cell[j] + "]");
3224         // }
3225         // }
3226 
3227     }
3228 
3229     // Settings
3230 
3231     /**
3232      * Enable or disable Javascript support
3233      */
3234     public void setScriptingEnabled(boolean value) {
3235         getTestingEngine().setScriptingEnabled(value);
3236     }
3237 
3238     /**
3239      * Set the Testing Engine that you want to use for the tests based on the Testing Engine Key.
3240      *
3241      * @see TestingEngineRegistry
3242      * @param testingEngineKey The testingEngineKey to set.
3243      */
3244     public void setTestingEngineKey(String testingEngineKey) {
3245         this.testingEngineKey = testingEngineKey;
3246         testingEngine = null;
3247     }
3248 
3249     /**
3250      * Gets the Testing Engine Key that is used to find the proper testing engine class (HtmlUnitDialog /
3251      * SeleniumDialog) for the tests.
3252      *
3253      * @return Returns the testingEngineKey.
3254      */
3255     public String getTestingEngineKey() {
3256         if (testingEngineKey == null) {
3257             // use first available testing engine
3258             String key = TestingEngineRegistry.getFirstAvailable();
3259             if (key != null) {
3260                 setTestingEngineKey(key);
3261             } else {
3262                 throw new RuntimeException(
3263                         "TestingEngineRegistry contains no testing engine. Check you put at least one plugin in the classpath.");
3264             }
3265         }
3266         return testingEngineKey;
3267     }
3268 
3269     private RE getRE(String regexp) {
3270         RE re = null;
3271         try {
3272             re = new RE(regexp, RE.MATCH_SINGLELINE);
3273         } catch (RESyntaxException e) {
3274             fail(e.toString());
3275         }
3276         return re;
3277     }
3278 
3279     /**
3280      * Return a string array of select box option labels. <br/>
3281      *
3282      * Example: <br/>
3283      *
3284      * <pre>
3285      *  &lt;FORM action=&quot;http://my_host/doit&quot; method=&quot;post&quot;&gt;
3286      *    &lt;P&gt;
3287      *      &lt;SELECT multiple size=&quot;4&quot; name=&quot;component-select&quot;&gt;
3288      *        &lt;OPTION selected value=&quot;Component_1_a&quot;&gt;Component_1&lt;/OPTION&gt;
3289      *        &lt;OPTION selected value=&quot;Component_1_b&quot;&gt;Component_2&lt;/OPTION&gt;
3290      *        &lt;OPTION&gt;Component_3&lt;/OPTION&gt;
3291      *        &lt;OPTION&gt;Component_4&lt;/OPTION&gt;
3292      *        &lt;OPTION&gt;Component_5&lt;/OPTION&gt;
3293      *      &lt;/SELECT&gt;
3294      *      &lt;INPUT type=&quot;submit&quot; value=&quot;Send&quot;&gt;&lt;INPUT type=&quot;reset&quot;&gt;
3295      *    &lt;/P&gt;
3296      *  &lt;/FORM&gt;
3297      * </pre>
3298      *
3299      * Should return [Component_1, Component_2, Component_3, Component_4, Component_5]
3300      *
3301      * @param selectName name of the select box.
3302      * @return Array of options labels.
3303      */
3304     private String[] getOptionsFor(String selectName) {
3305         String[] values = getTestingEngine().getSelectOptionValues(selectName);
3306         String[] result = new String[values.length];
3307         for (int i = 0; i < values.length; i++) {
3308             result[i] = getTestingEngine().getSelectOptionLabelForValue(
3309                     selectName, values[i]);
3310         }
3311         return result;
3312     }
3313 
3314     /**
3315      * Return a string array of select box option labels.
3316      *
3317      * @param selectName name of the select box.
3318      * @param index the 0-based index of the select element when multiple
3319      * select elements are expected.
3320      * @return Array of options labels.
3321      */
3322     private String[] getOptionsFor(String selectName, int index) {
3323         String[] values = getTestingEngine().getSelectOptionValues(selectName, index);
3324         String[] result = new String[values.length];
3325         for (int i = 0; i < values.length; i++) {
3326             result[i] = getTestingEngine().getSelectOptionLabelForValue(
3327                     selectName, index, values[i]);
3328         }
3329         return result;
3330     }
3331 
3332 
3333 
3334     /**
3335      * Select options by given labels in a select box.
3336      *
3337      * @param selectName name of the select
3338      * @param labels labels of options to be selected
3339      */
3340     private void selectOptionsByLabel(String selectName, String[] labels) {
3341         String[] values = new String[labels.length];
3342         for (int i = 0; i < values.length; i++) {
3343             values[i] = getTestingEngine().getSelectOptionValueForLabel(
3344                     selectName, labels[i]);
3345         }
3346         getTestingEngine().selectOptions(selectName, values);
3347     }
3348 
3349     /**
3350      * Select options by given labels in the Nth select box.
3351      *
3352      * @param selectName name of the select
3353      * @param index the 0-based index of the select element when multiple
3354      * select elements are expected.
3355      * @param labels labels of options to be selected
3356      */
3357     private void selectOptionsByLabel(String selectName, int index, String[] labels) {
3358         String[] values = new String[labels.length];
3359         for (int i = 0; i < values.length; i++) {
3360             values[i] = getTestingEngine().getSelectOptionValueForLabel(
3361                     selectName, index, labels[i]);
3362         }
3363         getTestingEngine().selectOptions(selectName, index, values);
3364     }
3365 
3366 
3367     private void assertArraysEqual(String[] exptected, String[] returned) {
3368         assertEquals("Arrays not same length", exptected.length,
3369                 returned.length);
3370         for (int i = 0; i < returned.length; i++) {
3371             assertEquals("Elements " + i + "not equal", exptected[i],
3372                     returned[i]);
3373         }
3374     }
3375 
3376     /**
3377      * Set the value of a form input element.
3378      *
3379      * @param formElementName name of form element.
3380      * @param value
3381      * @see #setTextField(String, String)
3382      * @deprecated use {@link #setTextField(String, String)} or other methods
3383      */
3384     public void setFormElement(String formElementName, String value) {
3385         assertFormElementPresent(formElementName);
3386         getTestingEngine().setTextField(formElementName, value);
3387     }
3388 
3389     /**
3390      * Tell that the given alert box is expected.
3391      *
3392      * @param message Message in the alert.
3393      */
3394     public void setExpectedJavaScriptAlert(String message) {
3395         try {
3396             getTestingEngine().setExpectedJavaScriptAlert(
3397                     new JavascriptAlert[] { new JavascriptAlert(message) });
3398         } catch (ExpectedJavascriptAlertException e) {
3399             fail("You previously tell that alert with message ["
3400                     + e.getAlertMessage()
3401                     + "] was expected, but nothing appeared.");
3402         }
3403     }
3404 
3405     /**
3406      * Tell that the given alert boxes are expected in the given order.
3407      *
3408      * @param messages Messages in the alerts.
3409      */
3410     public void setExpectedJavaScriptAlert(String[] messages) {
3411         JavascriptAlert[] alerts = new JavascriptAlert[messages.length];
3412         for (int i = 0; i < messages.length; i++) {
3413             alerts[i] = new JavascriptAlert(messages[i]);
3414         }
3415         try {
3416             getTestingEngine().setExpectedJavaScriptAlert(alerts);
3417         } catch (ExpectedJavascriptAlertException e) {
3418             fail("You previously tell that alert with message ["
3419                     + e.getAlertMessage()
3420                     + "] was expected, but nothing appeared.");
3421         }
3422     }
3423 
3424     /**
3425      * Tell that the given confirm boxe is expected.
3426      *
3427      * @param message Message in the confirm.
3428      * @param action Whether we should click on "OK" (true) or "Cancel" (false)
3429      */
3430     public void setExpectedJavaScriptConfirm(String message, boolean action) {
3431         try {
3432             getTestingEngine().setExpectedJavaScriptConfirm(
3433                     new JavascriptConfirm[] { new JavascriptConfirm(message,
3434                             action) });
3435         } catch (ExpectedJavascriptConfirmException e) {
3436             fail("You previously tell that confirm with message ["
3437                     + e.getConfirmMessage()
3438                     + "] was expected, but nothing appeared.");
3439         }
3440     }
3441 
3442     /**
3443      * Tell that the given confirm boxes are expected in the given order.
3444      *
3445      * @param messages Messages in the confirms.
3446      * @param actions Whether we should click on "OK" (true) or "Cancel" (false)
3447      */
3448     public void setExpectedJavaScriptConfirm(String[] messages,
3449             boolean[] actions) {
3450         assertEquals(
3451                 "You should give the same number of messages and actions",
3452                 messages.length, actions.length);
3453         JavascriptConfirm[] confirms = new JavascriptConfirm[messages.length];
3454         for (int i = 0; i < messages.length; i++) {
3455             confirms[i] = new JavascriptConfirm(messages[i], actions[i]);
3456         }
3457         try {
3458             getTestingEngine().setExpectedJavaScriptConfirm(confirms);
3459         } catch (ExpectedJavascriptConfirmException e) {
3460             fail("You previously tell that confirm with message ["
3461                     + e.getConfirmMessage()
3462                     + "] was expected, but nothing appeared.");
3463         }
3464     }
3465 
3466     /**
3467      * Tell that the given prompt boxe is expected.
3468      *
3469      * @param message Message in the prompt.
3470      * @param input What we should put in the prompt (null if user press Cancel)
3471      */
3472     public void setExpectedJavaScriptPrompt(String message, String input) {
3473         try {
3474             getTestingEngine().setExpectedJavaScriptPrompt(
3475                     new JavascriptPrompt[] { new JavascriptPrompt(message,
3476                             input) });
3477         } catch (ExpectedJavascriptPromptException e) {
3478             fail("You previously tell that prompt with message ["
3479                     + e.getPromptMessage()
3480                     + "] was expected, but nothing appeared.");
3481         }
3482     }
3483 
3484     /**
3485      * Tell that the given prompt boxes are expected in the given order.
3486      *
3487      * @param messages Messages in the prompts.
3488      * @param inputs What we should put in the prompt (null if user press Cancel)
3489      */
3490     public void setExpectedJavaScriptPrompt(String[] messages, String[] inputs) {
3491         assertEquals(
3492                 "You should give the same number of messages and inputs",
3493                 messages.length, inputs.length);
3494         JavascriptPrompt[] prompts = new JavascriptPrompt[messages.length];
3495         for (int i = 0; i < messages.length; i++) {
3496             prompts[i] = new JavascriptPrompt(messages[i], inputs[i]);
3497         }
3498         try {
3499             getTestingEngine().setExpectedJavaScriptPrompt(prompts);
3500         } catch (ExpectedJavascriptPromptException e) {
3501             fail("You previously tell that prompt with message ["
3502                     + e.getPromptMessage()
3503                     + "] was expected, but nothing appeared.");
3504         }
3505     }
3506 
3507     /**
3508      * Assert there is at least one image in the page with given src and (optional) alt attributes.
3509      * @param imageSrc Value of image src attribute.
3510      * @param imageAlt Value of image alt attribute. Ignored when null.
3511      */
3512     public void assertImagePresent(String imageSrc, String imageAlt) {
3513         String xpath = "//img[@src=\"" + imageSrc + "\"";
3514         if (imageAlt!= null) {
3515             xpath += " and @alt=\"" + imageAlt + "\"";
3516         }
3517         xpath += "]";
3518         assertElementPresentByXPath(xpath);
3519     }
3520 
3521     /**
3522      * Assert there is at least one image in the page with given partial src and (optional) partial alt attributes.
3523      * @param partialImageSrc
3524      * @param partialImageAlt
3525      */
3526     public void assertImagePresentPartial(String partialImageSrc, String partialImageAlt) {
3527         String xpath = "//img[contains(@src, \"" + partialImageSrc + "\")";
3528         if (partialImageAlt!= null) {
3529             xpath += " and contains(@alt, \"" + partialImageAlt + "\")";
3530         }
3531         xpath += "]";
3532         assertElementPresentByXPath(xpath);
3533     }
3534 
3535     /**
3536      * @see #assertImageValidAndStore(String, String, java.io.File)
3537      */
3538     public void assertImageValid(String imageSrc, String imageAlt) {
3539         validateImage(imageSrc, imageAlt, null);
3540     }
3541 
3542     /**
3543      * Asserts that the image with the given src and alt attribute values exist in the page and is an actual reachable
3544      * image, then saves it as png with the given file name.
3545      *
3546      * @param imageSrc as it appears in the html page, i.e. relative to the current page.
3547      */
3548     public void assertImageValidAndStore(String imageSrc, String imageAlt,
3549             File out) {
3550         validateImage(imageSrc, imageAlt, out);
3551     }
3552 
3553     /**
3554      * @see #assertImageValidAndStore(String, String, java.io.File)
3555      */
3556     public Image getImage(String imageSrc, String imageAlt) {
3557         return validateImage(imageSrc, imageAlt, null);
3558     }
3559 
3560     /**
3561      * Set the timeout for the request. A timeout of 0 means
3562      * an infinite timeout.
3563      *
3564      * @param milli the milliseconds in which to timeout, or 0 for infinite
3565      * wait (the default).
3566      */
3567     public void setTimeout(int milli) {
3568       getTestingEngine().setTimeout(milli);
3569     }
3570 
3571     private Image validateImage(String imageSrc, String imageAlt, File out) {
3572         assertImagePresent(imageSrc, imageAlt);
3573         URL imageUrl = null;
3574         try {
3575             imageUrl = createUrlFixed(imageSrc, getTestingEngine().getPageURL());
3576         } catch (MalformedURLException e1) {
3577             fail(e1.getLocalizedMessage());
3578         }
3579         try {
3580             final InputStream imgStream = getTestingEngine().getInputStream(imageUrl);
3581             final BufferedImage img = ImageIO.read(imgStream);
3582             if (img == null) {
3583                 fail("Could not load image from " + imageUrl);
3584             }
3585             if (out != null) {
3586                 ImageIO.write(img, "png", out);
3587             }
3588             return img;
3589         } catch (IOException e) {
3590             fail("Could not load or save image from " + imageUrl);
3591         } catch (TestingEngineResponseException e) {
3592             fail("The server returns the code " + e.getHttpStatusCode());
3593         }
3594         throw new IllegalStateException();
3595     }
3596 
3597     protected boolean areFilesEqual(URL f1, URL f2) throws IOException {
3598         // read and compare bytes pair-wise
3599         InputStream i1 = f1.openStream();
3600         InputStream i2 = f2.openStream();
3601         int b1, b2;
3602         do {
3603             b1 = i1.read();
3604             b2 = i2.read();
3605         } while (b1 == b2 && b1 != -1 && b2 != -1);
3606         i1.close();
3607         i2.close();
3608         // true only if end of file is reached for both
3609         return (b1 == -1) && (b2 == -1);
3610     }
3611 
3612 }