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 }