All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wicket.util.tester.WicketTester Maven / Gradle / Ivy

Go to download

Pax Wicket Service is an OSGi extension of the Wicket framework, allowing for dynamic loading and unloading of Wicket components and pageSources.

There is a newer version: 5.0.0
Show newest version
/*
 * 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.util.tester;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import junit.framework.Assert;
import junit.framework.AssertionFailedError;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.feedback.IFeedback;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.protocol.http.HttpSessionStore;
import org.apache.wicket.protocol.http.MockHttpServletResponse;
import org.apache.wicket.protocol.http.SecondLevelCacheSessionStore;
import org.apache.wicket.protocol.http.SecondLevelCacheSessionStore.IPageStore;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.session.ISessionStore;
import org.apache.wicket.util.diff.DiffUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A helper class to ease unit testing of Wicket applications without the need for a servlet
 * container. To start a test, either use startPage or startPanel:
 * 
 * 
 * // production page
 * public class MyPage extends WebPage
 * {
 * 	public MyPage()
 * 	{
 * 		add(new Label("myMessage", "Hello!"));
 * 		add(new Link("toYourPage")
 * 		{
 * 			public void onClick()
 * 			{
 * 				setResponsePage(new YourPage("Hi!"));
 * 			}
 * 		});
 * 	}
 * }
 * 
* *
 * // test code
 * private WicketTester tester;
 * 
 * public void setUp()
 * {
 * 	tester = new WicketTester();
 * }
 * 
 * public void testRenderMyPage()
 * {
 * 	// start and render the test page
 * 	tester.startPage(MyPage.class);
 * 	// assert rendered page class
 * 	tester.assertRenderedPage(MyPage.class);
 * 	// assert rendered label component
 * 	tester.assertLabel("myMessage", "Hello!");
 * }
 * 
* * The above example is straight forward: start MyPage.class and assert * Label it rendered. Next, we try to navigate through a Link: * *
 * // production page
 * public class YourPage extends WebPage
 * {
 * 	public YourPage(String message)
 * 	{
 * 		add(new Label("yourMessage", message));
 * 		info("Wicket Rocks ;-)");
 * 	}
 * }
 * 
 * // test code
 * public void testLinkToYourPage()
 * {
 * 	tester.startPage(MyPage.class);
 * 	// click link and render
 * 	tester.clickLink("toYourPage");
 * 	tester.assertRenderedPage(YourPage.class);
 * 	tester.assertLabel("yourMessage", "Hi!");
 * }
 * 
* * tester.clickLink(path); will simulate user click on the component (in this case, * it's a Link) and render the response page YourPage. Ok, unit test of * MyPage is completed. Now we test YourPage standalone: * *
 * // test code
 * public void testRenderYourPage()
 * {
 * 	// provide page instance source for WicketTester
 * 	tester.startPage(new TestPageSource()
 * 	{
 * 		public Page getTestPage()
 * 		{
 * 			return new YourPage("mock message");
 * 		}
 * 	});
 * 	tester.assertRenderedPage(YourPage.class);
 * 	tester.assertLabel("yourMessage", "mock message");
 * 	// assert feedback messages in INFO Level
 * 	tester.assertInfoMessages(new String[] { "Wicket Rocks ;-)" });
 * }
 * 
* * Instead of tester.startPage(pageClass), we define a * {@link org.apache.wicket.util.tester.ITestPageSource} to provide testing page instance for * WicketTester. This is necessary because YourPage uses a custom * constructor, which is very common for transferring model data, but cannot be instantiated by * reflection. Finally, we use assertInfoMessages to assert there is a feedback message * "Wicket Rocks ;-)" at the INFO level. * * Many methods require a 'path' parameter. E.g. the page relative path can be obtained via * {@link Component#getPageRelativePath()}. Since each Component has an ID/name, any Component can * also be referenced by its ID {@link MarkupContainer#get(String)}. And since MarkupContainer's and * its subclasses are containers which allow to add Components (in sync with the markup hierarchy), * you may not only access direct childs but also subchilds like get("myPanel:myForm:myNameField") * separating each ID with a ':'. * * TODO General: Example usage of FormTester * * @author Ingram Chen * @author Juergen Donnerstag * @author Frank Bille * @since 1.2.6 */ public class WicketTester extends BaseWicketTester { /** * Default dummy web application for testing. Uses {@link HttpSessionStore} to store pages and * the Session. */ public static class DummyWebApplication extends WebApplication { /** * @see org.apache.wicket.Application#getHomePage() */ @Override public Class getHomePage() { return DummyHomePage.class; } @Override protected ISessionStore newSessionStore() { // Don't use a filestore, or we spawn lots of threads, which makes // things slow. return new HttpSessionStore(this); } /** * @see org.apache.wicket.protocol.http.WebApplication#newWebResponse(javax.servlet.http.HttpServletResponse) */ @Override protected WebResponse newWebResponse(final HttpServletResponse servletResponse) { return new WebResponse(servletResponse); } @Override protected void outputDevelopmentModeWarning() { // do nothing } } /** * Dummy web application that does not support back button support but is cheaper to use for * unit tests. Uses {@link SecondLevelCacheSessionStore} with a noop {@link IPageStore}. */ public static class NonPageCachingDummyWebApplication extends DummyWebApplication { @Override protected ISessionStore newSessionStore() { return new SecondLevelCacheSessionStore(this, new IPageStore() { public void destroy() { } public Page getPage(String sessionId, String pagemap, int id, int versionNumber, int ajaxVersionNumber) { return null; } public void pageAccessed(String sessionId, Page page) { } public void removePage(String sessionId, String pagemap, int id) { } public void storePage(String sessionId, Page page) { } public void unbind(String sessionId) { } public boolean containsPage(String sessionId, String pageMapName, int pageId, int pageVersion) { return false; } }); } } /** log. */ private static final Logger log = LoggerFactory.getLogger(WicketTester.class); /** * Creates a WicketTester and automatically creates a WebApplication, * but the tester will have no home page. */ public WicketTester() { this(new DummyWebApplication()); } /** * Creates a WicketTester and automatically creates a WebApplication. * * @param homePage * a home page Class */ public WicketTester(final Class homePage) { this(new WebApplication() { /** * @see org.apache.wicket.Application#getHomePage() */ @Override public Class getHomePage() { return homePage; } @Override protected ISessionStore newSessionStore() { // Don't use a filestore, or we spawn lots of threads, which // makes things slow. return new HttpSessionStore(this); } @Override protected WebResponse newWebResponse(final HttpServletResponse servletResponse) { return new WebResponse(servletResponse); } @Override protected void outputDevelopmentModeWarning() { // Do nothing. } }); } /** * Creates a WicketTester. * * @param application * a WicketTester WebApplication object */ public WicketTester(final WebApplication application) { this(application, null); } /** * Creates a WicketTester to help unit testing. * * @param application * a WicketTester WebApplication object * @param path * the absolute path on disk to the web application's contents (e.g. war root) - may * be null * * @see org.apache.wicket.protocol.http.MockWebApplication#MockWebApplication(org.apache.wicket.protocol.http.WebApplication, * String) */ public WicketTester(final WebApplication application, final String path) { super(application, path); } /** * Asserts that the Ajax location header is present. */ public void assertAjaxLocation() { if (null != ((MockHttpServletResponse)getWicketResponse().getHttpServletResponse()).getRedirectLocation()) { throw new AssertionFailedError( "Location header should *not* be present when using Ajax"); } String ajaxLocation = ((MockHttpServletResponse)getWicketResponse().getHttpServletResponse()).getHeader("Ajax-Location"); if (null == ajaxLocation) { throw new AssertionFailedError("Ajax-Location header should be present when using Ajax"); } int statusCode = ((MockHttpServletResponse)getWicketResponse().getHttpServletResponse()).getStatus(); if (statusCode != 200) { throw new AssertionFailedError("Expected HTTP status code to be 200 (OK)"); } } /** * Asserts a Component class. * * @param path * path to Component * @param expectedComponentClass * expected Component class */ public void assertComponent(String path, Class expectedComponentClass) { assertResult(isComponent(path, expectedComponentClass)); } /** * Tests that a Component has been added to a AjaxRequestTarget, using * {@link AjaxRequestTarget#addComponent(Component)}. This method actually tests that a * Component is on the Ajax response sent back to the client. *

* PLEASE NOTE! This method doesn't actually insert the Component in the client DOM * tree, using Javascript. But it shouldn't be needed because you just have to trust that Wicket * Ajax Javascript works. * * @param component * a Component to be tested */ public void assertComponentOnAjaxResponse(Component component) { Result result = isComponentOnAjaxResponse(component); assertResult(result); } /** * Tests that a Component has been added to a AjaxRequestTarget, using * {@link AjaxRequestTarget#addComponent(Component)}. This method actually tests that a * Component is on the Ajax response sent back to the client. *

* PLEASE NOTE! This method doesn't actually insert the Component in the client DOM * tree, using Javascript. But it shouldn't be needed because you just have to trust that Wicket * Ajax Javascript works. * * @param componentPath * a Component path to test */ public void assertComponentOnAjaxResponse(String componentPath) { assertComponentOnAjaxResponse(getComponentFromLastRenderedPage(componentPath)); } /** * Asserts the content of last rendered page contains (matches) a given regex pattern. * * @param pattern * a reqex pattern to match */ public void assertContains(String pattern) { assertResult(ifContains(pattern)); } /** * The opposite of {@link #assertContains(String)}. * * @param pattern * pattern */ public void assertContainsNot(String pattern) { assertResult(ifContainsNot(pattern)); } /** * Asserts error-level feedback messages. * * @param expectedErrorMessages * expected error messages */ public void assertErrorMessages(String[] expectedErrorMessages) { List actualMessages = getMessages(FeedbackMessage.ERROR); List msgs = new ArrayList(); for (Iterator iterator = actualMessages.iterator(); iterator.hasNext();) { msgs.add(iterator.next().toString()); } WicketTesterHelper.assertEquals(Arrays.asList(expectedErrorMessages), msgs); } /** * Assert info-level feedback messages. * * @param expectedInfoMessages * expected info messages */ public void assertInfoMessages(String[] expectedInfoMessages) { List actualMessages = getMessages(FeedbackMessage.INFO); WicketTesterHelper.assertEquals(Arrays.asList(expectedInfoMessages), actualMessages); } /** * Assert that a particular feedback panel is rendering certain messages. * * NOTE: this casts the component at the specified path to a {@link FeedbackPanel}, so it will * not work with custom {@link IFeedback} implementations unless you are subclassing * {@link FeedbackPanel} * * @param path * path to the feedback panel * @param messages * messages expected to be rendered */ public void assertFeedback(String path, String[] messages) { final FeedbackPanel fbp = (FeedbackPanel)getComponentFromLastRenderedPage(path); final IModel> model = fbp.getFeedbackMessagesModel(); final List renderedMessages = model.getObject(); if (renderedMessages == null) { fail("feedback panel at path [" + path + "] returned null messages"); } if (messages.length != renderedMessages.size()) { fail("you expected " + messages.length + " messages for the feedback panel [" + path + "], but there were actually " + renderedMessages.size()); } for (int i = 0; i < messages.length && i < renderedMessages.size(); i++) { final String expected = messages[i]; final String actual = renderedMessages.get(i).getMessage().toString(); assertResult(isEqual(expected, actual)); } } /** * Asserts that a Component is invisible. * * @param path * path to Component */ public void assertInvisible(String path) { assertResult(isInvisible(path)); } /** * Asserts the text of a Label Component. * * @param path * path to Label Component * @param expectedLabelText * expected text of the Label */ public void assertLabel(String path, String expectedLabelText) { Label label = (Label)getComponentFromLastRenderedPage(path); Assert.assertEquals(expectedLabelText, label.getDefaultModelObjectAsString()); } /** * Asserts the model value of a component. * * @param path * path to the component on the page * @param expectedValue * expected value of the component's model */ public void assertModelValue(String path, Object expectedValue) { Component component = getComponentFromLastRenderedPage(path); Assert.assertEquals(expectedValue, component.getDefaultModelObject()); } /** * Asserts the model of a {@link ListView}. * * @param path * path to a {@link ListView} Component * @param expectedList * expected List in the model of the given {@link ListView} */ @Override public void assertListView(String path, List expectedList) { ListView listView = (ListView)getComponentFromLastRenderedPage(path); WicketTesterHelper.assertEquals(expectedList, listView.getList()); } /** * Asserts no error-level feedback messages. */ public void assertNoErrorMessage() { List messages = getMessages(FeedbackMessage.ERROR); Assert.assertTrue( "expect no error message, but contains\n" + WicketTesterHelper.asLined(messages), messages.isEmpty()); } /** * Asserts no info-level feedback messages. */ public void assertNoInfoMessage() { List messages = getMessages(FeedbackMessage.INFO); Assert.assertTrue( "expect no info message, but contains\n" + WicketTesterHelper.asLined(messages), messages.isEmpty()); } /** * Asserts a PageLink link to a Page class. * * @param path * path to PageLink Component * @param expectedPageClass * expected Page class to link */ public void assertPageLink(String path, Class expectedPageClass) { assertResult(isPageLink(path, expectedPageClass)); } /** * Asserts that that the BookmarkablePageLink identified by "id" points to the page as expected * - including parameters. * * @param id * @param pageClass * @param parameters */ public void assertBookmarkablePageLink(final String id, final Class pageClass, final String parameters) { BookmarkablePageLink pageLink = null; try { pageLink = (BookmarkablePageLink)getComponentFromLastRenderedPage(id); } catch (ClassCastException e) { throw new IllegalArgumentException("Component with id:" + id + " is not a BookmarkablePageLink"); } Assert.assertEquals("BookmarkablePageLink: " + id + " is pointing to the wrong page", pageClass, pageLink.getPageClass()); Assert.assertEquals( "One or more of the parameters associated with the BookmarkablePageLink: " + id + " do not match", new PageParameters(parameters), pageLink.getPageParameters()); } /** * Asserts a last-rendered Page class. * * @param expectedRenderedPageClass * expected class of last rendered Page */ public void assertRenderedPage(Class expectedRenderedPageClass) { assertResult(isRenderedPage(expectedRenderedPageClass)); } /** * Asserts last-rendered Page against an expected HTML document. *

* Use -Dwicket.replace.expected.results=true to automatically replace the expected * output file. * * @param clazz * Class used to load the file (relative to clazz package) * @param filename * expected output filename String * @throws Exception */ @Override public void assertResultPage(final Class clazz, final String filename) throws Exception { String document = getServletResponse().getDocument(); DiffUtil.validatePage(document, clazz, filename, true); } /** * Asserts last-rendered Page against an expected HTML document as a * String * * @param expectedDocument * expected output String * @throws Exception */ public void assertResultPage(final String expectedDocument) throws Exception { // Validate the document String document = getServletResponse().getDocument(); Assert.assertEquals(expectedDocument, document); } /** * Asserts that a Component is visible. * * @param path * path to a Component */ public void assertVisible(String path) { assertResult(isVisible(path)); } /** * assert component is enabled. * * @param path * path to component * */ public void assertEnabled(String path) { assertResult(isEnabled(path)); } /** * assert component is enabled. * * @param path * path to component */ public void assertDisabled(String path) { assertResult(isDisabled(path)); } /** * assert form component is required. * * @param path * path to form component */ public void assertRequired(String path) { assertResult(isRequired(path)); } private void assertResult(Result result) { if (result.wasFailed()) { throw new AssertionFailedError(result.getMessage()); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy