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