You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by ka...@apache.org on 2013/04/14 04:22:41 UTC

git commit: Selenium version used didn't anymore work with the latest FF versions. Selectively merge changes in functional tests from master and hack around just enough to get most of the tests going again

Updated Branches:
  refs/heads/5.3 8292d0583 -> f656ce399


Selenium version used didn't anymore work with the latest FF versions. Selectively merge changes in functional tests from master and hack around just enough to get most of the tests going again


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/f656ce39
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/f656ce39
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/f656ce39

Branch: refs/heads/5.3
Commit: f656ce399e298cb1d97d5c5863ec5bad8d31222a
Parents: 8292d05
Author: kaosko <ka...@apache.org>
Authored: Sun Apr 14 03:13:18 2013 +0100
Committer: kaosko <ka...@apache.org>
Committed: Sun Apr 14 03:13:18 2013 +0100

----------------------------------------------------------------------
 .../TapestryBeanValidationIntegrationTests.java    |  138 +-
 tapestry-test/build.gradle                         |   11 +-
 .../test/AbstractIntegrationTestSuite.java         | 1203 ---------------
 .../org/apache/tapestry5/test/JettyRunner.java     |  167 --
 .../apache/tapestry5/test/SeleniumTestCase.java    |  316 +++--
 .../tapestry5/test/TapestryTestConfiguration.java  |   66 +
 6 files changed, 341 insertions(+), 1560 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/f656ce39/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
----------------------------------------------------------------------
diff --git a/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java b/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
index 72806c3..658077d 100644
--- a/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
+++ b/tapestry-beanvalidator/src/test/java/org/apache/tapestry5/beanvalidator/integration/TapestryBeanValidationIntegrationTests.java
@@ -13,24 +13,21 @@
 // limitations under the License.
 package org.apache.tapestry5.beanvalidator.integration;
 
-import org.apache.tapestry5.test.AbstractIntegrationTestSuite;
+import org.apache.tapestry5.test.SeleniumTestCase;
+import org.apache.tapestry5.test.TapestryTestConfiguration;
 import org.testng.annotations.Test;
 
 @Test(sequential = true, groups = "integration")
-public class TapestryBeanValidationIntegrationTests extends AbstractIntegrationTestSuite
+@TapestryTestConfiguration(webAppFolder = "src/test/webapp")
+public class TapestryBeanValidationIntegrationTests extends SeleniumTestCase
 {
-    public TapestryBeanValidationIntegrationTests()
-    {
-        super("src/test/webapp");
-    }
-
     @Test
     public void form_validation() throws Exception
     {
-    	start("Form Validation Demo");
-    	
+      openLinks("Form Validation Demo");
+
     	//Test JSR-303 validator
-    	
+
     	clickAndWait(SUBMIT);
 
         assertTextPresent("Login Name may not be null");
@@ -39,18 +36,18 @@ public class TapestryBeanValidationIntegrationTests extends AbstractIntegrationT
         assertTextPresent("Favorite Colors may not be null");
         assertTextPresent("More Colors size must be between 3 and 4");
         assertTextPresent("Birth Day may not be null");
-        
+
 
         type("secretPassword", "igor");
-        
+
     	addSelection("programmingLanguages-avail", "label=Java");
     	addSelection("programmingLanguages-avail", "label=Ruby");
     	click("programmingLanguages-select");
-    	
+
     	select("favoriteColors", "label=Green");
-    	
+
     	type("birthDay", "01.01.5000");
-    	
+
     	clickAndWait(SUBMIT);
 
     	assertTextPresent("Login Name may not be null");
@@ -59,115 +56,115 @@ public class TapestryBeanValidationIntegrationTests extends AbstractIntegrationT
     	assertFalse(isTextPresent("Favorite Colors may not be null"));
         assertTextPresent("More Colors size must be between 3 and 4");
     	assertTextPresent("Birth Day must be in the past");
-        
+
         //Test Tapestry validator
-        
+
         type("loginName", "igor");
         type("birthDay", "6.04.1978");
 
         check("//input[@value='White']");
         check("//input[@value='Yellow']");
         check("//input[@value='Orange']");
-    	
+
     	clickAndWait(SUBMIT);
-    	
+
     	assertTextPresent("You must provide at least 5 characters for Login Name.");
     	assertFalse(isTextPresent("Birth Day must be in the past"));
     	assertFalse(isTextPresent("More Colors size must be between 3 and 4"));
-        
+
         type("loginName", "igor123");
-    	
+
     	clickAndWait(SUBMIT);
-    	
+
     	assertFalse(isTextPresent("You must provide at least 5 characters for Login Name."));
     }
 
     @Test
     public void beaneditform_validation() throws Exception
     {
-    	start("BeanEditForm Validation Demo");
-    	
+    	openLinks("BeanEditForm Validation Demo");
+
     	clickAndWait(SUBMIT);
-    	
+
         assertTextPresent("User Name may not be null", "Password may not be null");
-        
+
         type("userName", "igor");
-    	
+
     	clickAndWait(SUBMIT);
-    	
+
         assertTextPresent("User Name size must be between 7 and 10", "User Name must match \"[0-9]+\"");
     }
-    
+
     @Test
     public void inject_validator() throws Exception
     {
-    	start("Inject Validator Demo");
-    	
+    	openLinks("Inject Validator Demo");
+
     	clickAndWait(SUBMIT);
 
     	assertTextPresent("User Name may not be null");
     }
-    
+
     @Test
     public void client_validaton() throws Exception
     {
-    	start("Client Validation Demo");
-    	
+    	openLinks("Client Validation Demo");
+
     	//@NotNull
     	click(SUBMIT);
 
     	assertBubbleMessage("notNullValue", "Not Null Value may not be null");
-    	
+
     	type("notNullValue", "igor");
-    	
+
     	//@Min
     	type("minValue", "3");
-    	
+
     	click(SUBMIT);
-    	
+
     	assertBubbleMessage("minValue", "Min Value must be greater than or equal to 6");
-    	
+
     	//@Max
     	type("minValue", "6");
     	type("maxValue", "123");
-    	
+
     	click(SUBMIT);
-    	
+
     	assertBubbleMessage("maxValue", "Max Value must be less than or equal to 100");
-    	
+
     	//@Null
     	type("maxValue", "100");
     	type("nullValue", "igor");
-    	
+
     	type("stringSizeValue", "a");
-    	
+
     	click(SUBMIT);
-    	
+
     	assertBubbleMessage("stringSizeValue", "String Size Value size must be between 3 and 6");
-    	
+
     	click(SUBMIT);
-    	
+
     	type("stringSizeValue", "ab");
-    	
+
     	addSelection("languages-avail", "label=Java");
     	click("languages-select");
-    	
+
     	click(SUBMIT);
-    	
+
     	assertBubbleMessage("languages", "Languages size must be between 2 and 3");
-    	
+
     	click(SUBMIT);
 
     	assertBubbleMessage("nullValue", "Null Value must be null");
     }
-    
 
-    
+
+
     @Test
     public void form_client_validation() throws Exception
     {
-    	start("Form Client Validation Demo");
-    	
+    	openLinks("Form Client Validation Demo");
+
     	click(SUBMIT);
 
     	assertBubbleMessage("loginName", "Login Name may not be null");
@@ -175,37 +172,37 @@ public class TapestryBeanValidationIntegrationTests extends AbstractIntegrationT
     	assertBubbleMessage("programmingLanguages", "Programming Languages may not be null");
     	assertBubbleMessage("favoriteColors", "Favorite Colors may not be null");
     	assertBubbleMessage("birthDay", "Birth Day may not be null");
-    	
+
     	type("loginName", "123");
     	click(SUBMIT);
-    	
+
     	assertBubbleMessage("loginName", "Login Name must match \"[a-zA-Z]+\"");
-    	
+
     	type("loginName", "abc");
     	click(SUBMIT);
-    	
+
     	assertBubbleMessage("loginName", "You must provide at least 5 characters for Login Name.");
     }
-    
+
     /*
      * Ensures TAP5-1393 is fixed.
      */
     @Test
     public void form_on_prepare() throws Exception
     {
-    	start("OnPrepare Demo");
-    	
+    	openLinks("OnPrepare Demo");
+
     	clickAndWait(SUBMIT);
-    	
+
         assertTextPresent("Login Name may not be null", "Secret Password may not be null");
-        
+
         type("loginName", "igor");
-    	
+
     	clickAndWait(SUBMIT);
-    	
+
         assertTextPresent("Login Name size must be between 7 and 10", "Login Name must match \"[0-9]+\"");
     }
-    
+
     protected final void assertBubbleMessage(String fieldId, String expected)
     {
         String popupId = fieldId + "_errorpopup";
@@ -214,11 +211,4 @@ public class TapestryBeanValidationIntegrationTests extends AbstractIntegrationT
 
         assertText(String.format("//div[@id='%s']/span", popupId), expected);
     }
-    
-    protected final void waitForElementToAppear(String elementId)
-    {
-        String condition = String.format("window.$(\"%s\")", elementId);
-
-        waitForCondition(condition, PAGE_LOAD_TIMEOUT);
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/f656ce39/tapestry-test/build.gradle
----------------------------------------------------------------------
diff --git a/tapestry-test/build.gradle b/tapestry-test/build.gradle
index 23a1aed..8214e97 100644
--- a/tapestry-test/build.gradle
+++ b/tapestry-test/build.gradle
@@ -1,23 +1,22 @@
 description = "Utilities for unit and integration testing of Tapestry applications"
 
-versions.selenium = '2.14.0'
+versions.selenium = '2.26.0'
 
 dependencies {
   compile "org.seleniumhq.selenium:selenium-java:${versions.selenium}"
   compile "org.seleniumhq.selenium:selenium-server:${versions.selenium}"
-  compile "jetty:org.mortbay.jetty:5.1.12"
 
   compile "org.testng:testng:${versions.testng}"
-    
+
   compile "org.eclipse.jetty:jetty-server:${versions.jetty}"
   compile "org.eclipse.jetty:jetty-jndi:${versions.jetty}"
   compile "org.eclipse.jetty:jetty-plus:${versions.jetty}"
   compile "org.eclipse.jetty:jetty-webapp:${versions.jetty}"
-  
+
   compile "org.apache.tomcat:catalina:${versions.tomcat}"
   compile "org.apache.tomcat:coyote:${versions.tomcat}"
-  
+
   compile "org.apache.tomcat:dbcp:${versions.tomcat}"
 
   compile "org.easymock:easymock:${versions.easymock}"
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/f656ce39/tapestry-test/src/main/java/org/apache/tapestry5/test/AbstractIntegrationTestSuite.java
----------------------------------------------------------------------
diff --git a/tapestry-test/src/main/java/org/apache/tapestry5/test/AbstractIntegrationTestSuite.java b/tapestry-test/src/main/java/org/apache/tapestry5/test/AbstractIntegrationTestSuite.java
deleted file mode 100644
index 116ddd7..0000000
--- a/tapestry-test/src/main/java/org/apache/tapestry5/test/AbstractIntegrationTestSuite.java
+++ /dev/null
@@ -1,1203 +0,0 @@
-// Copyright 2007, 2008, 2009 The Apache Software Foundation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.tapestry5.test;
-
-import com.thoughtworks.selenium.CommandProcessor;
-import com.thoughtworks.selenium.DefaultSelenium;
-import com.thoughtworks.selenium.HttpCommandProcessor;
-import com.thoughtworks.selenium.Selenium;
-import org.openqa.selenium.server.RemoteControlConfiguration;
-import org.openqa.selenium.server.SeleniumServer;
-import org.testng.Assert;
-import org.testng.ITestContext;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-
-/**
- * A base class for creating integration tests. Ths encapsulates starting up an in-process copy of
- * Jetty, and in-process
- * copy of {@link SeleniumServer}, and a Selenium client.
- * <p/>
- * Unless you are <em>very, very clever</em>, you will want to run the tests sequentially. TestNG
- * tends to run them in an arbitrary order unless you explicitly set the order. If you have managed
- * to get TestNG to run tests in parallel, you may see further problems caused by a single client
- * jumping all over your web application in an unpredictable order.
- * <p/>
- * This class implements the {@link Selenium} interface, and delegates all those methods to the
- * {@link DefaultSelenium} instance it creates. It also extends the normal exception reporting for
- * any failed command or query to produce a more detailed report to the main console.
- * 
- * @see org.apache.tapestry5.test.JettyRunner
- * @deprecated Use {@link SeleniumLauncher} and {@link SeleniumTestCase} instead.
- */
-public class AbstractIntegrationTestSuite extends Assert implements Selenium
-{
-    /**
-     * Default directory containing the web application to be tested (this conforms to Maven's
-     * default folder).
-     */
-    public static final String DEFAULT_WEB_APP_ROOT = "src/main/webapp";
-
-    /**
-     * Default browser in which to run tests - firefox
-     */
-    public static final String DEFAULT_WEB_BROWSER_COMMAND = "*firefox";
-
-    /**
-     * 15 seconds
-     */
-    public static final String PAGE_LOAD_TIMEOUT = "15000";
-
-    /**
-     * The port on which the internal copy of Jetty is executed.
-     */
-    public static final int JETTY_PORT = 9999;
-
-    // This is likely to be a problem, since may want to test with a context path, rather than as
-    // root.
-    public static final String BASE_URL = String.format("http://localhost:%d/", JETTY_PORT);
-
-    public static final String SUBMIT = "//input[@type='submit']";
-
-    private String webappRoot;
-
-    private final String seleniumBrowserCommand;
-
-    private JettyRunner jettyRunner;
-
-    private Selenium selenium;
-
-    private SeleniumServer server;
-
-    private String[] virtualHosts;
-
-    /**
-     * Initializes the suite using {@link #DEFAULT_WEB_APP_ROOT}.
-     */
-    public AbstractIntegrationTestSuite()
-    {
-        this(DEFAULT_WEB_APP_ROOT, DEFAULT_WEB_BROWSER_COMMAND, new String[0]);
-    }
-
-    /**
-     * @param webAppRoot
-     *            the directory containing the web application to be tested.
-     */
-    protected AbstractIntegrationTestSuite(String webAppRoot)
-    {
-        this(webAppRoot, DEFAULT_WEB_BROWSER_COMMAND);
-    }
-
-    /**
-     * @param webAppRoot
-     *            web application root (default src/main/webapp)
-     * @param browserCommand
-     *            browser command to pass to selenium. Default is *firefox, syntax for custom
-     *            browsers is
-     *            *custom &lt;path_to_browser&gt;, e.g. *custom /usr/lib/mozilla-firefox/firefox
-     * @param virtualHosts
-     *            an array with virtual hosts
-     */
-    protected AbstractIntegrationTestSuite(String webAppRoot, String browserCommand,
-            String... virtualHosts)
-    {
-        webappRoot = webAppRoot;
-        seleniumBrowserCommand = browserCommand;
-        this.virtualHosts = virtualHosts;
-    }
-
-    protected final void assertSourcePresent(String... expected)
-    {
-        String source = selenium.getHtmlSource();
-
-        for (String snippet : expected)
-        {
-            if (source.contains(snippet))
-                continue;
-
-            System.err.printf("Source content '%s' not found in:\n%s\n\n", snippet, source);
-
-            throw new AssertionError("Page did not contain source '" + snippet + "'.");
-        }
-    }
-
-    /**
-     * Used when the locator identifies an attribute, not an element.
-     * 
-     * @param locator
-     *            identifies the attribute whose value is to be asserted
-     * @param expected
-     *            expected value for the attribute
-     */
-    protected final void assertAttribute(String locator, String expected)
-    {
-        String actual = null;
-
-        try
-        {
-            actual = getAttribute(locator);
-        }
-        catch (RuntimeException ex)
-        {
-            System.err.printf("Error accessing %s: %s, in:\n\n%s\n\n", locator, ex.getMessage(),
-                    selenium.getHtmlSource());
-
-            throw ex;
-        }
-
-        if (actual.equals(expected))
-            return;
-
-        System.err.printf("Text for attribute %s should be '%s' but is '%s', in:\n\n%s\n\n",
-                locator, expected, actual, getHtmlSource());
-
-        throw new AssertionError(String.format("%s was '%s' not '%s'", locator, actual, expected));
-    }
-
-    /**
-     * Asserts the text of an element, identified by the locator.
-     * 
-     * @param locator
-     *            identifies the element whose text value is to be asserted
-     * @param expected
-     *            expected value for the element's text
-     */
-    protected final void assertText(String locator, String expected)
-    {
-        String actual = null;
-
-        try
-        {
-            actual = getText(locator);
-        }
-        catch (RuntimeException ex)
-        {
-            System.err.printf("Error accessing %s: %s, in:\n\n%s\n\n", locator, ex.getMessage(),
-                    selenium.getHtmlSource());
-
-            throw ex;
-        }
-
-        if (actual.equals(expected))
-            return;
-
-        System.err.printf("Text for %s should be '%s' but is '%s', in:\n\n%s\n\n", locator,
-                expected, actual, getHtmlSource());
-
-        throw new AssertionError(String.format("%s was '%s' not '%s'", locator, actual, expected));
-    }
-
-    protected final void assertTextPresent(String... text)
-    {
-        for (String item : text)
-        {
-            if (isTextPresent(item))
-                continue;
-
-            System.err.printf("Text pattern '%s' not found in:\n%s\n\n", item, selenium
-                    .getHtmlSource());
-
-            throw new AssertionError("Page did not contain '" + item + "'.");
-        }
-    }
-
-    protected final void assertFieldValue(String locator, String expected)
-    {
-        try
-        {
-            assertEquals(getValue(locator), expected);
-        }
-        catch (AssertionError ex)
-        {
-            System.err.printf("%s:\n%s\n\n", ex.getMessage(), selenium.getHtmlSource());
-
-            throw ex;
-        }
-    }
-
-    protected final void clickAndWait(String link)
-    {
-        click(link);
-        waitForPageToLoad(PAGE_LOAD_TIMEOUT);
-    }
-
-    protected final void assertTextSeries(String idFormat, int startIndex, String... values)
-    {
-        for (int i = 0; i < values.length; i++)
-        {
-            String id = String.format(idFormat, startIndex + i);
-
-            assertText(id, values[i]);
-        }
-    }
-
-    protected final void assertAttributeSeries(String idFormat, int startIndex, String... values)
-    {
-        for (int i = 0; i < values.length; i++)
-        {
-            String id = String.format(idFormat, startIndex + i);
-
-            assertAttribute(id, values[i]);
-        }
-    }
-
-    protected final void assertFieldValueSeries(String idFormat, int startIndex, String... values)
-    {
-        for (int i = 0; i < values.length; i++)
-        {
-            String id = String.format(idFormat, startIndex + i);
-
-            assertFieldValue(id, values[i]);
-        }
-    }
-
-    protected void waitForCSSSelectedElementToAppear(String cssRule)
-    {
-        String condition = String.format(
-                "selenium.browserbot.getCurrentWindow().$$(\"%s\").size() > 0", cssRule);
-
-        waitForCondition(condition, PAGE_LOAD_TIMEOUT);
-
-    }
-
-    @AfterClass(alwaysRun = true)
-    public void cleanup() throws Exception
-    {
-        if (selenium != null)
-        {
-            selenium.stop();
-            selenium = null;
-        }
-
-        if (server != null)
-        {
-            server.stop();
-            server = null;
-        }
-
-        if (jettyRunner != null)
-        {
-            jettyRunner.stop();
-            jettyRunner = null;
-        }
-    }
-
-    @BeforeClass(alwaysRun = true)
-    public void setup(ITestContext testContext) throws Exception
-    {
-        jettyRunner = new JettyRunner(TapestryTestConstants.MODULE_BASE_DIR, "/", JETTY_PORT,
-                webappRoot, virtualHosts);
-
-        server = new SeleniumServer();
-
-        server.start();
-
-        CommandProcessor cp = new HttpCommandProcessor("localhost",
-                RemoteControlConfiguration.DEFAULT_PORT, seleniumBrowserCommand, BASE_URL);
-
-        ErrorReporter errorReporter = new ErrorReporterImpl(cp, testContext);
-
-        selenium = new DefaultSelenium(new ErrorReportingCommandProcessor(cp, errorReporter));
-
-        selenium.start();
-    }
-
-    public void start()
-    {
-        selenium.start();
-    }
-
-    public void stop()
-    {
-        selenium.stop();
-    }
-
-    public void click(String locator)
-    {
-        selenium.click(locator);
-    }
-
-    public void doubleClick(String locator)
-    {
-        selenium.doubleClick(locator);
-    }
-
-    public void contextMenu(String locator)
-    {
-        selenium.contextMenu(locator);
-    }
-
-    public void clickAt(String locator, String coordString)
-    {
-        selenium.clickAt(locator, coordString);
-    }
-
-    public void doubleClickAt(String locator, String coordString)
-    {
-        selenium.doubleClickAt(locator, coordString);
-    }
-
-    public void contextMenuAt(String locator, String coordString)
-    {
-        selenium.contextMenuAt(locator, coordString);
-    }
-
-    public void fireEvent(String locator, String eventName)
-    {
-        selenium.fireEvent(locator, eventName);
-    }
-
-    public void focus(String locator)
-    {
-        selenium.focus(locator);
-    }
-
-    public void keyPress(String locator, String keySequence)
-    {
-        selenium.keyPress(locator, keySequence);
-    }
-
-    public void shiftKeyDown()
-    {
-        selenium.shiftKeyDown();
-    }
-
-    public void shiftKeyUp()
-    {
-        selenium.shiftKeyUp();
-    }
-
-    public void metaKeyDown()
-    {
-        selenium.metaKeyDown();
-    }
-
-    public void metaKeyUp()
-    {
-        selenium.metaKeyUp();
-    }
-
-    public void altKeyDown()
-    {
-        selenium.altKeyDown();
-    }
-
-    public void altKeyUp()
-    {
-        selenium.altKeyUp();
-    }
-
-    public void controlKeyDown()
-    {
-        selenium.controlKeyDown();
-    }
-
-    public void controlKeyUp()
-    {
-        selenium.controlKeyUp();
-    }
-
-    public void keyDown(String locator, String keySequence)
-    {
-        selenium.keyDown(locator, keySequence);
-    }
-
-    public void keyUp(String locator, String keySequence)
-    {
-        selenium.keyUp(locator, keySequence);
-    }
-
-    public void mouseOver(String locator)
-    {
-        selenium.mouseOver(locator);
-    }
-
-    public void mouseOut(String locator)
-    {
-        selenium.mouseOut(locator);
-    }
-
-    public void mouseDown(String locator)
-    {
-        selenium.mouseDown(locator);
-    }
-
-    public void mouseDownAt(String locator, String coordString)
-    {
-        selenium.mouseDownAt(locator, coordString);
-    }
-
-    public void mouseUp(String locator)
-    {
-        selenium.mouseUp(locator);
-    }
-
-    public void mouseUpAt(String locator, String coordString)
-    {
-        selenium.mouseUpAt(locator, coordString);
-    }
-
-    public void mouseMove(String locator)
-    {
-        selenium.mouseMove(locator);
-    }
-
-    public void mouseMoveAt(String locator, String coordString)
-    {
-        selenium.mouseMoveAt(locator, coordString);
-    }
-
-    public void type(String locator, String value)
-    {
-        selenium.type(locator, value);
-    }
-
-    public void typeKeys(String locator, String value)
-    {
-        selenium.typeKeys(locator, value);
-    }
-
-    public void setSpeed(String value)
-    {
-        selenium.setSpeed(value);
-    }
-
-    public String getSpeed()
-    {
-        return selenium.getSpeed();
-    }
-
-    public void check(String locator)
-    {
-        selenium.check(locator);
-    }
-
-    public void uncheck(String locator)
-    {
-        selenium.uncheck(locator);
-    }
-
-    public void select(String selectLocator, String optionLocator)
-    {
-        selenium.select(selectLocator, optionLocator);
-    }
-
-    public void addSelection(String locator, String optionLocator)
-    {
-        selenium.addSelection(locator, optionLocator);
-    }
-
-    public void removeSelection(String locator, String optionLocator)
-    {
-        selenium.removeSelection(locator, optionLocator);
-    }
-
-    public void removeAllSelections(String locator)
-    {
-        selenium.removeAllSelections(locator);
-    }
-
-    public void submit(String formLocator)
-    {
-        selenium.submit(formLocator);
-    }
-
-    public void open(String url)
-    {
-        // open the URL but ignore the HTTP status code. Necessary if we want to check
-        // for certain contents on error pages. The behaviour changed in Selenium 1.0.2.
-        // Until then the HTTP status code was just ignored.
-        selenium.open(url, "true");
-    }
-
-    public void openWindow(String url, String windowID)
-    {
-        selenium.openWindow(url, windowID);
-    }
-
-    public void selectWindow(String windowID)
-    {
-        selenium.selectWindow(windowID);
-    }
-
-    public void selectFrame(String locator)
-    {
-        selenium.selectFrame(locator);
-    }
-
-    public boolean getWhetherThisFrameMatchFrameExpression(String currentFrameString, String target)
-    {
-        return selenium.getWhetherThisFrameMatchFrameExpression(currentFrameString, target);
-    }
-
-    public boolean getWhetherThisWindowMatchWindowExpression(String currentWindowString,
-            String target)
-    {
-        return selenium.getWhetherThisWindowMatchWindowExpression(currentWindowString, target);
-    }
-
-    /**
-     * Waits the default time for the page to load.
-     */
-    public void waitForPageToLoad()
-    {
-        waitForPageToLoad(PAGE_LOAD_TIMEOUT);
-    }
-
-    public void waitForPopUp(String windowID, String timeout)
-    {
-        selenium.waitForPopUp(windowID, timeout);
-    }
-
-    public void chooseCancelOnNextConfirmation()
-    {
-        selenium.chooseCancelOnNextConfirmation();
-    }
-
-    public void chooseOkOnNextConfirmation()
-    {
-        selenium.chooseOkOnNextConfirmation();
-    }
-
-    public void answerOnNextPrompt(String answer)
-    {
-        selenium.answerOnNextPrompt(answer);
-    }
-
-    public void goBack()
-    {
-        selenium.goBack();
-    }
-
-    public void refresh()
-    {
-        selenium.refresh();
-    }
-
-    public void close()
-    {
-        selenium.close();
-    }
-
-    public boolean isAlertPresent()
-    {
-        return selenium.isAlertPresent();
-    }
-
-    public boolean isPromptPresent()
-    {
-        return selenium.isPromptPresent();
-    }
-
-    public boolean isConfirmationPresent()
-    {
-        return selenium.isConfirmationPresent();
-    }
-
-    public String getAlert()
-    {
-        return selenium.getAlert();
-    }
-
-    public String getConfirmation()
-    {
-        return selenium.getConfirmation();
-    }
-
-    public String getPrompt()
-    {
-        return selenium.getPrompt();
-    }
-
-    public String getLocation()
-    {
-        return selenium.getLocation();
-    }
-
-    public String getTitle()
-    {
-        return selenium.getTitle();
-    }
-
-    public String getBodyText()
-    {
-        return selenium.getBodyText();
-    }
-
-    public String getValue(String locator)
-    {
-        return selenium.getValue(locator);
-    }
-
-    public String getText(String locator)
-    {
-        return selenium.getText(locator);
-    }
-
-    public void highlight(String locator)
-    {
-        selenium.highlight(locator);
-    }
-
-    public String getEval(String script)
-    {
-        return selenium.getEval(script);
-    }
-
-    public boolean isChecked(String locator)
-    {
-        return selenium.isChecked(locator);
-    }
-
-    public String getTable(String tableCellAddress)
-    {
-        return selenium.getTable(tableCellAddress);
-    }
-
-    public String[] getSelectedLabels(String selectLocator)
-    {
-        return selenium.getSelectedLabels(selectLocator);
-    }
-
-    public String getSelectedLabel(String selectLocator)
-    {
-        return selenium.getSelectedLabel(selectLocator);
-    }
-
-    public String[] getSelectedValues(String selectLocator)
-    {
-        return selenium.getSelectedValues(selectLocator);
-    }
-
-    public String getSelectedValue(String selectLocator)
-    {
-        return selenium.getSelectedValue(selectLocator);
-    }
-
-    public String[] getSelectedIndexes(String selectLocator)
-    {
-        return selenium.getSelectedIndexes(selectLocator);
-    }
-
-    public String getSelectedIndex(String selectLocator)
-    {
-        return selenium.getSelectedIndex(selectLocator);
-    }
-
-    public String[] getSelectedIds(String selectLocator)
-    {
-        return selenium.getSelectedIds(selectLocator);
-    }
-
-    public String getSelectedId(String selectLocator)
-    {
-        return selenium.getSelectedId(selectLocator);
-    }
-
-    public boolean isSomethingSelected(String selectLocator)
-    {
-        return selenium.isSomethingSelected(selectLocator);
-    }
-
-    public String[] getSelectOptions(String selectLocator)
-    {
-        return selenium.getSelectOptions(selectLocator);
-    }
-
-    public String getAttribute(String attributeLocator)
-    {
-        return selenium.getAttribute(attributeLocator);
-    }
-
-    public boolean isTextPresent(String pattern)
-    {
-        return selenium.isTextPresent(pattern);
-    }
-
-    public boolean isElementPresent(String locator)
-    {
-        return selenium.isElementPresent(locator);
-    }
-
-    public boolean isVisible(String locator)
-    {
-        return selenium.isVisible(locator);
-    }
-
-    public boolean isEditable(String locator)
-    {
-        return selenium.isEditable(locator);
-    }
-
-    public String[] getAllButtons()
-    {
-        return selenium.getAllButtons();
-    }
-
-    public String[] getAllLinks()
-    {
-        return selenium.getAllLinks();
-    }
-
-    public String[] getAllFields()
-    {
-        return selenium.getAllFields();
-    }
-
-    public String[] getAttributeFromAllWindows(String attributeName)
-    {
-        return selenium.getAttributeFromAllWindows(attributeName);
-    }
-
-    public void dragdrop(String locator, String movementsString)
-    {
-        selenium.dragdrop(locator, movementsString);
-    }
-
-    public void setMouseSpeed(String pixels)
-    {
-        selenium.setMouseSpeed(pixels);
-    }
-
-    public Number getMouseSpeed()
-    {
-        return selenium.getMouseSpeed();
-    }
-
-    public void dragAndDrop(String locator, String movementsString)
-    {
-        selenium.dragAndDrop(locator, movementsString);
-    }
-
-    public void dragAndDropToObject(String locatorOfObjectToBeDragged,
-            String locatorOfDragDestinationObject)
-    {
-        selenium.dragAndDropToObject(locatorOfObjectToBeDragged, locatorOfDragDestinationObject);
-    }
-
-    public void windowFocus()
-    {
-        selenium.windowFocus();
-    }
-
-    public void windowMaximize()
-    {
-        selenium.windowMaximize();
-    }
-
-    public String[] getAllWindowIds()
-    {
-        return selenium.getAllWindowIds();
-    }
-
-    public String[] getAllWindowNames()
-    {
-        return selenium.getAllWindowNames();
-    }
-
-    public String[] getAllWindowTitles()
-    {
-        return selenium.getAllWindowTitles();
-    }
-
-    public String getHtmlSource()
-    {
-        return selenium.getHtmlSource();
-    }
-
-    public void setCursorPosition(String locator, String position)
-    {
-        selenium.setCursorPosition(locator, position);
-    }
-
-    public Number getElementIndex(String locator)
-    {
-        return selenium.getElementIndex(locator);
-    }
-
-    public boolean isOrdered(String locator1, String locator2)
-    {
-        return selenium.isOrdered(locator1, locator2);
-    }
-
-    public Number getElementPositionLeft(String locator)
-    {
-        return selenium.getElementPositionLeft(locator);
-    }
-
-    public Number getElementPositionTop(String locator)
-    {
-        return selenium.getElementPositionTop(locator);
-    }
-
-    public Number getElementWidth(String locator)
-    {
-        return selenium.getElementWidth(locator);
-    }
-
-    public Number getElementHeight(String locator)
-    {
-        return selenium.getElementHeight(locator);
-    }
-
-    public Number getCursorPosition(String locator)
-    {
-        return selenium.getCursorPosition(locator);
-    }
-
-    public String getExpression(String expression)
-    {
-        return selenium.getExpression(expression);
-    }
-
-    public Number getXpathCount(String xpath)
-    {
-        return selenium.getXpathCount(xpath);
-    }
-
-    public void assignId(String locator, String identifier)
-    {
-        selenium.assignId(locator, identifier);
-    }
-
-    public void allowNativeXpath(String allow)
-    {
-        selenium.allowNativeXpath(allow);
-    }
-
-    public void ignoreAttributesWithoutValue(String ignore)
-    {
-        selenium.ignoreAttributesWithoutValue(ignore);
-    }
-
-    public void waitForCondition(String script, String timeout)
-    {
-        selenium.waitForCondition(script, timeout);
-    }
-
-    public void setTimeout(String timeout)
-    {
-        selenium.setTimeout(timeout);
-    }
-
-    public void waitForPageToLoad(String timeout)
-    {
-        selenium.waitForPageToLoad(timeout);
-    }
-
-    public void waitForFrameToLoad(String frameAddress, String timeout)
-    {
-        selenium.waitForFrameToLoad(frameAddress, timeout);
-    }
-
-    public String getCookie()
-    {
-        return selenium.getCookie();
-    }
-
-    public String getCookieByName(String name)
-    {
-        return selenium.getCookieByName(name);
-    }
-
-    public boolean isCookiePresent(String name)
-    {
-        return selenium.isCookiePresent(name);
-    }
-
-    public void createCookie(String nameValuePair, String optionsString)
-    {
-        selenium.createCookie(nameValuePair, optionsString);
-    }
-
-    public void deleteCookie(String name, String optionsString)
-    {
-        selenium.deleteCookie(name, optionsString);
-    }
-
-    public void deleteAllVisibleCookies()
-    {
-        selenium.deleteAllVisibleCookies();
-    }
-
-    public void setBrowserLogLevel(String logLevel)
-    {
-        selenium.setBrowserLogLevel(logLevel);
-    }
-
-    public void runScript(String script)
-    {
-        selenium.runScript(script);
-    }
-
-    public void addLocationStrategy(String strategyName, String functionDefinition)
-    {
-        selenium.addLocationStrategy(strategyName, functionDefinition);
-    }
-
-    public void setContext(String context)
-    {
-        selenium.setContext(context);
-    }
-
-    public void attachFile(String fieldLocator, String fileLocator)
-    {
-        selenium.attachFile(fieldLocator, fileLocator);
-    }
-
-    public void captureScreenshot(String filename)
-    {
-        selenium.captureScreenshot(filename);
-    }
-
-    public void shutDownSeleniumServer()
-    {
-        selenium.shutDownSeleniumServer();
-    }
-
-    public void keyDownNative(String keycode)
-    {
-        selenium.keyDownNative(keycode);
-    }
-
-    public void keyUpNative(String keycode)
-    {
-        selenium.keyUpNative(keycode);
-    }
-
-    public void keyPressNative(String keycode)
-    {
-        selenium.keyPressNative(keycode);
-    }
-
-    /**
-     * Used to start a typical test, by opening to the base URL and clicking through a series of
-     * links.
-     * <p/>
-     * Note: Selenium 1.0-beta-2 has introduced a method start(String) which is distinct from this
-     * implementation (which dates back to Tapestry 5.0 and Selenium 1.0-beta-1).
-     */
-    protected final void start(String... linkText)
-    {
-        open(BASE_URL);
-
-        for (String s : linkText)
-            clickAndWait(String.format("link=%s", s));
-    }
-
-    public String getWebappRoot()
-    {
-        return webappRoot;
-    }
-
-    public void setWebappRoot(String webappRoot)
-    {
-        this.webappRoot = webappRoot;
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void setExtensionJs(String extensionJs)
-    {
-        selenium.setExtensionJs(extensionJs);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void start(Object optionsObject)
-    {
-        selenium.start(optionsObject);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void showContextualBanner()
-    {
-        selenium.showContextualBanner();
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void showContextualBanner(String className, String methodName)
-    {
-        selenium.showContextualBanner(className, methodName);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void mouseDownRight(String locator)
-    {
-        selenium.mouseDownRight(locator);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void mouseDownRightAt(String locator, String coordString)
-    {
-        selenium.mouseDownRightAt(locator, coordString);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void captureEntirePageScreenshot(String filename, String kwargs)
-    {
-        selenium.captureEntirePageScreenshot(filename, kwargs);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void rollup(String rollupName, String kwargs)
-    {
-        selenium.rollup(rollupName, kwargs);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void addScript(String scriptContent, String scriptTagId)
-    {
-        selenium.addScript(scriptContent, scriptTagId);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void removeScript(String scriptTagId)
-    {
-        selenium.removeScript(scriptTagId);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void useXpathLibrary(String libraryName)
-    {
-        selenium.useXpathLibrary(libraryName);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public String captureScreenshotToString()
-    {
-        return selenium.captureScreenshotToString();
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public String captureEntirePageScreenshotToString(String kwargs)
-    {
-        return selenium.captureEntirePageScreenshotToString(kwargs);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public String retrieveLastRemoteControlLogs()
-    {
-        return selenium.retrieveLastRemoteControlLogs();
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void mouseUpRight(String locator)
-    {
-        selenium.mouseUpRight(locator);
-    }
-
-    /**
-     * @since 5.1.0.0
-     */
-    public void mouseUpRightAt(String locator, String coordString)
-    {
-        selenium.mouseUpRightAt(locator, coordString);
-    }
-
-    /**
-     * This does NOT invoke {@link com.thoughtworks.selenium.Selenium#start(String)}; it invokes
-     * {@link #start(String[])}. This is necesasry due to the introduction of the start() method.
-     * 
-     * @param linkText
-     *            text of link to click
-     * @since 5.1.0.0
-     */
-    public void start(String linkText)
-    {
-        start(new String[]
-        { linkText });
-    }
-
-    /**
-     * @since 5.2.0.0
-     */
-    public void addCustomRequestHeader(String key, String value)
-    {
-        selenium.addCustomRequestHeader(key, value);
-    }
-
-    /**
-     * @since 5.2.0.0
-     */
-    public String captureNetworkTraffic(String type)
-    {
-        return selenium.captureNetworkTraffic(type);
-    }
-
-    /**
-     * @since 5.2.0.0
-     */
-    public void deselectPopUp()
-    {
-        selenium.deselectPopUp();
-    }
-
-    /**
-     * @since 5.2.0.0
-     */
-    public void selectPopUp(String windowID)
-    {
-        selenium.selectPopUp(windowID);
-    }
-
-    /**
-     * @since 5.2.0.0
-     */
-    public String getLog()
-    {
-        return selenium.getLog();
-    }
-
-    /**
-     * @since 5.2.0.0
-     */
-    public void open(String url, String ignoreResponseCode)
-    {
-        selenium.open(url, ignoreResponseCode);
-    }
-
-    public Number getCssCount(String str) {
-        return selenium.getCssCount(str);
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/f656ce39/tapestry-test/src/main/java/org/apache/tapestry5/test/JettyRunner.java
----------------------------------------------------------------------
diff --git a/tapestry-test/src/main/java/org/apache/tapestry5/test/JettyRunner.java b/tapestry-test/src/main/java/org/apache/tapestry5/test/JettyRunner.java
deleted file mode 100644
index 9c1abd0..0000000
--- a/tapestry-test/src/main/java/org/apache/tapestry5/test/JettyRunner.java
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package org.apache.tapestry5.test;
-
-import org.mortbay.http.NCSARequestLog;
-import org.mortbay.http.SocketListener;
-import org.mortbay.http.SunJsseListener;
-import org.mortbay.jetty.Server;
-import org.mortbay.jetty.servlet.WebApplicationContext;
-
-import java.io.File;
-import static java.lang.String.format;
-
-/**
- * Used to start up an instance of the Jetty servlet container in-process, as part of an integration
- * test suite. The
- * started Jetty is reliant on the file <code>src/test/conf/webdefault.xml</code>.
- * 
- * @see AbstractIntegrationTestSuite
- * @deprecated Use {@link Jetty7Runner} instead
- */
-public class JettyRunner
-{
-    public static final String DEFAULT_CONTEXT_PATH = "/";
-
-    public static final int DEFAULT_PORT = 8080;
-
-    public static final int DEFAULT_SECURE_PORT = 8443;
-
-    private final File workingDir;
-
-    private final String contextPath;
-
-    private final int port;
-
-    private final String warPath;
-
-    private final Server jetty;
-
-    private final String[] virtualHosts;
-
-    /**
-     * Creates and starts a new instance of Jetty. This should be done from a test case setup
-     * method.
-     * 
-     * @param workingDir
-     *            current directory (used for any relative files)
-     * @param contextPath
-     *            the context path for the deployed application
-     * @param port
-     *            the port number used to access the application
-     * @param warPath
-     *            the path to the exploded web application (typically, "src/main/webapp")
-     * @param virtualHosts
-     *            an array with virtual hosts
-     */
-    public JettyRunner(File workingDir, String contextPath, int port, String warPath,
-            String... virtualHosts)
-    {
-        this.workingDir = workingDir;
-        this.contextPath = contextPath;
-        this.port = port;
-        this.warPath = warPath;
-        this.virtualHosts = virtualHosts;
-
-        jetty = createAndStart();
-    }
-
-    /**
-     * Stops the Jetty instance. This should be called from a test case tear down method.
-     */
-    public void stop()
-    {
-        System.out.printf("Stopping Jetty instance on port %d\n", port);
-
-        try
-        {
-            // Stop immediately and not gracefully.
-            jetty.stop(false);
-
-            while (jetty.isStarted())
-            {
-                Thread.sleep(100);
-            }
-        }
-        catch (Exception ex)
-        {
-            throw new RuntimeException("Error stopping Jetty instance: " + ex.toString(), ex);
-        }
-
-        System.out.println("Jetty instance has stopped.");
-    }
-
-    @Override
-    public String toString()
-    {
-        return format("<JettyRunner %s:%d (%s)>", contextPath, port, warPath);
-    }
-
-    private Server createAndStart()
-    {
-        try
-        {
-
-            File warPathFile = new File(warPath);
-
-            String webappPath = warPathFile.isAbsolute() ? warPath : new File(workingDir,
-                    this.warPath).getPath();
-            String webDefaults = new File(workingDir, "src/test/conf/webdefault.xml").getPath();
-
-            File keystoreFile = new File(workingDir, "src/test/conf/keystore");
-            String keystore = keystoreFile.getPath();
-
-            System.out.printf("Starting Jetty instance on port %d (%s mapped to %s)\n", port,
-                    contextPath, webappPath);
-
-            Server server = new Server();
-
-            SocketListener socketListener = new SocketListener();
-            socketListener.setPort(port);
-            server.addListener(socketListener);
-
-            if (keystoreFile.exists())
-            {
-                SunJsseListener secureListener = new SunJsseListener();
-                secureListener.setPort(DEFAULT_SECURE_PORT);
-                secureListener.setKeystore(keystore);
-                secureListener.setPassword("tapestry");
-                secureListener.setKeyPassword("tapestry");
-
-                server.addListener(secureListener);
-            }
-
-            NCSARequestLog log = new NCSARequestLog();
-            server.setRequestLog(log);
-
-            WebApplicationContext context = server.addWebApplication(contextPath, webappPath);
-
-            for (String virtualHost : virtualHosts)
-            {
-                context.addVirtualHost(virtualHost);
-            }
-
-            context.setDefaultsDescriptor(webDefaults);
-
-            server.start();
-
-            return server;
-        }
-        catch (Exception ex)
-        {
-            throw new RuntimeException("Failure starting Jetty instance: " + ex.toString(), ex);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/f656ce39/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
----------------------------------------------------------------------
diff --git a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
index 15736dd..8251490 100644
--- a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
+++ b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
@@ -1,4 +1,4 @@
-// Copyright 2009, 2010 The Apache Software Foundation
+// Copyright 2009, 2010, 2012 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ import com.thoughtworks.selenium.Selenium;
  * Base class for creating Selenium-based integration test cases. This class implements all the
  * methods of {@link Selenium} and delegates to an instance (setup once per test by
  * {@link #testStartup(org.testng.ITestContext, org.testng.xml.XmlTest)}.
- * 
+ *
  * @since 5.2.0
  */
 public abstract class SeleniumTestCase extends Assert implements Selenium
@@ -55,7 +55,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
     /**
      * An XPath expression for locating a submit element (very commonly used
      * with {@link #clickAndWait(String)}.
-     * 
+     *
      * @since 5.3
      */
     public static final String SUBMIT = "//input[@type='submit']";
@@ -65,7 +65,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
      * this can be useful when attempting to use SeleniumTestCase with a newer version of Selenium which
      * has added some methods to the interface. This field will not be set until the test case instance
      * has gone through its full initialization.
-     * 
+     *
      * @since 5.3
      */
     protected Selenium selenium;
@@ -127,21 +127,19 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
      * <td>Command string used to launch the browser, as defined by Selenium</td>
      * </tr>
      * </table>
-     * <p>
+     * <p/>
      * Tests in the <em>beforeStartup</em> group will be run before the start of Selenium. This can be used to
-     * programmatically override the above parameter values. For an example see
-     * org.apache.tapestry5.integration.reload.ReloadTests#beforeStartup in
-     * Tapestry-core.
-     * <p>
+     * programmatically override the above parameter values.
+     * <p/>
      * This method will be invoked in <em>each</em> subclass, but is set up to only startup the servers once (it checks
      * the {@link ITestContext} to see if the necessary keys are already present).
-     * 
+     *
      * @param testContext
-     *            Used to share objects between the launcher and the test suites
+     *         Used to share objects between the launcher and the test suites
      * @throws Exception
      */
     @BeforeTest(dependsOnGroups =
-    { "beforeStartup" })
+            {"beforeStartup"})
     public void testStartup(final ITestContext testContext, XmlTest xmlTest) throws Exception
     {
         // This is not actually necessary, because TestNG will only invoke this method once
@@ -149,7 +147,9 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         // just invokes it on the "first" TestCase instance it has test methods for.
 
         if (testContext.getAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE) != null)
+        {
             return;
+        }
 
         // If a parameter is overridden in another test method, TestNG won't pass the
         // updated value via a parameter, but still passes the original (coming from testng.xml or the default).
@@ -157,13 +157,38 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
 
         // Map<String, String> testParameters = xmlTest.getParameters();
 
-        String webAppFolder = getParameter(xmlTest, TapestryTestConstants.WEB_APP_FOLDER_PARAMETER, "src/main/webapp");
-        String container = getParameter(xmlTest, TapestryTestConstants.SERVLET_CONTAINER_PARAMETER, JETTY_7);
-        String contextPath = getParameter(xmlTest, TapestryTestConstants.CONTEXT_PATH_PARAMETER, "");
-        int port = Integer.parseInt(getParameter(xmlTest, TapestryTestConstants.PORT_PARAMETER, "9090"));
-        int sslPort = Integer.parseInt(getParameter(xmlTest, TapestryTestConstants.SSL_PORT_PARAMETER, "8443"));
+        TapestryTestConfiguration annotation = this.getClass().getAnnotation(TapestryTestConfiguration.class);
+        if (annotation == null)
+        {
+            @TapestryTestConfiguration
+            final class EmptyInnerClass
+            {
+            }
+
+            annotation = EmptyInnerClass.class.getAnnotation(TapestryTestConfiguration.class);
+        }
+
+        String webAppFolder = getParameter(xmlTest, TapestryTestConstants.WEB_APP_FOLDER_PARAMETER,
+                annotation.webAppFolder());
+        String container = getParameter(xmlTest, TapestryTestConstants.SERVLET_CONTAINER_PARAMETER,
+                annotation.container());
+        String contextPath = getParameter(xmlTest, TapestryTestConstants.CONTEXT_PATH_PARAMETER,
+                annotation.contextPath());
+        int port = getIntParameter(xmlTest, TapestryTestConstants.PORT_PARAMETER, annotation.port());
+        int sslPort = getIntParameter(xmlTest, TapestryTestConstants.SSL_PORT_PARAMETER, annotation.sslPort());
         String browserStartCommand = getParameter(xmlTest, TapestryTestConstants.BROWSER_START_COMMAND_PARAMETER,
-                "*firefox");
+                annotation.browserStartCommand());
+
+        String baseURL = String.format("http://localhost:%d%s/", port, contextPath);
+
+        System.err.println("Starting SeleniumTestCase:");
+        System.err.println("    currentDir: " + System.getProperty("user.dir"));
+        System.err.println("  webAppFolder: " + webAppFolder);
+        System.err.println("     container: " + container);
+        System.err.println("   contextPath: " + contextPath);
+        System.err.printf("         ports: %d / %d%n", port, sslPort);
+        System.err.println("  browserStart: " + browserStartCommand);
+        System.err.println("       baseURL: " + baseURL);
 
         final Runnable stopWebServer = launchWebServer(container, webAppFolder, contextPath, port, sslPort);
 
@@ -172,11 +197,12 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         File ffProfileTemplate = new File(TapestryTestConstants.MODULE_BASE_DIR, "src/test/conf/ff_profile_template");
 
         if (ffProfileTemplate.isDirectory())
+        {
             seleniumServer.getConfiguration().setFirefoxProfileTemplate(ffProfileTemplate);
+        }
 
         seleniumServer.start();
 
-        String baseURL = String.format("http://localhost:%d%s/", port, contextPath);
 
         CommandProcessor httpCommandProcessor = new HttpCommandProcessor("localhost",
                 RemoteControlConfiguration.DEFAULT_PORT, browserStartCommand, baseURL);
@@ -211,8 +237,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
                     // builds.
 
                     errorReporter.writeOutputPaths();
-                }
-                finally
+                } finally
                 {
                     testContext.removeAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE);
                     testContext.removeAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE);
@@ -231,6 +256,13 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         return value != null ? value : defaultValue;
     }
 
+    private final int getIntParameter(XmlTest xmlTest, String key, int defaultValue)
+    {
+        String value = xmlTest.getParameter(key);
+
+        return value != null ? Integer.parseInt(value) : defaultValue;
+    }
+
     /**
      * Like {@link #testStartup(org.testng.ITestContext, org.testng.xml.XmlTest)} , this may
      * be called multiple times against multiple instances, but only does work the first time.
@@ -245,42 +277,33 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         // and the runnable is the last thing it puts into the test context.
 
         if (r != null)
+        {
             r.run();
+        }
     }
 
     /**
      * Invoked from {@link #testStartup(org.testng.ITestContext, org.testng.xml.XmlTest)} to launch the web
-     * server to be
-     * tested. The return value is a Runnable that will shut down the launched server at the end of
-     * the test (it is coded this way so that the default Jetty web server can be more easily
-     * replaced).
-     * 
+     * server to be tested. The return value is a Runnable that can be invoked later to cleanly shut down the launched
+     * server at the end of the test.
+     *
+     * @param container
+     *         identifies which web server should be launched
      * @param webAppFolder
-     *            path to the web application context
+     *         path to the web application context
      * @param contextPath
-     *            the path the context is mapped to, usually the empty string
+     *         the path the context is mapped to, usually the empty string
      * @param port
-     *            the port number the server should handle
+     *         the port number the server should handle
      * @param sslPort
-     *            the port number on which the server should handle secure requests
+     *         the port number on which the server should handle secure requests
      * @return Runnable used to shut down the server
      * @throws Exception
      */
-    protected Runnable launchWebServer(String webAppFolder, String contextPath, int port, int sslPort) throws Exception
-    {
-        return launchWebServer(TOMCAT_6, webAppFolder, contextPath, port, sslPort);
-    }
-
     protected Runnable launchWebServer(String container, String webAppFolder, String contextPath, int port, int sslPort)
             throws Exception
     {
-        final ServletContainerRunner runner;
-        if (TOMCAT_6.equals(container))
-            runner = new Tomcat6Runner(webAppFolder, contextPath, port, sslPort);
-        else if (JETTY_7.equals(container))
-            runner = new Jetty7Runner(webAppFolder, contextPath, port, sslPort);
-        else
-            throw new RuntimeException("Unknown servlet container: " + container);
+        final ServletContainerRunner runner = createWebServer(container, webAppFolder, contextPath, port, sslPort);
 
         return new Runnable()
         {
@@ -291,6 +314,21 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         };
     }
 
+    private ServletContainerRunner createWebServer(String container, String webAppFolder, String contextPath, int port, int sslPort) throws Exception
+    {
+        if (TOMCAT_6.equals(container))
+        {
+            return new Tomcat6Runner(webAppFolder, contextPath, port, sslPort);
+        }
+
+        if (JETTY_7.equals(container))
+        {
+            return new Jetty7Runner(webAppFolder, contextPath, port, sslPort);
+        }
+
+        throw new RuntimeException("Unknown servlet container: " + container);
+    }
+
     @BeforeClass
     public void setup(ITestContext context)
     {
@@ -311,10 +349,10 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
     }
 
     /**
-     * Delegates to {@link ErrorReporter#writeErrorReport()} to capture the current page markup in a
+     * Delegates to {@link ErrorReporter#writeErrorReport(String)} to capture the current page markup in a
      * file for later analysis.
      */
-    protected void writeErrorReport()
+    protected void writeErrorReport(String reportText)
     {
         errorReporter.writeErrorReport();
     }
@@ -322,7 +360,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
     /**
      * Returns the base URL for the application. This is of the typically <code>http://localhost:9999/</code> (i.e., it
      * includes a trailing slash).
-     * <p>
+     * <p/>
      * Generally, you should use {@link #openLinks(String...)} to start from your application's home page.
      */
     public String getBaseURL()
@@ -1129,14 +1167,56 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
     // End of delegate methods
     // ---------------------------------------------------------------------
 
-    protected final void unreachable()
+    /**
+     * Formats a message from the provided arguments, which is written to System.err. In addition,
+     * captures the AUT's markup, screenshot, and a report to the output directory.
+     *
+     * @param message
+     * @param arguments
+     * @since 5.4
+     */
+    protected final void reportAndThrowAssertionError(String message, Object... arguments)
     {
-        writeErrorReport();
+        StringBuilder builder = new StringBuilder(5000);
+
+        String formatted = String.format(message, arguments);
+
+        builder.append(formatted);
+
+        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+
+        StringBuilder buffer = new StringBuilder(5000);
+
+        boolean enabled = false;
+
+        for (StackTraceElement e : stackTrace)
+        {
+            if (enabled)
+            {
+                buffer.append("\n- ");
+                buffer.append(e);
+                continue;
+            }
+
+            if (e.getMethodName().equals("reportAndThrowAssertionError"))
+            {
+                enabled = true;
+            }
+        }
 
-        throw new AssertionError("This statement should not be reachable.");
+        writeErrorReport(builder.toString());
+
+        throw new AssertionError(formatted);
+    }
+
+    protected final void unreachable()
+    {
+        reportAndThrowAssertionError("An unreachable statement was reached.");
     }
 
-    /** Open the {@linkplain #getBaseURL()}, and waits for the page to load. */
+    /**
+     * Open the {@linkplain #getBaseURL()}, and waits for the page to load.
+     */
     protected final void openBaseURL()
     {
         open(baseURL);
@@ -1146,11 +1226,11 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
 
     /**
      * Asserts the text of an element, identified by the locator.
-     * 
+     *
      * @param locator
-     *            identifies the element whose text value is to be asserted
+     *         identifies the element whose text value is to be asserted
      * @param expected
-     *            expected value for the element's text
+     *         expected value for the element's text
      */
     protected final void assertText(String locator, String expected)
     {
@@ -1159,8 +1239,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         try
         {
             actual = getText(locator);
-        }
-        catch (RuntimeException ex)
+        } catch (RuntimeException ex)
         {
             System.err.printf("Error accessing %s: %s, in:\n\n%s\n\n", locator, ex.getMessage(), getHtmlSource());
 
@@ -1168,11 +1247,11 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         }
 
         if (actual.equals(expected))
+        {
             return;
+        }
 
-        writeErrorReport();
-
-        throw new AssertionError(String.format("%s was '%s' not '%s'", locator, actual, expected));
+        reportAndThrowAssertionError("%s was '%s' not '%s'", locator, actual, expected);
     }
 
     protected final void assertTextPresent(String... text)
@@ -1180,19 +1259,19 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         for (String item : text)
         {
             if (isTextPresent(item))
+            {
                 continue;
+            }
 
-            writeErrorReport();
-
-            throw new AssertionError("Page did not contain '" + item + "'.");
+            reportAndThrowAssertionError("Page did not contain '" + item + "'.");
         }
     }
 
     /**
      * Assets that each string provided is present somewhere in the current document.
-     * 
+     *
      * @param expected
-     *            string expected to be present
+     *         string expected to be present
      */
     protected final void assertSourcePresent(String... expected)
     {
@@ -1201,20 +1280,20 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         for (String snippet : expected)
         {
             if (source.contains(snippet))
+            {
                 continue;
+            }
 
-            writeErrorReport();
-
-            throw new AssertionError("Page did not contain source '" + snippet + "'.");
+            reportAndThrowAssertionError("Page did not contain source '" + snippet + "'.");
         }
     }
 
     /**
      * Click a link identified by a locator, then wait for the resulting page to load.
      * This is not useful for Ajax updates, just normal full-page refreshes.
-     * 
+     *
      * @param locator
-     *            identifies the link to click
+     *         identifies the link to click
      */
     protected final void clickAndWait(String locator)
     {
@@ -1234,11 +1313,11 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
 
     /**
      * Used when the locator identifies an attribute, not an element.
-     * 
+     *
      * @param locator
-     *            identifies the attribute whose value is to be asserted
+     *         identifies the attribute whose value is to be asserted
      * @param expected
-     *            expected value for the attribute
+     *         expected value for the attribute
      */
     protected final void assertAttribute(String locator, String expected)
     {
@@ -1247,31 +1326,27 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         try
         {
             actual = getAttribute(locator);
-        }
-        catch (RuntimeException ex)
+        } catch (RuntimeException ex)
         {
-            System.err.printf("Error accessing %s: %s", locator, ex.getMessage());
 
-            writeErrorReport();
-
-            throw ex;
+            reportAndThrowAssertionError("Error accessing %s: %s", locator, ex.getMessage());
         }
 
         if (actual.equals(expected))
+        {
             return;
+        }
 
-        writeErrorReport();
-
-        throw new AssertionError(String.format("%s was '%s' not '%s'", locator, actual, expected));
+        reportAndThrowAssertionError("%s was '%s' not '%s'", locator, actual, expected);
     }
 
     /**
      * Assets that the value in the field matches the expectation
-     * 
+     *
      * @param locator
-     *            identifies the field
+     *         identifies the field
      * @param expected
-     *            expected value for the field
+     *         expected value for the field
      * @since 5.3
      */
     protected final void assertFieldValue(String locator, String expected)
@@ -1279,19 +1354,16 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         try
         {
             assertEquals(getValue(locator), expected);
-        }
-        catch (AssertionError ex)
+        } catch (AssertionError ex)
         {
-            writeErrorReport();
-
-            throw ex;
+            reportAndThrowAssertionError("Failure accessing %s: %s", locator, ex);
         }
     }
 
     /**
      * Opens the base URL, then clicks through a series of links to get to a desired application
      * state.
-     * 
+     *
      * @since 5.3
      */
     protected final void openLinks(String... linkText)
@@ -1306,7 +1378,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
 
     /**
      * Sleeps for the indicated number of seconds.
-     * 
+     *
      * @since 5.3
      */
     protected final void sleep(long millis)
@@ -1314,8 +1386,7 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
         try
         {
             Thread.sleep(millis);
-        }
-        catch (InterruptedException ex)
+        } catch (InterruptedException ex)
         {
             // Ignore.
         }
@@ -1324,14 +1395,14 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
     /**
      * Waits, up to the page load limit for an element (identified by a CSS rule) to exist
      * (it is not assured that the element will be visible).
-     * 
+     *
      * @param cssRule
-     *            used to locate the element
+     *         used to locate the element
      * @since 5.3
      */
     protected void waitForCSSSelectedElementToAppear(String cssRule)
     {
-        String condition = String.format("window.$$(\"%s\").size() > 0", cssRule);
+        String condition = String.format("window.$$ && window.$$(\"%s\").size() > 0", cssRule);
 
         waitForCondition(condition, PAGE_LOAD_TIMEOUT);
     }
@@ -1339,9 +1410,9 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
     /**
      * Waits for the element with the given client-side id to be present in the DOM (
      * does not assure that the element is visible).
-     * 
+     *
      * @param elementId
-     *            identifies the element
+     *         identifies the element
      * @since 5.3
      */
     protected final void waitForElementToAppear(String elementId)
@@ -1354,9 +1425,9 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
 
     /**
      * Waits for the element to be removed from the DOM.
-     * 
+     *
      * @param elementId
-     *            client-side id of element
+     *         client-side id of element
      * @since 5.3
      */
     protected final void waitForElementToDisappear(String elementId)
@@ -1370,8 +1441,9 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
      * Waits for the element specified by the selector to become visible
      * Note that waitForElementToAppear waits for the element to be present in the dom, visible or not. waitForVisible
      * waits for an element that already exists in the dom to become visible.
+     *
      * @param selector
-     *              element selector
+     *         element selector
      * @since 5.3
      */
     protected final void waitForVisible(String selector)
@@ -1385,8 +1457,9 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
      * Waits for the element specified by the selector to become invisible
      * Note that waitForElementToDisappear waits for the element to be absent from the dom, visible or not. waitForInvisible
      * waits for an existing element to become invisible.
+     *
      * @param selector
-     *              element selector
+     *         element selector
      * @since 5.3
      */
     protected final void waitForInvisible(String selector)
@@ -1395,40 +1468,63 @@ public abstract class SeleniumTestCase extends Assert implements Selenium
 
         waitForCondition(condition, PAGE_LOAD_TIMEOUT);
     }
+
     /**
      * Asserts that the current page's title matches the expected value.
-     * 
-     * @since 5.3
+     *
      * @param expected
-     *            value for title
+     *         value for title
+     * @since 5.3
      */
     protected final void assertTitle(String expected)
     {
         try
         {
             assertEquals(getTitle(), expected);
-        }
-        catch (AssertionError ex)
+        } catch (AssertionError ex)
         {
-            writeErrorReport();
+            reportAndThrowAssertionError("Unexpected title: %s", ex);
 
             throw ex;
         }
     }
 
     /**
-     * Waits until all active XHR requests are completed.
+     * Waits until all active XHR requests are completed. However, this is Prototype-based.
      *
+     * @param timeout
+     *         timeout to wait for
      * @since 5.3
-     *
-     * @param timeout timeout to wait for
+     * @deprecated Deprecated in 5.4 as it is tied to Prototype.
      */
     protected final void waitForAjaxRequestsToComplete(String timeout)
     {
         waitForCondition("selenium.browserbot.getCurrentWindow().Ajax.activeRequestCount == 0", timeout);
     }
 
-    public Number getCssCount(String str) {
+    public Number getCssCount(String str)
+    {
         return selenium.getCssCount(str);
     }
+
+    /**
+     * Waits for page initialization to finish, which is recognized by the {@code data-page-initialized} attribute
+     * being added to the HTML element. Polls at 20ms intervals for 200ms.
+     *
+     * @since 5.4
+     */
+    protected final void waitForPageInitialized()
+    {
+        for (int i = 0; i < 10; i++)
+        {
+            if (isElementPresent("css=html[data-page-initialized]"))
+            {
+                return;
+            }
+
+            sleep(20);
+        }
+
+        reportAndThrowAssertionError("Page did not finish initializing.");
+    }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/f656ce39/tapestry-test/src/main/java/org/apache/tapestry5/test/TapestryTestConfiguration.java
----------------------------------------------------------------------
diff --git a/tapestry-test/src/main/java/org/apache/tapestry5/test/TapestryTestConfiguration.java b/tapestry-test/src/main/java/org/apache/tapestry5/test/TapestryTestConfiguration.java
new file mode 100644
index 0000000..325a8b3
--- /dev/null
+++ b/tapestry-test/src/main/java/org/apache/tapestry5/test/TapestryTestConfiguration.java
@@ -0,0 +1,66 @@
+//  Copyright 2011, 2012 The Apache Software Foundation
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+
+package org.apache.tapestry5.test;
+
+import org.apache.tapestry5.test.SeleniumTestCase;
+
+import java.lang.annotation.*;
+
+/**
+ * To be used on Selenium-based integration tests that extend {@link SeleniumTestCase} as an alternative to using a
+ * TestNG XML configuration file. Using the XML file, it's intricate to run <em>individual</em> test classes or
+ * methods using IDEA's or Eclipse's TestNG integration.
+ *
+ * <b>Parameters coming from a TestNG XML configuration file take precedence over those supplied with the annotation.</b>
+ *
+ * Configures the container to be started for the tests and the browser to be used.
+ * @since 5.4
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface TapestryTestConfiguration
+{
+    /**
+     * The folder for the web application root relative to the working directory. Defaults to "src/main/webapp".
+     */
+    String webAppFolder() default "src/main/webapp";
+
+    /**
+     * Which container to use. Can be one of {@link SeleniumTestCase#JETTY_7} or {@link SeleniumTestCase#TOMCAT_6}.
+     * Defaults to {@link SeleniumTestCase#JETTY_7}.
+     */
+    String container() default SeleniumTestCase.JETTY_7;
+
+    /**
+     * The context path to make the application available under. Defaults to "", i.e. the context root.
+     */
+    String contextPath() default "";
+
+    /**
+     * The port to listen on for HTTP requests. Defaults to "9090".
+     */
+    int port() default 9090;
+
+    /**
+     * The port to listen on fot HTTPS requests. Defaults to "8443".
+     */
+    int sslPort() default 8443;
+
+    /**
+     * The browser start command to use with Selenium. Defaults to "*firefox".
+     */
+    String browserStartCommand() default "*firefox";
+}