You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by kn...@apache.org on 2009/11/16 14:07:15 UTC

svn commit: r880735 - in /wicket/trunk/wicket/src: main/java/org/apache/wicket/ng/ main/java/org/apache/wicket/ng/mock/ main/java/org/apache/wicket/ng/request/ test/java/org/apache/wicket/ng/request/ test/java/org/apache/wicket/ng/test/

Author: knopp
Date: Mon Nov 16 13:07:15 2009
New Revision: 880735

URL: http://svn.apache.org/viewvc?rev=880735&view=rev
Log:
Initial possible NG WicketTester implementation. 

Added:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/WicketTester.java   (with props)
    wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/test/TestWicketTester.java   (with props)
Removed:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockRenderPageRequestHandlerDelegate.java
Modified:
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/Session.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/request/UrlTest.java

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/Session.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/Session.java?rev=880735&r1=880734&r2=880735&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/Session.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/Session.java Mon Nov 16 13:07:15 2009
@@ -42,7 +42,8 @@
 
 	private Request getRequest()
 	{
-		return RequestCycle.get().getRequest();
+		RequestCycle cycle = RequestCycle.get();
+		return cycle != null ? cycle.getRequest() : null;
 	}
 
 	public void invalidateNow()

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java?rev=880735&r1=880734&r2=880735&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockApplication.java Mon Nov 16 13:07:15 2009
@@ -19,9 +19,11 @@
 import org.apache.wicket.ng.page.PageManager;
 import org.apache.wicket.ng.protocol.http.WebApplication;
 import org.apache.wicket.ng.request.component.RequestablePage;
+import org.apache.wicket.ng.request.cycle.RequestCycle;
 import org.apache.wicket.ng.request.cycle.RequestCycleContext;
 import org.apache.wicket.ng.request.handler.impl.RenderPageRequestHandler;
 import org.apache.wicket.ng.request.handler.impl.render.RenderPageRequestHandlerDelegate;
+import org.apache.wicket.ng.request.handler.impl.render.WebRenderPageRequestHandlerDelegate;
 import org.apache.wicket.ng.session.SessionStore;
 
 public class MockApplication extends WebApplication
@@ -59,12 +61,13 @@
 	public RenderPageRequestHandlerDelegate getRenderPageRequestHandlerDelegate(
 		RenderPageRequestHandler renderPageRequestHandler)
 	{
-		return new MockRenderPageRequestHandlerDelegate(renderPageRequestHandler)
+		return new WebRenderPageRequestHandlerDelegate(renderPageRequestHandler)
 		{
 			@Override
-			protected void onPageRender(RequestablePage page)
+			public void respond(RequestCycle requestCycle)
 			{
-				lastRenderedPage = page;
+				lastRenderedPage = getPageProvider().getPageInstance();
+				super.respond(requestCycle);
 			}
 		};
 	}

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java?rev=880735&r1=880734&r2=880735&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/MockPageManager.java Mon Nov 16 13:07:15 2009
@@ -17,23 +17,20 @@
 package org.apache.wicket.ng.mock;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.wicket.ng.page.ManageablePage;
 import org.apache.wicket.ng.page.PageManager;
 import org.apache.wicket.ng.page.PageManagerContext;
-import org.apache.wicket.ng.page.common.AbstractPageManager;
-import org.apache.wicket.ng.page.common.RequestAdapter;
 
 /**
  * Simple {@link PageManager} used for testing.
  * 
  * @author Matej Knopp
  */
-public class MockPageManager extends AbstractPageManager
+public class MockPageManager implements PageManager
 {
+	private final Map<Integer, ManageablePage> pages = new HashMap<Integer, ManageablePage>();
 
 	/**
 	 * Construct.
@@ -42,65 +39,39 @@
 	{
 	}
 
-	private final Map<String, Map<Integer, ManageablePage>> sessionMap = new ConcurrentHashMap<String, Map<Integer, ManageablePage>>();
+	public void commitRequest()
+	{
+	}
+
+	public void destroy()
+	{
+	}
 
-	private class MockRequestAdapter extends RequestAdapter
+	public ManageablePage getPage(int id)
 	{
-		public MockRequestAdapter(PageManagerContext context)
-		{
-			super(context);
-		}
-
-		@Override
-		protected ManageablePage getPage(int id)
-		{
-			Map<Integer, ManageablePage> pages = sessionMap.get(getSessionId());
-			return pages != null ? pages.get(id) : null;
-		}
-
-		@Override
-		protected void newSessionCreated()
-		{
-
-		}
-
-		@Override
-		protected void storeTouchedPages(List<ManageablePage> touchedPages)
-		{
-			bind();
-			Map<Integer, ManageablePage> pages = sessionMap.get(getSessionId());
-			if (pages == null)
-			{
-				pages = new HashMap<Integer, ManageablePage>();
-				sessionMap.put(getSessionId(), pages);
-			}
-			for (ManageablePage page : touchedPages)
-			{
-				pages.put(page.getPageId(), page);
-			}
-		}
-	};
+		return pages.get(id);
+	}
 
-	@Override
-	protected RequestAdapter newRequestAdapter(PageManagerContext context)
+	public void newSessionCreated()
 	{
-		return new MockRequestAdapter(context);
 	}
 
-	@Override
 	public void sessionExpired(String sessionId)
 	{
-		sessionMap.remove(sessionId);
 	}
 
-	@Override
+	public void setContext(PageManagerContext context)
+	{
+	}
+
 	public boolean supportsVersioning()
 	{
 		return false;
 	}
 
-	public void destroy()
+	public void touchPage(ManageablePage page)
 	{
-		sessionMap.clear();
+		pages.put(page.getPageId(), page);
 	}
+
 }

Added: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/WicketTester.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/WicketTester.java?rev=880735&view=auto
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/WicketTester.java (added)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/WicketTester.java Mon Nov 16 13:07:15 2009
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.ng.mock;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.wicket.ng.Component;
+import org.apache.wicket.ng.Page;
+import org.apache.wicket.ng.ThreadContext;
+import org.apache.wicket.ng.WicketRuntimeException;
+import org.apache.wicket.ng.request.RequestHandler;
+import org.apache.wicket.ng.request.RequestMapper;
+import org.apache.wicket.ng.request.Url;
+import org.apache.wicket.ng.request.cycle.RequestCycle;
+import org.apache.wicket.ng.request.handler.DefaultPageProvider;
+import org.apache.wicket.ng.request.handler.PageAndComponentProvider;
+import org.apache.wicket.ng.request.handler.PageProvider;
+import org.apache.wicket.ng.request.handler.impl.ListenerInterfaceRequestHandler;
+import org.apache.wicket.ng.request.handler.impl.RenderPageRequestHandler;
+import org.apache.wicket.ng.request.listener.RequestListenerInterface;
+import org.apache.wicket.ng.settings.RequestCycleSettings.RenderStrategy;
+
+/**
+ * Experimental implementation
+ * 
+ * @author Matej Knopp
+ */
+public class WicketTester
+{
+	private final MockApplication application;
+
+	private boolean followRedirects = true;
+
+	private MockWebRequest lastRequest;
+	private MockWebResponse lastResponse;
+
+	private final List<MockWebRequest> previousRequests = new ArrayList<MockWebRequest>();
+	private final List<MockWebResponse> previousResponses = new ArrayList<MockWebResponse>();
+
+	private final ThreadContext oldThreadContext;
+
+	/**
+	 * Creates a new {@link WicketTester} instance. It also binds it's Application to current thread
+	 * so all activities that needs the original application (if there was one bound to current
+	 * thread) need to wait until {@link #destroy()} is invoked.
+	 */
+	public WicketTester()
+	{
+		oldThreadContext = ThreadContext.getAndClean();
+
+		application = new MockApplication();
+		application.setName("WicketTesterApplication");
+		application.set();
+		application.initApplication();
+	}
+
+	/**
+	 * Destroys the tester. Restores {@link ThreadContext} to state before instance of
+	 * {@link WicketTester} was created.
+	 */
+	public void destroy()
+	{
+		ThreadContext.restore(oldThreadContext);
+		application.destroy();
+	}
+
+	int redirectCount;
+
+	/**
+	 * Processes the request in mocked Wicket environment.
+	 * 
+	 * @param request
+	 *            request to process
+	 * 
+	 * @param forcedRequestHandler
+	 *            optional parameter to override parsing the request URL and force
+	 *            {@link RequestHandler}
+	 */
+	public void processRequest(MockWebRequest request, RequestHandler forcedRequestHandler)
+	{
+		try
+		{
+			if (lastRequest != null)
+			{
+				previousRequests.add(lastRequest);
+			}
+			if (lastResponse != null)
+			{
+				previousResponses.add(lastResponse);
+			}
+
+			lastRequest = request;
+			lastResponse = new MockWebResponse();
+
+			MockRequestCycle cycle = (MockRequestCycle)application.createRequestCycle(request,
+				lastResponse);
+
+			if (forcedRequestHandler != null)
+			{
+				cycle.forceRequestHandler(forcedRequestHandler);
+			}
+
+			cycle.processRequestAndDetach();
+
+			if (followRedirects && lastResponse.isRedirect())
+			{
+				if (redirectCount == 100)
+				{
+					throw new IllegalStateException(
+						"Possible infinite redirect detected. Bailing out.");
+				}
+				++redirectCount;
+				Url newUrl = Url.parse(lastResponse.getRedirectUrl());
+				if (newUrl.isAbsolute())
+				{
+					throw new WicketRuntimeException("Can not follow absolute redirect URL.");
+				}
+
+				// append redirect URL to current URL (what browser would do)
+				Url mergedURL = new Url(request.getUrl().getSegments(), newUrl.getQueryParameters());
+				mergedURL.concatSegments(newUrl.getSegments());
+
+				processRequest(new MockWebRequest(mergedURL), null);
+
+				--redirectCount;
+			}
+		}
+		finally
+		{
+			redirectCount = 0;
+		}
+	}
+
+	/**
+	 * Renders the page specified by given {@link PageProvider}. After render the page instance can
+	 * be retreived using {@link #getLastRenderedPage()} and the rendered document will be available
+	 * in {@link #getLastResponse()}.
+	 * 
+	 * Depending on {@link RenderStrategy} invoking this method can mean that a redirect will happen
+	 * before the actual render.
+	 * 
+	 * @param pageProvider
+	 */
+	public void startPage(PageProvider pageProvider)
+	{
+		MockWebRequest request = new MockWebRequest(new Url());
+		RequestHandler handler = new RenderPageRequestHandler(pageProvider);
+		processRequest(request, handler);
+	}
+
+	/**
+	 * Renders the page.
+	 * 
+	 * @see #startPage(PageProvider)
+	 * 
+	 * @param page
+	 */
+	public void startPage(Page page)
+	{
+		startPage(new DefaultPageProvider(page));
+	}
+
+	/**
+	 * Simulates processing URL that invokes specified {@link RequestListenerInterface} on
+	 * component.
+	 * 
+	 * After the listener interface is invoked the page containing the component will be rendered
+	 * (with an optional redirect - depending on {@link RenderStrategy}).
+	 * 
+	 * @param component
+	 * @param listener
+	 */
+	public void executeListener(Component component, RequestListenerInterface listener)
+	{
+		// there are two ways to do this. RequestCycle could be forced to call the handler
+		// directly but constructing and parsing the URL increases the chance of triggering bugs
+		RequestHandler handler = new ListenerInterfaceRequestHandler(new PageAndComponentProvider(
+			component.getPage(), component), listener);
+
+		Url url = urlFor(handler);
+
+		processRequest(new MockWebRequest(url), null);
+	}
+
+	/**
+	 * @return last request or <code>null</code> if no request has happened yet.
+	 */
+	public MockWebRequest getLastRequest()
+	{
+		return lastRequest;
+	}
+
+	/**
+	 * @return last response or <code>null</code>> if no response has been produced yet.
+	 */
+	public MockWebResponse getLastResponse()
+	{
+		return lastResponse;
+	}
+
+	/**
+	 * @return list of prior requests
+	 */
+	public List<MockWebRequest> getPreviousRequests()
+	{
+		return Collections.unmodifiableList(previousRequests);
+	}
+
+	/**
+	 * @return list of prior responses
+	 */
+	public List<MockWebResponse> getPreviousResponses()
+	{
+		return Collections.unmodifiableList(previousResponses);
+	}
+
+	/**
+	 * @return last rendered page
+	 */
+	public Page getLastRenderedPage()
+	{
+		return (Page)application.getLastRenderedPage();
+	}
+
+	/**
+	 * Sets whether responses with redirects will be followed automatically.
+	 * 
+	 * @param followRedirects
+	 */
+	public void setFollowRedirects(boolean followRedirects)
+	{
+		this.followRedirects = followRedirects;
+	}
+
+	/**
+	 * @return <code>true</code> if redirect responses will be followed automatically,
+	 *         <code>false</code> otherwise.
+	 */
+	public boolean isFollowRedirects()
+	{
+		return followRedirects;
+	}
+
+	/**
+	 * Encodes the {@link RequestHandler} to {@link Url}. It should be safe to call this method
+	 * outside request thread as log as no registered {@link RequestMapper} requires a
+	 * {@link RequestCycle}.
+	 * 
+	 * @param handler
+	 * @return {@link Url} for handler.
+	 */
+	public Url urlFor(RequestHandler handler)
+	{
+		return application.getRootRequestMapper().mapHandler(handler);
+	}
+
+	/**
+	 * Returns the {@link MockApplication} for this environment.
+	 * 
+	 * @return application
+	 */
+	public MockApplication getApplication()
+	{
+		return application;
+	}
+}

Propchange: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/mock/WicketTester.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java?rev=880735&r1=880734&r2=880735&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/ng/request/Url.java Mon Nov 16 13:07:15 2009
@@ -29,7 +29,11 @@
 import org.apache.wicket.util.string.Strings;
 
 /**
- * Represents the URL part after Wicket Filter.
+ * Represents the URL part <b>after Wicket Filter</b>. For example if Wicket Filter is mapped to
+ * <code>/app/*</code> then with URL <code>/app/my/url</code> the {@link Url} object would represent
+ * part <code>my/url</code>. If Wicket Filter is mapped to <code>/*</code> then with URL
+ * <code>/my/url</code> the {@link Url} object would represent <code>my/url</code> (without leading
+ * the slash).
  * <p>
  * URL consists of segments and query parameters.
  * <p>
@@ -46,8 +50,7 @@
  *                                                an additional slash, i.e. //
  * </pre>
  * 
- * The Url class takes care of encoding and decoding of the segments and
- * parameters.
+ * The Url class takes care of encoding and decoding of the segments and parameters.
  * 
  * @author Matej Knopp
  * @author Igor Vaynberg
@@ -119,8 +122,7 @@
 	/**
 	 * Returns whether the URL is absolute.
 	 * 
-	 * @return <code>true</code> if URL is absolute, <code>false</code>
-	 *         otherwise.
+	 * @return <code>true</code> if URL is absolute, <code>false</code> otherwise.
 	 */
 	public boolean isAbsolute()
 	{
@@ -160,8 +162,7 @@
 	}
 
 	/**
-	 * Convenience method that prepends <code>segments</code> to the segments
-	 * collection
+	 * Convenience method that prepends <code>segments</code> to the segments collection
 	 * 
 	 * @param newSegments
 	 */
@@ -172,8 +173,8 @@
 	}
 
 	/**
-	 * Convenience method that removes all query parameters with given name and
-	 * adds new query parameter with specified name and value
+	 * Convenience method that removes all query parameters with given name and adds new query
+	 * parameter with specified name and value
 	 * 
 	 * @param name
 	 * @param value
@@ -189,8 +190,8 @@
 	}
 
 	/**
-	 * Returns first query parameter with specified name or null if such query
-	 * parameter doesn't exist.
+	 * Returns first query parameter with specified name or null if such query parameter doesn't
+	 * exist.
 	 * 
 	 * @param name
 	 * @return query parameter or <code>null</code>
@@ -208,9 +209,8 @@
 	}
 
 	/**
-	 * Returns the value of first query parameter with specified name. Note that
-	 * this method never returns <code>null</code>. Not even if the parameter
-	 * does not exist.
+	 * Returns the value of first query parameter with specified name. Note that this method never
+	 * returns <code>null</code>. Not even if the parameter does not exist.
 	 * 
 	 * @see StringValue#isNull()
 	 * 
@@ -241,9 +241,8 @@
 		private final String value;
 
 		/**
-		 * Creates new {@link QueryParameter} instance. The <code>name</code>
-		 * and <code>value</code> parameters must not be <code>null</code>,
-		 * though they can be empty strings.
+		 * Creates new {@link QueryParameter} instance. The <code>name</code> and <code>value</code>
+		 * parameters must not be <code>null</code>, though they can be empty strings.
 		 * 
 		 * @param name
 		 *            parameter name
@@ -291,8 +290,8 @@
 				return false;
 			}
 			QueryParameter rhs = (QueryParameter)obj;
-			return Objects.equal(getName(), rhs.getName())
-					&& Objects.equal(getValue(), rhs.getValue());
+			return Objects.equal(getName(), rhs.getName()) &&
+				Objects.equal(getValue(), rhs.getValue());
 		}
 
 		@Override
@@ -328,8 +327,8 @@
 		}
 		Url rhs = (Url)obj;
 
-		return getSegments().equals(rhs.getSegments())
-				&& getQueryParameters().equals(rhs.getQueryParameters());
+		return getSegments().equals(rhs.getSegments()) &&
+			getQueryParameters().equals(rhs.getQueryParameters());
 	}
 
 	@Override
@@ -481,4 +480,58 @@
 
 		return result;
 	};
+
+	private boolean isLastSegmentReal()
+	{
+		if (segments.isEmpty())
+		{
+			return false;
+		}
+		String last = segments.get(segments.size() - 1);
+		return last.length() > 0 && !".".equals(last) && !"..".equals(last);
+	}
+
+	private boolean isLastSegmentEmpty()
+	{
+		if (segments.isEmpty())
+		{
+			return false;
+		}
+		String last = segments.get(segments.size() - 1);
+		return last.length() == 0;
+	}
+
+	/**
+	 * Concatenate the specified segments; The segments can be relative - begin with "." or "..".
+	 * 
+	 * @param segments
+	 */
+	public void concatSegments(List<String> segments)
+	{
+		boolean checkedLastSegment = false;
+
+		for (String s : segments)
+		{
+			if (".".equals(s))
+			{
+				continue;
+			}
+			else if ("..".equals(s) && isLastSegmentReal())
+			{
+				this.segments.remove(this.segments.size() - 1);
+			}
+			else
+			{
+				if (!checkedLastSegment)
+				{
+					if (isLastSegmentReal() || isLastSegmentEmpty())
+					{
+						this.segments.remove(this.segments.size() - 1);
+					}
+					checkedLastSegment = true;
+				}
+				this.segments.add(s);
+			}
+		}
+	}
 }

Modified: wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/request/UrlTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/request/UrlTest.java?rev=880735&r1=880734&r2=880735&view=diff
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/request/UrlTest.java (original)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/request/UrlTest.java Mon Nov 16 13:07:15 2009
@@ -125,7 +125,7 @@
 		checkSegments(url);
 		checkQueryParams(url, "a", "b");
 	}
-	
+
 	/**
 	 * 
 	 */
@@ -136,7 +136,7 @@
 		checkSegments(url, "", "");
 		checkQueryParams(url);
 	}
-	
+
 	/**
 	 * 
 	 */
@@ -173,7 +173,7 @@
 		Url url = Url.parse(s);
 		assertEquals(url.toString(), s);
 	}
-	
+
 	/**
 	 * 
 	 */
@@ -183,7 +183,7 @@
 		Url url = Url.parse(s);
 		assertEquals(url.toString(), s);
 	}
-	
+
 	/**
 	 * 
 	 */
@@ -202,7 +202,7 @@
 		Url url = Url.parse("abc/efg");
 		assertFalse(url.isAbsolute());
 	}
-	
+
 	/**
 	 * 
 	 */
@@ -211,7 +211,7 @@
 		Url url = Url.parse("");
 		assertFalse(url.isAbsolute());
 	}
-	
+
 	/**
 	 * 
 	 */
@@ -220,7 +220,7 @@
 		Url url = Url.parse("/");
 		assertTrue(url.isAbsolute());
 	}
-	
+
 	/**
 	 * 
 	 */
@@ -230,4 +230,53 @@
 		assertTrue(url.isAbsolute());
 	}
 
+	/**
+	 * 
+	 */
+	public void testConcat1()
+	{
+		Url url = Url.parse("abc/efg");
+		url.concatSegments(Arrays.asList("xx", "yy"));
+		assertEquals(Url.parse("abc/xx/yy"), url);
+	}
+
+	/**
+	 * 
+	 */
+	public void testConcat2()
+	{
+		Url url = Url.parse("abc/efg");
+		url.concatSegments(Arrays.asList(".", "..", "xx", "yy"));
+		assertEquals(Url.parse("xx/yy"), url);
+	}
+
+	/**
+	 * 
+	 */
+	public void testConcat3()
+	{
+		Url url = Url.parse("abc/efg");
+		url.concatSegments(Arrays.asList("..", "..", "xx", "yy"));
+		assertEquals(Url.parse("xx/yy"), url);
+	}
+
+	/**
+	 * 
+	 */
+	public void testConcat4()
+	{
+		Url url = Url.parse("abc/efg");
+		url.concatSegments(Arrays.asList("..", "..", "..", "xx", "yy"));
+		assertEquals(Url.parse("../xx/yy"), url);
+	}
+
+	/**
+	 * 
+	 */
+	public void testConcat5()
+	{
+		Url url = Url.parse("abc/efg/");
+		url.concatSegments(Arrays.asList("xx", "yy"));
+		assertEquals(Url.parse("abc/efg/xx/yy"), url);
+	}
 }

Added: wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/test/TestWicketTester.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/test/TestWicketTester.java?rev=880735&view=auto
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/test/TestWicketTester.java (added)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/test/TestWicketTester.java Mon Nov 16 13:07:15 2009
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.ng.test;
+
+import junit.framework.TestCase;
+
+import org.apache.wicket.ng.Component;
+import org.apache.wicket.ng.Page;
+import org.apache.wicket.ng.markup.html.link.ILinkListener;
+import org.apache.wicket.ng.markup.html.link.Link;
+import org.apache.wicket.ng.mock.WicketTester;
+
+
+public class TestWicketTester extends TestCase
+{
+	public static class Page1 extends Page
+	{
+		private static final long serialVersionUID = 1L;
+
+		public Page1()
+		{
+			Link l;
+			add(l = new Link("link")
+			{
+				private static final long serialVersionUID = 1L;
+
+				public void onLinkClicked()
+				{
+					System.out.println("Link clicked!");
+				}
+			});
+			l.setLabel("A Link!");
+		}
+
+		@Override
+		public void renderPage()
+		{
+			super.renderPage();
+		}
+	};
+
+	public void testPageRender1()
+	{
+		WicketTester tester = new WicketTester();
+
+		tester.startPage(new Page1());
+
+		System.out.println(tester.getLastResponse().getTextResponse());
+
+		Component c = tester.getLastRenderedPage().get("link");
+
+		tester.executeListener(c, ILinkListener.INTERFACE);
+
+		tester.destroy();
+	}
+}

Propchange: wicket/trunk/wicket/src/test/java/org/apache/wicket/ng/test/TestWicketTester.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain