001 // Copyright 2009, 2010 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.test;
016
017 import java.io.File;
018 import java.lang.reflect.Method;
019
020 import org.openqa.selenium.server.RemoteControlConfiguration;
021 import org.openqa.selenium.server.SeleniumServer;
022 import org.testng.Assert;
023 import org.testng.ITestContext;
024 import org.testng.annotations.AfterClass;
025 import org.testng.annotations.AfterMethod;
026 import org.testng.annotations.AfterTest;
027 import org.testng.annotations.BeforeClass;
028 import org.testng.annotations.BeforeMethod;
029 import org.testng.annotations.BeforeTest;
030 import org.testng.xml.XmlTest;
031
032 import com.thoughtworks.selenium.CommandProcessor;
033 import com.thoughtworks.selenium.DefaultSelenium;
034 import com.thoughtworks.selenium.HttpCommandProcessor;
035 import com.thoughtworks.selenium.Selenium;
036
037 /**
038 * Base class for creating Selenium-based integration test cases. This class implements all the
039 * methods of {@link Selenium} and delegates to an instance (setup once per test by
040 * {@link #testStartup(org.testng.ITestContext, org.testng.xml.XmlTest)}.
041 *
042 * @since 5.2.0
043 */
044 public abstract class SeleniumTestCase extends Assert implements Selenium
045 {
046 /**
047 * 15 seconds
048 */
049 public static final String PAGE_LOAD_TIMEOUT = "15000";
050
051 public static final String TOMCAT_6 = "tomcat6";
052
053 public static final String JETTY_7 = "jetty7";
054
055 /**
056 * An XPath expression for locating a submit element (very commonly used
057 * with {@link #clickAndWait(String)}.
058 *
059 * @since 5.3
060 */
061 public static final String SUBMIT = "//input[@type='submit']";
062
063 /**
064 * The underlying {@link Selenium} instance that all the methods of this class delegate to;
065 * this can be useful when attempting to use SeleniumTestCase with a newer version of Selenium which
066 * has added some methods to the interface. This field will not be set until the test case instance
067 * has gone through its full initialization.
068 *
069 * @since 5.3
070 */
071 protected Selenium selenium;
072
073 private String baseURL;
074
075 private ErrorReporter errorReporter;
076
077 private ITestContext testContext;
078
079 /**
080 * Starts up the servers for the entire test (i.e., for multiple TestCases). By placing <parameter> elements
081 * inside the appropriate <test> (of your testng.xml configuration
082 * file), you can change the configuration or behavior of the servers. It is common to have two
083 * or more identical tests that differ only in terms of the <code>tapestry.browser-start-command</code> parameter,
084 * to run tests against multiple browsers.
085 * <table>
086 * <tr>
087 * <th>Parameter</th>
088 * <th>Name</th>
089 * <th>Default</th>
090 * <th>Description</th>
091 * </tr>
092 * <tr>
093 * <td>container</td>
094 * <td>tapestry.servlet-container</td>
095 * <td>JETTY_7</td>
096 * <td>The Servlet container to use for the tests. Currently {@link #JETTY_7} or {@link #TOMCAT_6}</td>
097 * </tr>
098 * <tr>
099 * <td>webAppFolder</td>
100 * <td>tapestry.web-app-folder</td>
101 * <td>src/main/webapp</td>
102 * <td>Location of web application context</td>
103 * </tr>
104 * <tr>
105 * <td>contextPath</td>
106 * <td>tapestry.context-path</td>
107 * <td><em>empty string</em></td>
108 * <td>Context path (defaults to root). As elsewhere, the context path should be blank, or start with a slash (but
109 * not end with one).</td>
110 * </tr>
111 * <tr>
112 * <td>port</td>
113 * <td>tapestry.port</td>
114 * <td>9090</td>
115 * <td>Port number for web server to listen to</td>
116 * </tr>
117 * <tr>
118 * <td>sslPort</td>
119 * <td>tapestry.ssl-port</td>
120 * <td>8443</td>
121 * <td>Port number for web server to listen to for secure requests</td>
122 * </tr>
123 * <tr>
124 * <td>browserStartCommand</td>
125 * <td>tapestry.browser-start-command</td>
126 * <td>*firefox</td>
127 * <td>Command string used to launch the browser, as defined by Selenium</td>
128 * </tr>
129 * </table>
130 * <p>
131 * Tests in the <em>beforeStartup</em> group will be run before the start of Selenium. This can be used to
132 * programmatically override the above parameter values. For an example see
133 * {@link org.apache.tapestry5.integration.reload.ReloadTests#beforeStartup}.
134 * <p>
135 * This method will be invoked in <em>each</em> subclass, but is set up to only startup the servers once (it checks
136 * the {@link ITestContext} to see if the necessary keys are already present).
137 *
138 * @param testContext
139 * Used to share objects between the launcher and the test suites
140 * @throws Exception
141 */
142 @BeforeTest(dependsOnGroups =
143 { "beforeStartup" })
144 public void testStartup(final ITestContext testContext, XmlTest xmlTest) throws Exception
145 {
146 // This is not actually necessary, because TestNG will only invoke this method once
147 // even when multiple test cases within the test extend from SeleniumTestCase. TestNG
148 // just invokes it on the "first" TestCase instance it has test methods for.
149
150 if (testContext.getAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE) != null)
151 return;
152
153 // If a parameter is overridden in another test method, TestNG won't pass the
154 // updated value via a parameter, but still passes the original (coming from testng.xml or the default).
155 // Seems like a TestNG bug.
156
157 // Map<String, String> testParameters = xmlTest.getParameters();
158
159 String webAppFolder = getParameter(xmlTest, TapestryTestConstants.WEB_APP_FOLDER_PARAMETER, "src/main/webapp");
160 String container = getParameter(xmlTest, TapestryTestConstants.SERVLET_CONTAINER_PARAMETER, JETTY_7);
161 String contextPath = getParameter(xmlTest, TapestryTestConstants.CONTEXT_PATH_PARAMETER, "");
162 int port = Integer.parseInt(getParameter(xmlTest, TapestryTestConstants.PORT_PARAMETER, "9090"));
163 int sslPort = Integer.parseInt(getParameter(xmlTest, TapestryTestConstants.SSL_PORT_PARAMETER, "8443"));
164 String browserStartCommand = getParameter(xmlTest, TapestryTestConstants.BROWSER_START_COMMAND_PARAMETER,
165 "*firefox");
166
167 final Runnable stopWebServer = launchWebServer(container, webAppFolder, contextPath, port, sslPort);
168
169 final SeleniumServer seleniumServer = new SeleniumServer();
170
171 File ffProfileTemplate = new File(TapestryTestConstants.MODULE_BASE_DIR, "src/test/conf/ff_profile_template");
172
173 if (ffProfileTemplate.isDirectory())
174 seleniumServer.getConfiguration().setFirefoxProfileTemplate(ffProfileTemplate);
175
176 seleniumServer.start();
177
178 String baseURL = String.format("http://localhost:%d%s/", port, contextPath);
179
180 CommandProcessor httpCommandProcessor = new HttpCommandProcessor("localhost",
181 RemoteControlConfiguration.DEFAULT_PORT, browserStartCommand, baseURL);
182
183 final ErrorReporterImpl errorReporter = new ErrorReporterImpl(httpCommandProcessor, testContext);
184
185 ErrorReportingCommandProcessor commandProcessor = new ErrorReportingCommandProcessor(httpCommandProcessor,
186 errorReporter);
187
188 final Selenium selenium = new DefaultSelenium(commandProcessor);
189
190 selenium.start();
191
192 testContext.setAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE, baseURL);
193 testContext.setAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE, selenium);
194 testContext.setAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE, errorReporter);
195 testContext.setAttribute(TapestryTestConstants.COMMAND_PROCESSOR_ATTRIBUTE, commandProcessor);
196
197 testContext.setAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE, new Runnable()
198 {
199 public void run()
200 {
201 try
202 {
203 selenium.stop();
204 seleniumServer.stop();
205 stopWebServer.run();
206
207 // Output, at the end of the Test, any html capture or screen shots (this makes it much easier
208 // to locate them at the end of the run; there's such a variance on where they end up based
209 // on whether the tests are running from inside an IDE or via one of the command line
210 // builds.
211
212 errorReporter.writeOutputPaths();
213 }
214 finally
215 {
216 testContext.removeAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE);
217 testContext.removeAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE);
218 testContext.removeAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE);
219 testContext.removeAttribute(TapestryTestConstants.COMMAND_PROCESSOR_ATTRIBUTE);
220 testContext.removeAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE);
221 }
222 }
223 });
224 }
225
226 private final String getParameter(XmlTest xmlTest, String key, String defaultValue)
227 {
228 String value = xmlTest.getParameter(key);
229
230 return value != null ? value : defaultValue;
231 }
232
233 /**
234 * Like {@link #testStartup(org.testng.ITestContext, org.testng.xml.XmlTest)} , this may
235 * be called multiple times against multiple instances, but only does work the first time.
236 */
237 @AfterTest
238 public void testShutdown(ITestContext context)
239 {
240 // Likewise, this method should only be invoked once.
241 Runnable r = (Runnable) context.getAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE);
242
243 // This test is still useful, however, because testStartup() may not have completed properly,
244 // and the runnable is the last thing it puts into the test context.
245
246 if (r != null)
247 r.run();
248 }
249
250 /**
251 * Invoked from {@link #testStartup(org.testng.ITestContext, org.testng.xml.XmlTest)} to launch the web
252 * server to be
253 * tested. The return value is a Runnable that will shut down the launched server at the end of
254 * the test (it is coded this way so that the default Jetty web server can be more easily
255 * replaced).
256 *
257 * @param webAppFolder
258 * path to the web application context
259 * @param contextPath
260 * the path the context is mapped to, usually the empty string
261 * @param port
262 * the port number the server should handle
263 * @param sslPort
264 * the port number on which the server should handle secure requests
265 * @return Runnable used to shut down the server
266 * @throws Exception
267 */
268 protected Runnable launchWebServer(String webAppFolder, String contextPath, int port, int sslPort) throws Exception
269 {
270 return launchWebServer(TOMCAT_6, webAppFolder, contextPath, port, sslPort);
271 }
272
273 protected Runnable launchWebServer(String container, String webAppFolder, String contextPath, int port, int sslPort)
274 throws Exception
275 {
276 final ServletContainerRunner runner;
277 if (TOMCAT_6.equals(container))
278 runner = new Tomcat6Runner(webAppFolder, contextPath, port, sslPort);
279 else if (JETTY_7.equals(container))
280 runner = new Jetty7Runner(webAppFolder, contextPath, port, sslPort);
281 else
282 throw new RuntimeException("Unknown servlet container: " + container);
283
284 return new Runnable()
285 {
286 public void run()
287 {
288 runner.stop();
289 }
290 };
291 }
292
293 @BeforeClass
294 public void setup(ITestContext context)
295 {
296 this.testContext = context;
297
298 selenium = (Selenium) context.getAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE);
299 baseURL = (String) context.getAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE);
300 errorReporter = (ErrorReporter) context.getAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE);
301 }
302
303 @AfterClass
304 public void cleanup()
305 {
306 selenium = null;
307 baseURL = null;
308 errorReporter = null;
309 testContext = null;
310 }
311
312 /**
313 * Delegates to {@link ErrorReporter#writeErrorReport()} to capture the current page markup in a
314 * file for later analysis.
315 */
316 protected void writeErrorReport()
317 {
318 errorReporter.writeErrorReport();
319 }
320
321 /**
322 * Returns the base URL for the application. This is of the typically <code>http://localhost:9999/</code> (i.e., it
323 * includes a trailing slash).
324 * <p>
325 * Generally, you should use {@link #openLinks(String...)} to start from your application's home page.
326 */
327 public String getBaseURL()
328 {
329 return baseURL;
330 }
331
332 @BeforeMethod
333 public void indicateTestMethodName(Method testMethod)
334 {
335 testContext.setAttribute(TapestryTestConstants.CURRENT_TEST_METHOD_ATTRIBUTE, testMethod);
336
337 String className = testMethod.getDeclaringClass().getSimpleName();
338 String testName = testMethod.getName().replace("_", " ");
339
340 selenium.setContext(className + ": " + testName);
341 }
342
343 @AfterMethod
344 public void cleanupTestMethod()
345 {
346 testContext.setAttribute(TapestryTestConstants.CURRENT_TEST_METHOD_ATTRIBUTE, null);
347 }
348
349 // ---------------------------------------------------------------------
350 // Start of delegate methods
351 //
352 // When upgrading to a new version of Selenium, it is probably easiest
353 // to delete all these methods and use the Generate Delegate Methods
354 // refactoring.
355 // ---------------------------------------------------------------------
356
357 public void addCustomRequestHeader(String key, String value)
358 {
359 selenium.addCustomRequestHeader(key, value);
360 }
361
362 public void addLocationStrategy(String strategyName, String functionDefinition)
363 {
364 selenium.addLocationStrategy(strategyName, functionDefinition);
365 }
366
367 public void addScript(String scriptContent, String scriptTagId)
368 {
369 selenium.addScript(scriptContent, scriptTagId);
370 }
371
372 public void addSelection(String locator, String optionLocator)
373 {
374 selenium.addSelection(locator, optionLocator);
375 }
376
377 public void allowNativeXpath(String allow)
378 {
379 selenium.allowNativeXpath(allow);
380 }
381
382 public void altKeyDown()
383 {
384 selenium.altKeyDown();
385 }
386
387 public void altKeyUp()
388 {
389 selenium.altKeyUp();
390 }
391
392 public void answerOnNextPrompt(String answer)
393 {
394 selenium.answerOnNextPrompt(answer);
395 }
396
397 public void assignId(String locator, String identifier)
398 {
399 selenium.assignId(locator, identifier);
400 }
401
402 public void attachFile(String fieldLocator, String fileLocator)
403 {
404 selenium.attachFile(fieldLocator, fileLocator);
405 }
406
407 public void captureEntirePageScreenshot(String filename, String kwargs)
408 {
409 selenium.captureEntirePageScreenshot(filename, kwargs);
410 }
411
412 public String captureEntirePageScreenshotToString(String kwargs)
413 {
414 return selenium.captureEntirePageScreenshotToString(kwargs);
415 }
416
417 public String captureNetworkTraffic(String type)
418 {
419 return selenium.captureNetworkTraffic(type);
420 }
421
422 public void captureScreenshot(String filename)
423 {
424 selenium.captureScreenshot(filename);
425 }
426
427 public String captureScreenshotToString()
428 {
429 return selenium.captureScreenshotToString();
430 }
431
432 public void check(String locator)
433 {
434 selenium.check(locator);
435 }
436
437 public void chooseCancelOnNextConfirmation()
438 {
439 selenium.chooseCancelOnNextConfirmation();
440 }
441
442 public void chooseOkOnNextConfirmation()
443 {
444 selenium.chooseOkOnNextConfirmation();
445 }
446
447 public void click(String locator)
448 {
449 selenium.click(locator);
450 }
451
452 public void clickAt(String locator, String coordString)
453 {
454 selenium.clickAt(locator, coordString);
455 }
456
457 public void close()
458 {
459 selenium.close();
460 }
461
462 public void contextMenu(String locator)
463 {
464 selenium.contextMenu(locator);
465 }
466
467 public void contextMenuAt(String locator, String coordString)
468 {
469 selenium.contextMenuAt(locator, coordString);
470 }
471
472 public void controlKeyDown()
473 {
474 selenium.controlKeyDown();
475 }
476
477 public void controlKeyUp()
478 {
479 selenium.controlKeyUp();
480 }
481
482 public void createCookie(String nameValuePair, String optionsString)
483 {
484 selenium.createCookie(nameValuePair, optionsString);
485 }
486
487 public void deleteAllVisibleCookies()
488 {
489 selenium.deleteAllVisibleCookies();
490 }
491
492 public void deleteCookie(String name, String optionsString)
493 {
494 selenium.deleteCookie(name, optionsString);
495 }
496
497 public void deselectPopUp()
498 {
499 selenium.deselectPopUp();
500 }
501
502 public void doubleClick(String locator)
503 {
504 selenium.doubleClick(locator);
505 }
506
507 public void doubleClickAt(String locator, String coordString)
508 {
509 selenium.doubleClickAt(locator, coordString);
510 }
511
512 public void dragAndDrop(String locator, String movementsString)
513 {
514 selenium.dragAndDrop(locator, movementsString);
515 }
516
517 public void dragAndDropToObject(String locatorOfObjectToBeDragged, String locatorOfDragDestinationObject)
518 {
519 selenium.dragAndDropToObject(locatorOfObjectToBeDragged, locatorOfDragDestinationObject);
520 }
521
522 public void dragdrop(String locator, String movementsString)
523 {
524 selenium.dragdrop(locator, movementsString);
525 }
526
527 public void fireEvent(String locator, String eventName)
528 {
529 selenium.fireEvent(locator, eventName);
530 }
531
532 public void focus(String locator)
533 {
534 selenium.focus(locator);
535 }
536
537 public String getAlert()
538 {
539 return selenium.getAlert();
540 }
541
542 public String[] getAllButtons()
543 {
544 return selenium.getAllButtons();
545 }
546
547 public String[] getAllFields()
548 {
549 return selenium.getAllFields();
550 }
551
552 public String[] getAllLinks()
553 {
554 return selenium.getAllLinks();
555 }
556
557 public String[] getAllWindowIds()
558 {
559 return selenium.getAllWindowIds();
560 }
561
562 public String[] getAllWindowNames()
563 {
564 return selenium.getAllWindowNames();
565 }
566
567 public String[] getAllWindowTitles()
568 {
569 return selenium.getAllWindowTitles();
570 }
571
572 public String getAttribute(String attributeLocator)
573 {
574 return selenium.getAttribute(attributeLocator);
575 }
576
577 public String[] getAttributeFromAllWindows(String attributeName)
578 {
579 return selenium.getAttributeFromAllWindows(attributeName);
580 }
581
582 public String getBodyText()
583 {
584 return selenium.getBodyText();
585 }
586
587 public String getConfirmation()
588 {
589 return selenium.getConfirmation();
590 }
591
592 public String getCookie()
593 {
594 return selenium.getCookie();
595 }
596
597 public String getCookieByName(String name)
598 {
599 return selenium.getCookieByName(name);
600 }
601
602 public Number getCursorPosition(String locator)
603 {
604 return selenium.getCursorPosition(locator);
605 }
606
607 public Number getElementHeight(String locator)
608 {
609 return selenium.getElementHeight(locator);
610 }
611
612 public Number getElementIndex(String locator)
613 {
614 return selenium.getElementIndex(locator);
615 }
616
617 public Number getElementPositionLeft(String locator)
618 {
619 return selenium.getElementPositionLeft(locator);
620 }
621
622 public Number getElementPositionTop(String locator)
623 {
624 return selenium.getElementPositionTop(locator);
625 }
626
627 public Number getElementWidth(String locator)
628 {
629 return selenium.getElementWidth(locator);
630 }
631
632 public String getEval(String script)
633 {
634 return selenium.getEval(script);
635 }
636
637 public String getExpression(String expression)
638 {
639 return selenium.getExpression(expression);
640 }
641
642 public String getHtmlSource()
643 {
644 return selenium.getHtmlSource();
645 }
646
647 public String getLocation()
648 {
649 return selenium.getLocation();
650 }
651
652 public String getLog()
653 {
654 return selenium.getLog();
655 }
656
657 public Number getMouseSpeed()
658 {
659 return selenium.getMouseSpeed();
660 }
661
662 public String getPrompt()
663 {
664 return selenium.getPrompt();
665 }
666
667 public String getSelectedId(String selectLocator)
668 {
669 return selenium.getSelectedId(selectLocator);
670 }
671
672 public String[] getSelectedIds(String selectLocator)
673 {
674 return selenium.getSelectedIds(selectLocator);
675 }
676
677 public String getSelectedIndex(String selectLocator)
678 {
679 return selenium.getSelectedIndex(selectLocator);
680 }
681
682 public String[] getSelectedIndexes(String selectLocator)
683 {
684 return selenium.getSelectedIndexes(selectLocator);
685 }
686
687 public String getSelectedLabel(String selectLocator)
688 {
689 return selenium.getSelectedLabel(selectLocator);
690 }
691
692 public String[] getSelectedLabels(String selectLocator)
693 {
694 return selenium.getSelectedLabels(selectLocator);
695 }
696
697 public String getSelectedValue(String selectLocator)
698 {
699 return selenium.getSelectedValue(selectLocator);
700 }
701
702 public String[] getSelectedValues(String selectLocator)
703 {
704 return selenium.getSelectedValues(selectLocator);
705 }
706
707 public String[] getSelectOptions(String selectLocator)
708 {
709 return selenium.getSelectOptions(selectLocator);
710 }
711
712 public String getSpeed()
713 {
714 return selenium.getSpeed();
715 }
716
717 public String getTable(String tableCellAddress)
718 {
719 return selenium.getTable(tableCellAddress);
720 }
721
722 public String getText(String locator)
723 {
724 return selenium.getText(locator);
725 }
726
727 public String getTitle()
728 {
729 return selenium.getTitle();
730 }
731
732 public String getValue(String locator)
733 {
734 return selenium.getValue(locator);
735 }
736
737 public boolean getWhetherThisFrameMatchFrameExpression(String currentFrameString, String target)
738 {
739 return selenium.getWhetherThisFrameMatchFrameExpression(currentFrameString, target);
740 }
741
742 public boolean getWhetherThisWindowMatchWindowExpression(String currentWindowString, String target)
743 {
744 return selenium.getWhetherThisWindowMatchWindowExpression(currentWindowString, target);
745 }
746
747 public Number getXpathCount(String xpath)
748 {
749 return selenium.getXpathCount(xpath);
750 }
751
752 public void goBack()
753 {
754 selenium.goBack();
755 }
756
757 public void highlight(String locator)
758 {
759 selenium.highlight(locator);
760 }
761
762 public void ignoreAttributesWithoutValue(String ignore)
763 {
764 selenium.ignoreAttributesWithoutValue(ignore);
765 }
766
767 public boolean isAlertPresent()
768 {
769 return selenium.isAlertPresent();
770 }
771
772 public boolean isChecked(String locator)
773 {
774 return selenium.isChecked(locator);
775 }
776
777 public boolean isConfirmationPresent()
778 {
779 return selenium.isConfirmationPresent();
780 }
781
782 public boolean isCookiePresent(String name)
783 {
784 return selenium.isCookiePresent(name);
785 }
786
787 public boolean isEditable(String locator)
788 {
789 return selenium.isEditable(locator);
790 }
791
792 public boolean isElementPresent(String locator)
793 {
794 return selenium.isElementPresent(locator);
795 }
796
797 public boolean isOrdered(String locator1, String locator2)
798 {
799 return selenium.isOrdered(locator1, locator2);
800 }
801
802 public boolean isPromptPresent()
803 {
804 return selenium.isPromptPresent();
805 }
806
807 public boolean isSomethingSelected(String selectLocator)
808 {
809 return selenium.isSomethingSelected(selectLocator);
810 }
811
812 public boolean isTextPresent(String pattern)
813 {
814 return selenium.isTextPresent(pattern);
815 }
816
817 public boolean isVisible(String locator)
818 {
819 return selenium.isVisible(locator);
820 }
821
822 public void keyDown(String locator, String keySequence)
823 {
824 selenium.keyDown(locator, keySequence);
825 }
826
827 public void keyDownNative(String keycode)
828 {
829 selenium.keyDownNative(keycode);
830 }
831
832 public void keyPress(String locator, String keySequence)
833 {
834 selenium.keyPress(locator, keySequence);
835 }
836
837 public void keyPressNative(String keycode)
838 {
839 selenium.keyPressNative(keycode);
840 }
841
842 public void keyUp(String locator, String keySequence)
843 {
844 selenium.keyUp(locator, keySequence);
845 }
846
847 public void keyUpNative(String keycode)
848 {
849 selenium.keyUpNative(keycode);
850 }
851
852 public void metaKeyDown()
853 {
854 selenium.metaKeyDown();
855 }
856
857 public void metaKeyUp()
858 {
859 selenium.metaKeyUp();
860 }
861
862 public void mouseDown(String locator)
863 {
864 selenium.mouseDown(locator);
865 }
866
867 public void mouseDownAt(String locator, String coordString)
868 {
869 selenium.mouseDownAt(locator, coordString);
870 }
871
872 public void mouseDownRight(String locator)
873 {
874 selenium.mouseDownRight(locator);
875 }
876
877 public void mouseDownRightAt(String locator, String coordString)
878 {
879 selenium.mouseDownRightAt(locator, coordString);
880 }
881
882 public void mouseMove(String locator)
883 {
884 selenium.mouseMove(locator);
885 }
886
887 public void mouseMoveAt(String locator, String coordString)
888 {
889 selenium.mouseMoveAt(locator, coordString);
890 }
891
892 public void mouseOut(String locator)
893 {
894 selenium.mouseOut(locator);
895 }
896
897 public void mouseOver(String locator)
898 {
899 selenium.mouseOver(locator);
900 }
901
902 public void mouseUp(String locator)
903 {
904 selenium.mouseUp(locator);
905 }
906
907 public void mouseUpAt(String locator, String coordString)
908 {
909 selenium.mouseUpAt(locator, coordString);
910 }
911
912 public void mouseUpRight(String locator)
913 {
914 selenium.mouseUpRight(locator);
915 }
916
917 public void mouseUpRightAt(String locator, String coordString)
918 {
919 selenium.mouseUpRightAt(locator, coordString);
920 }
921
922 public void open(String url)
923 {
924 selenium.open(url);
925 }
926
927 public void open(String url, String ignoreResponseCode)
928 {
929 selenium.open(url, ignoreResponseCode);
930 }
931
932 public void openWindow(String url, String windowID)
933 {
934 selenium.openWindow(url, windowID);
935 }
936
937 public void refresh()
938 {
939 selenium.refresh();
940 }
941
942 public void removeAllSelections(String locator)
943 {
944 selenium.removeAllSelections(locator);
945 }
946
947 public void removeScript(String scriptTagId)
948 {
949 selenium.removeScript(scriptTagId);
950 }
951
952 public void removeSelection(String locator, String optionLocator)
953 {
954 selenium.removeSelection(locator, optionLocator);
955 }
956
957 public String retrieveLastRemoteControlLogs()
958 {
959 return selenium.retrieveLastRemoteControlLogs();
960 }
961
962 public void rollup(String rollupName, String kwargs)
963 {
964 selenium.rollup(rollupName, kwargs);
965 }
966
967 public void runScript(String script)
968 {
969 selenium.runScript(script);
970 }
971
972 public void select(String selectLocator, String optionLocator)
973 {
974 selenium.select(selectLocator, optionLocator);
975 }
976
977 public void selectFrame(String locator)
978 {
979 selenium.selectFrame(locator);
980 }
981
982 public void selectPopUp(String windowID)
983 {
984 selenium.selectPopUp(windowID);
985 }
986
987 public void selectWindow(String windowID)
988 {
989 selenium.selectWindow(windowID);
990 }
991
992 public void setBrowserLogLevel(String logLevel)
993 {
994 selenium.setBrowserLogLevel(logLevel);
995 }
996
997 public void setContext(String context)
998 {
999 selenium.setContext(context);
1000 }
1001
1002 public void setCursorPosition(String locator, String position)
1003 {
1004 selenium.setCursorPosition(locator, position);
1005 }
1006
1007 public void setExtensionJs(String extensionJs)
1008 {
1009 selenium.setExtensionJs(extensionJs);
1010 }
1011
1012 public void setMouseSpeed(String pixels)
1013 {
1014 selenium.setMouseSpeed(pixels);
1015 }
1016
1017 public void setSpeed(String value)
1018 {
1019 selenium.setSpeed(value);
1020 }
1021
1022 public void setTimeout(String timeout)
1023 {
1024 selenium.setTimeout(timeout);
1025 }
1026
1027 public void shiftKeyDown()
1028 {
1029 selenium.shiftKeyDown();
1030 }
1031
1032 public void shiftKeyUp()
1033 {
1034 selenium.shiftKeyUp();
1035 }
1036
1037 public void showContextualBanner()
1038 {
1039 selenium.showContextualBanner();
1040 }
1041
1042 public void showContextualBanner(String className, String methodName)
1043 {
1044 selenium.showContextualBanner(className, methodName);
1045 }
1046
1047 public void shutDownSeleniumServer()
1048 {
1049 selenium.shutDownSeleniumServer();
1050 }
1051
1052 public void start()
1053 {
1054 selenium.start();
1055 }
1056
1057 public void start(Object optionsObject)
1058 {
1059 selenium.start(optionsObject);
1060 }
1061
1062 public void start(String optionsString)
1063 {
1064 selenium.start(optionsString);
1065 }
1066
1067 public void stop()
1068 {
1069 selenium.stop();
1070 }
1071
1072 public void submit(String formLocator)
1073 {
1074 selenium.submit(formLocator);
1075 }
1076
1077 public void type(String locator, String value)
1078 {
1079 selenium.type(locator, value);
1080 }
1081
1082 public void typeKeys(String locator, String value)
1083 {
1084 selenium.typeKeys(locator, value);
1085 }
1086
1087 public void uncheck(String locator)
1088 {
1089 selenium.uncheck(locator);
1090 }
1091
1092 public void useXpathLibrary(String libraryName)
1093 {
1094 selenium.useXpathLibrary(libraryName);
1095 }
1096
1097 public void waitForCondition(String script, String timeout)
1098 {
1099 selenium.waitForCondition(script, timeout);
1100 }
1101
1102 public void waitForFrameToLoad(String frameAddress, String timeout)
1103 {
1104 selenium.waitForFrameToLoad(frameAddress, timeout);
1105 }
1106
1107 public void waitForPageToLoad(String timeout)
1108 {
1109 selenium.waitForPageToLoad(timeout);
1110 }
1111
1112 public void waitForPopUp(String windowID, String timeout)
1113 {
1114 selenium.waitForPopUp(windowID, timeout);
1115 }
1116
1117 public void windowFocus()
1118 {
1119 selenium.windowFocus();
1120 }
1121
1122 public void windowMaximize()
1123 {
1124 selenium.windowMaximize();
1125 }
1126
1127 // ---------------------------------------------------------------------
1128 // End of delegate methods
1129 // ---------------------------------------------------------------------
1130
1131 protected final void unreachable()
1132 {
1133 writeErrorReport();
1134
1135 throw new AssertionError("This statement should not be reachable.");
1136 }
1137
1138 /** Open the {@linkplain #getBaseURL()}, and waits for the page to load. */
1139 protected final void openBaseURL()
1140 {
1141 open(baseURL);
1142
1143 waitForPageToLoad();
1144 }
1145
1146 /**
1147 * Asserts the text of an element, identified by the locator.
1148 *
1149 * @param locator
1150 * identifies the element whose text value is to be asserted
1151 * @param expected
1152 * expected value for the element's text
1153 */
1154 protected final void assertText(String locator, String expected)
1155 {
1156 String actual = null;
1157
1158 try
1159 {
1160 actual = getText(locator);
1161 }
1162 catch (RuntimeException ex)
1163 {
1164 System.err.printf("Error accessing %s: %s, in:\n\n%s\n\n", locator, ex.getMessage(), getHtmlSource());
1165
1166 throw ex;
1167 }
1168
1169 if (actual.equals(expected))
1170 return;
1171
1172 writeErrorReport();
1173
1174 throw new AssertionError(String.format("%s was '%s' not '%s'", locator, actual, expected));
1175 }
1176
1177 protected final void assertTextPresent(String... text)
1178 {
1179 for (String item : text)
1180 {
1181 if (isTextPresent(item))
1182 continue;
1183
1184 writeErrorReport();
1185
1186 throw new AssertionError("Page did not contain '" + item + "'.");
1187 }
1188 }
1189
1190 /**
1191 * Assets that each string provided is present somewhere in the current document.
1192 *
1193 * @param expected
1194 * string expected to be present
1195 */
1196 protected final void assertSourcePresent(String... expected)
1197 {
1198 String source = getHtmlSource();
1199
1200 for (String snippet : expected)
1201 {
1202 if (source.contains(snippet))
1203 continue;
1204
1205 writeErrorReport();
1206
1207 throw new AssertionError("Page did not contain source '" + snippet + "'.");
1208 }
1209 }
1210
1211 /**
1212 * Click a link identified by a locator, then wait for the resulting page to load.
1213 * This is not useful for Ajax updates, just normal full-page refreshes.
1214 *
1215 * @param locator
1216 * identifies the link to click
1217 */
1218 protected final void clickAndWait(String locator)
1219 {
1220 click(locator);
1221
1222 waitForPageToLoad();
1223 }
1224
1225 /**
1226 * Waits for the page to load (up to 15 seconds). This is invoked after clicking on an element
1227 * that forces a full page refresh.
1228 */
1229 protected final void waitForPageToLoad()
1230 {
1231 waitForPageToLoad(PAGE_LOAD_TIMEOUT);
1232 }
1233
1234 /**
1235 * Used when the locator identifies an attribute, not an element.
1236 *
1237 * @param locator
1238 * identifies the attribute whose value is to be asserted
1239 * @param expected
1240 * expected value for the attribute
1241 */
1242 protected final void assertAttribute(String locator, String expected)
1243 {
1244 String actual = null;
1245
1246 try
1247 {
1248 actual = getAttribute(locator);
1249 }
1250 catch (RuntimeException ex)
1251 {
1252 System.err.printf("Error accessing %s: %s", locator, ex.getMessage());
1253
1254 writeErrorReport();
1255
1256 throw ex;
1257 }
1258
1259 if (actual.equals(expected))
1260 return;
1261
1262 writeErrorReport();
1263
1264 throw new AssertionError(String.format("%s was '%s' not '%s'", locator, actual, expected));
1265 }
1266
1267 /**
1268 * Assets that the value in the field matches the expectation
1269 *
1270 * @param locator
1271 * identifies the field
1272 * @param expected
1273 * expected value for the field
1274 * @since 5.3
1275 */
1276 protected final void assertFieldValue(String locator, String expected)
1277 {
1278 try
1279 {
1280 assertEquals(getValue(locator), expected);
1281 }
1282 catch (AssertionError ex)
1283 {
1284 writeErrorReport();
1285
1286 throw ex;
1287 }
1288 }
1289
1290 /**
1291 * Opens the base URL, then clicks through a series of links to get to a desired application
1292 * state.
1293 *
1294 * @since 5.3
1295 */
1296 protected final void openLinks(String... linkText)
1297 {
1298 openBaseURL();
1299
1300 for (String text : linkText)
1301 {
1302 clickAndWait("link=" + text);
1303 }
1304 }
1305
1306 /**
1307 * Sleeps for the indicated number of seconds.
1308 *
1309 * @since 5.3
1310 */
1311 protected final void sleep(long millis)
1312 {
1313 try
1314 {
1315 Thread.sleep(millis);
1316 }
1317 catch (InterruptedException ex)
1318 {
1319 // Ignore.
1320 }
1321 }
1322
1323 /**
1324 * Waits, up to the page load limit for an element (identified by a CSS rule) to exist
1325 * (it is not assured that the element will be visible).
1326 *
1327 * @param cssRule
1328 * used to locate the element
1329 * @since 5.3
1330 */
1331 protected void waitForCSSSelectedElementToAppear(String cssRule)
1332 {
1333 String condition = String.format("window.$$(\"%s\").size() > 0", cssRule);
1334
1335 waitForCondition(condition, PAGE_LOAD_TIMEOUT);
1336 }
1337
1338 /**
1339 * Waits for the element with the given client-side id to be present in the DOM (
1340 * does not assure that the element is visible).
1341 *
1342 * @param elementId
1343 * identifies the element
1344 * @since 5.3
1345 */
1346 protected final void waitForElementToAppear(String elementId)
1347 {
1348
1349 String condition = String.format("window.$(\"%s\")", elementId);
1350
1351 waitForCondition(condition, PAGE_LOAD_TIMEOUT);
1352 }
1353
1354 /**
1355 * Waits for the element to be removed from the DOM.
1356 *
1357 * @param elementId
1358 * client-side id of element
1359 * @since 5.3
1360 */
1361 protected final void waitForElementToDisappear(String elementId)
1362 {
1363 String condition = String.format("window.$(\"%s\").hide()", elementId);
1364
1365 waitForCondition(condition, PAGE_LOAD_TIMEOUT);
1366 }
1367
1368 /**
1369 * Waits for the element specified by the selector to become visible
1370 * Note that waitForElementToAppear waits for the element to be present in the dom, visible or not. waitForVisible
1371 * waits for an element that already exists in the dom to become visible.
1372 * @param selector
1373 * element selector
1374 * @since 5.3
1375 */
1376 protected final void waitForVisible(String selector)
1377 {
1378 String condition = String.format("selenium.isVisible(\"%s\")", selector);
1379
1380 waitForCondition(condition, PAGE_LOAD_TIMEOUT);
1381 }
1382
1383 /**
1384 * Waits for the element specified by the selector to become invisible
1385 * Note that waitForElementToDisappear waits for the element to be absent from the dom, visible or not. waitForInvisible
1386 * waits for an existing element to become invisible.
1387 * @param selector
1388 * element selector
1389 * @since 5.3
1390 */
1391 protected final void waitForInvisible(String selector)
1392 {
1393 String condition = String.format("!selenium.isVisible(\"%s\")", selector);
1394
1395 waitForCondition(condition, PAGE_LOAD_TIMEOUT);
1396 }
1397 /**
1398 * Asserts that the current page's title matches the expected value.
1399 *
1400 * @since 5.3
1401 * @param expected
1402 * value for title
1403 */
1404 protected final void assertTitle(String expected)
1405 {
1406 try
1407 {
1408 assertEquals(getTitle(), expected);
1409 }
1410 catch (AssertionError ex)
1411 {
1412 writeErrorReport();
1413
1414 throw ex;
1415 }
1416 }
1417
1418 /**
1419 * Waits until all active XHR requests are completed.
1420 *
1421 * @since 5.3
1422 *
1423 * @param timeout timeout to wait for
1424 */
1425 protected final void waitForAjaxRequestsToComplete(String timeout)
1426 {
1427 waitForCondition("selenium.browserbot.getCurrentWindow().Ajax.activeRequestCount == 0", timeout);
1428 }
1429
1430 public Number getCssCount(String str) {
1431 return selenium.getCssCount(str);
1432 }
1433 }