You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2006/09/03 17:13:51 UTC
svn commit: r439787 - in /tapestry/tapestry5/tapestry-core/trunk: ./
src/main/java/org/apache/tapestry/internal/services/
src/main/java/org/apache/tapestry/services/ src/test/app1/WEB-INF/
src/test/conf/ src/test/java/org/apache/tapestry/integration/
Author: hlship
Date: Sun Sep 3 08:13:50 2006
New Revision: 439787
URL: http://svn.apache.org/viewvc?rev=439787&view=rev
Log:
Add basic integration tests, driven by Selenium.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassFactoryImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/test/conf/webdefault.xml
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/JettyRunner.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/pom.xml
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/web.xml
tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
Modified: tapestry/tapestry5/tapestry-core/trunk/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/pom.xml?rev=439787&r1=439786&r2=439787&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/pom.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/pom.xml Sun Sep 3 08:13:50 2006
@@ -54,6 +54,22 @@
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.openqa.selenium.client-drivers</groupId>
+ <artifactId>selenium-java-client-driver</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openqa.selenium.server</groupId>
+ <artifactId>selenium-server</artifactId>
+ </dependency>
+ <!--
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>6.0.0beta10</version>
+ <classifier>standalone</classifier>
+ <scope>test</scope>
+ </dependency> -->
</dependencies>
<build>
<plugins>
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassFactoryImpl.java?rev=439787&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassFactoryImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassFactoryImpl.java Sun Sep 3 08:13:50 2006
@@ -0,0 +1,81 @@
+// Copyright 2006 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.tapestry.internal.services;
+
+import org.apache.commons.logging.Log;
+import org.apache.tapestry.events.InvalidationEvent;
+import org.apache.tapestry.events.InvalidationListener;
+import org.apache.tapestry.internal.ioc.services.ClassFactoryImpl;
+import org.apache.tapestry.ioc.services.ClassFab;
+import org.apache.tapestry.ioc.services.ClassFactory;
+
+/**
+ * ClassFactory implementation that works with the class loader created for instantiating
+ * transformed component classes. Works with the
+ * {@link org.apache.tapestry.internal.services.ComponentInstantiatorSource} to handle
+ * {@link org.apache.tapestry.events.InvalidationListener#objectWasInvalidated(InvalidationEvent) invalidations of that class loader}.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public class ComponentClassFactoryImpl implements ClassFactory, InvalidationListener
+{
+ private final Log _log;
+
+ private final ComponentInstantiatorSource _source;
+
+ private ClassFactory _innerFactory;
+
+ public ComponentClassFactoryImpl(Log log, ComponentInstantiatorSource source)
+ {
+ _log = log;
+ _source = source;
+
+ source.addInvalidationListener(this);
+ }
+
+ private synchronized ClassFactory getInnerFactory()
+ {
+ if (_innerFactory == null)
+ _innerFactory = new ClassFactoryImpl(_source.getClassLoader(), _log);
+
+ return _innerFactory;
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return getInnerFactory().getClassLoader();
+ }
+
+ public int getCreatedClassCount()
+ {
+ return getInnerFactory().getCreatedClassCount();
+ }
+
+ public ClassFab newClass(Class serviceInterface)
+ {
+ return getInnerFactory().newClass(serviceInterface);
+ }
+
+ public ClassFab newClass(String name, Class superClass)
+ {
+ return getInnerFactory().newClass(name, superClass);
+ }
+
+ public synchronized void objectWasInvalidated(InvalidationEvent event)
+ {
+ _innerFactory = null;
+ }
+
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java?rev=439787&r1=439786&r2=439787&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSource.java Sun Sep 3 08:13:50 2006
@@ -26,7 +26,8 @@
* loaded classes can be discarded and rebuilt when classes change.
* <p>
* The strategy used is that when <em>any</em> class (in a controlled package) changes, the entire
- * class loader is discarded, along with any instances derived from those classes.
+ * class loader is discarded, along with any instances derived from those classes. A new class
+ * loader is created, and then invalidation events are fired to listeners.
*
* @author Howard M. Lewis Ship
*/
@@ -65,4 +66,11 @@
* the package name to add (must not be blank)
*/
void addPackage(String packageName);
+
+ /**
+ * Returns a class loader with visibility to the transformed classes. Caution: callers of this
+ * should also listen for invalidation events and re-acquire the
+ */
+
+ ClassLoader getClassLoader();
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java?rev=439787&r1=439786&r2=439787&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentInstantiatorSourceImpl.java Sun Sep 3 08:13:50 2006
@@ -32,6 +32,7 @@
import org.apache.tapestry.events.UpdateListener;
import org.apache.tapestry.internal.event.InvalidationEventHubImpl;
import org.apache.tapestry.internal.util.URLChangeTracker;
+import org.apache.tapestry.ioc.services.ClassFactory;
import org.apache.tapestry.model.ComponentModel;
import org.apache.tapestry.util.Defense;
@@ -57,6 +58,8 @@
private Loader _loader;
+ private ClassFactory _classFactory;
+
private final ComponentClassTransformer _transformer;
private final Log _log;
@@ -110,8 +113,7 @@
_instantiatorMap.clear();
// Release the existing class pool, loader and so forth.
- // Create a new one. Eventually, we need to add notifications
- // so that existing instances can be released as well.
+ // Create a new one.
initializeService();
@@ -119,8 +121,8 @@
}
/**
- * Invoked at object crtation, or when there are updates, to create a new set of Javassist class
- * pools and loaders.
+ * Invoked at object creation, or when there are updates to class files (i.e., invalidation), to
+ * create a new set of Javassist class pools and loaders.
*/
private void initializeService()
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=439787&r1=439786&r2=439787&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Sun Sep 3 08:13:50 2006
@@ -30,6 +30,7 @@
import org.apache.tapestry.internal.bindings.LiteralBindingFactory;
import org.apache.tapestry.internal.services.ApplicationGlobalsImpl;
import org.apache.tapestry.internal.services.BindingSourceImpl;
+import org.apache.tapestry.internal.services.ComponentClassFactoryImpl;
import org.apache.tapestry.internal.services.ComponentClassResolverImpl;
import org.apache.tapestry.internal.services.ComponentInstantiatorSource;
import org.apache.tapestry.internal.services.HTMLDispatcher;
@@ -55,6 +56,7 @@
import org.apache.tapestry.ioc.annotations.Lifecycle;
import org.apache.tapestry.ioc.annotations.SubModule;
import org.apache.tapestry.ioc.services.ChainBuilder;
+import org.apache.tapestry.ioc.services.ClassFactory;
import org.apache.tapestry.ioc.services.PipelineBuilder;
import org.apache.tapestry.ioc.services.PropertyShadowBuilder;
@@ -364,5 +366,16 @@
public void contributeBindingSource(MappedConfiguration<String, BindingFactory> configuration)
{
configuration.add(InternalConstants.LITERAL_BINDING_PREFIX, new LiteralBindingFactory());
+ }
+
+ /**
+ * Returns a {@link ClassFactory} that can be used to create extra classes around component
+ * classes.
+ */
+ public ClassFactory buildComponentClassFactory(Log log,
+ @InjectService("tapestry.internal.ComponentInstantiatorSource")
+ ComponentInstantiatorSource source)
+ {
+ return new ComponentClassFactoryImpl(log, source);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/web.xml?rev=439787&r1=439786&r2=439787&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/web.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/WEB-INF/web.xml Sun Sep 3 08:13:50 2006
@@ -30,6 +30,6 @@
</filter>
<filter-mapping>
<filter-name>app</filter-name>
- <url-pattern>/</url-pattern>
+ <url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml?rev=439787&r1=439786&r2=439787&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/testng.xml Sun Sep 3 08:13:50 2006
@@ -36,4 +36,9 @@
<package name="org.apache.tapestry.internal.model"/>
</packages>
</test>
+ <test name="Integration">
+ <packages>
+ <package name="org.apache.tapestry.integration"/>
+ </packages>
+ </test>
</suite>
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/conf/webdefault.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/conf/webdefault.xml?rev=439787&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/conf/webdefault.xml (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/conf/webdefault.xml Sun Sep 3 08:13:50 2006
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Copyright 2006 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.
+-->
+
+<web-app
+ xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+ <description>
+ Default web.xml file.
+ This file is applied to a Web application before it's own WEB_INF/web.xml file
+ </description>
+
+
+
+ <!-- ==================================================================== -->
+ <!-- Context params to control Session Cookies -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- UNCOMMENT TO ACTIVATE
+ <context-param>
+ <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
+ <param-value>127.0.0.1</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
+ <param-value>/</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
+ <param-value>-1</param-value>
+ </context-param>
+ -->
+
+
+
+ <!-- ==================================================================== -->
+ <!-- The default servlet. -->
+ <!-- This servlet, normally mapped to /, provides the handling for static -->
+ <!-- content, OPTIONS and TRACE methods for the context. -->
+ <!-- The following initParameters are supported: -->
+ <!-- -->
+ <!-- acceptRanges If true, range requests and responses are -->
+ <!-- supported -->
+ <!-- -->
+ <!-- dirAllowed If true, directory listings are returned if no -->
+ <!-- welcome file is found. Else 403 Forbidden. -->
+ <!-- -->
+ <!-- putAllowed If true, the PUT method is allowed -->
+ <!-- -->
+ <!-- delAllowed If true, the DELETE method is allowed -->
+ <!-- -->
+ <!-- redirectWelcome If true, redirect welcome file requests -->
+ <!-- else use request dispatcher forwards -->
+ <!-- -->
+ <!-- minGzipLength If set to a positive integer, then static content -->
+ <!-- larger than this will be served as gzip content -->
+ <!-- encoded if a matching resource is found ending -->
+ <!-- with ".gz" -->
+ <!-- -->
+ <!-- resoureBase Can be set to replace the context resource base -->
+ <!-- -->
+ <!-- relativeResourceBase -->
+ <!-- Set with a pathname relative to the base of the -->
+ <!-- servlet context root. Useful for only serving -->
+ <!-- static content from only specific subdirectories. -->
+ <!-- -->
+ <!-- The MOVE method is allowed if PUT and DELETE are allowed -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.mortbay.jetty.servlet.Default</servlet-class>
+ <init-param>
+ <param-name>acceptRanges</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>dirAllowed</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>putAllowed</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>delAllowed</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectWelcome</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>minGzipLength</param-name>
+ <param-value>8192</param-value>
+ </init-param>
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+
+ <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
+
+ <!-- ==================================================================== -->
+ <session-config>
+ <session-timeout>30</session-timeout>
+ </session-config>
+
+
+ <!-- ==================================================================== -->
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ <welcome-file>index.htm</welcome-file>
+ </welcome-file-list>
+
+ <!-- ==================================================================== -->
+ <locale-encoding-mapping-list>
+ <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>
+ </locale-encoding-mapping-list>
+
+
+
+</web-app>
+
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=439787&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Sun Sep 3 08:13:50 2006
@@ -0,0 +1,108 @@
+// Copyright 2006 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.tapestry.integration;
+
+import org.openqa.selenium.server.SeleniumServer;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.thoughtworks.selenium.DefaultSelenium;
+import com.thoughtworks.selenium.Selenium;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+@Test(sequential = true, groups =
+{ "integration" })
+public class IntegrationTests extends Assert
+{
+ private Selenium _selenium;
+
+ private SeleniumServer _server;
+
+ private JettyRunner _jettyRunner;
+
+ public static final String BASE_URL = String.format(
+ "http://localhost:%d",
+ SeleniumServer.DEFAULT_PORT);
+
+ @BeforeClass
+ public void startupBackground() throws Exception
+ {
+ _jettyRunner = new JettyRunner("src/test/app1");
+
+ _server = new SeleniumServer();
+
+ _server.start();
+
+ }
+
+ @BeforeMethod
+ public void setupSelenium()
+ {
+ _selenium = new DefaultSelenium("localhost", SeleniumServer.DEFAULT_PORT, "*firefox",
+ "http://localhost");
+
+ _selenium.start();
+ }
+
+ @AfterMethod
+ public void shutdownSelenim()
+ {
+ _selenium.stop();
+ _selenium = null;
+ }
+
+ @AfterClass
+ public void shutdownBackground() throws Exception
+ {
+ // Thread.sleep(10000);
+
+ _server.stop();
+ _server = null;
+
+ _jettyRunner.stop();
+ _jettyRunner = null;
+ }
+
+ public static final String PAGE_LOAD_TIMEOUT = "1000";
+
+ @Test
+ public void app1_basic_output() throws Exception
+ {
+ _selenium.open("http://localhost/");
+
+ _selenium.click("link=Start Page");
+ _selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
+
+ // This comes from the Border cmponent's template
+
+ assertTrue(_selenium.getTitle().contains("Tapestry"));
+
+ // Text from Start.html
+
+ String body = _selenium.getBodyText();
+
+ assertTrue(body.contains("First Tapestry 5 Page"));
+
+ // This is text passed from Start.html to Output as a parameter
+
+ assertTrue(body.contains("we have basic parameters working"));
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/JettyRunner.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/JettyRunner.java?rev=439787&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/JettyRunner.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/JettyRunner.java Sun Sep 3 08:13:50 2006
@@ -0,0 +1,117 @@
+// Copyright 2006 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.tapestry.integration;
+
+import org.mortbay.http.NCSARequestLog;
+import org.mortbay.http.SocketListener;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.WebApplicationContext;
+
+import static java.lang.String.format;
+
+/**
+ * @author Howard M. Lewis Ship
+ */
+public class JettyRunner
+{
+ public static final String DEFAULT_CONTEXT_PATH = "/";
+
+ public static final int DEFAULT_PORT = 80;
+
+ private final String _contextPath;
+
+ private final int _port;
+
+ private final String _warPath;
+
+ private final Server _jetty;
+
+ public static void main(String[] args)
+ {
+ new JettyRunner("src/test/app1");
+ }
+
+ /** Defaults the context path to "/" and the port to 80. */
+ public JettyRunner(String warPath)
+ {
+ this(DEFAULT_CONTEXT_PATH, DEFAULT_PORT, warPath);
+ }
+
+ /**
+ * Creates and starts a new instance of Jetty. This should be done from a test case setup
+ * method.
+ *
+ * @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")
+ */
+ public JettyRunner(String contextPath, int port, String warPath)
+ {
+ _contextPath = contextPath;
+ _port = port;
+ _warPath = warPath;
+
+ _jetty = createAndStart();
+ }
+
+ /** Stops the Jetty instance. This should be called from a test case tear down method. */
+ public void stop()
+ {
+ try
+ {
+ _jetty.stop();
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException("Error stopping Jetty instance: " + ex.toString(), ex);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return format("<JettyRunner %s:%d (%s)>", _contextPath, _port, _warPath);
+ }
+
+ private Server createAndStart()
+ {
+ try
+ {
+ Server server = new Server();
+
+ SocketListener socketListener = new SocketListener();
+ socketListener.setPort(_port);
+ server.addListener(socketListener);
+
+ NCSARequestLog log = new NCSARequestLog();
+ server.setRequestLog(log);
+
+ WebApplicationContext context = server.addWebApplication(_contextPath, _warPath);
+
+ context.setDefaultsDescriptor("src/test/conf/webdefault.xml");
+
+ server.start();
+
+ return server;
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException("Failure starting Jetty instance: " + ex.toString(), ex);
+ }
+ }
+}