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

com.premiumminds.webapp.wicket.testing.ExtendedWicketTester Maven / Gradle / Ivy

/**
 * Copyright (C) 2016 Premium Minds.
 *
 * This file is part of pm-wicket-utils.
 *
 * pm-wicket-utils is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * pm-wicket-utils is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with pm-wicket-utils. If not, see .
 */
package com.premiumminds.webapp.wicket.testing;

import static junit.framework.Assert.fail;

import java.lang.reflect.Constructor;

import javax.servlet.ServletContext;

import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.markup.ContainerInfo;
import org.apache.wicket.markup.IMarkupFragment;
import org.apache.wicket.markup.Markup;
import org.apache.wicket.markup.MarkupParser;
import org.apache.wicket.markup.MarkupResourceStream;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.resource.StringResourceStream;
import org.apache.wicket.util.tester.WicketTester;

/**
 * A helper class to ease unit testing of Wicket form components without the need for a servlet
 * container. The class adds methods to start a component in a form, which have the same functionality as
 * {@link #startComponentInPage(Component)} and variants.
 */
public class ExtendedWicketTester extends WicketTester {
	private ComponentInForm componentInForm;

	/**
	 * Creates an ExtendedWicketTester and automatically creates a WebApplication,
	 * but the tester will have no home page.
	 */
	public ExtendedWicketTester()
	{
	}

	/**
	 * Creates an ExtendedWicketTester and automatically creates a WebApplication.
	 * 
	 * @param homePage
	 *            a home page Class
	 */
	public ExtendedWicketTester(final Class homePage)
	{
		super(homePage);
	}

	/**
	 * Creates an ExtendedWicketTester.
	 * 
	 * @param application
	 *            a WicketTester WebApplication object
	 */
	public ExtendedWicketTester(final WebApplication application)
	{
		super(application);
	}

	/**
	 * Creates an ExtendedWicketTester 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.mock.MockApplication#MockApplication()
	 */
	public ExtendedWicketTester(final WebApplication application, final String path)
	{
		super(application, path);
	}

	/**
	 * Creates an ExtendedWicketTester to help unit testing.
	 * 
	 * @param application
	 *            a WicketTester WebApplication object
	 * @param servletCtx
	 *            the servlet context used as backend
	 */
	public ExtendedWicketTester(WebApplication application, ServletContext servletCtx)
	{
		super(application, servletCtx);
	}

	/**
	 * Process a component. A web page will be automatically created with the markup created in
	 * {@link #createPageMarkup(String)}.
	 * 

* Note: the instantiated component will have an auto-generated id. To * reach any of its children use their relative path to the component itself. For example * if the started component has a child a Link component with id "link" then after starting * the component you can click it with: tester.clickLink("link") *

* * @param * the type of the component * @param componentClass * the class of the component to be tested * @param inputType * the type of HTML input to be associated with the component to be tested * @return The component processed * @see #startComponentInPage(org.apache.wicket.Component) */ public final C startComponentInForm(final Class componentClass, final String inputType) { return startComponentInForm(componentClass, inputType, null); } /** * Process a component. A web page will be automatically created with the {@code pageMarkup} * provided. In case pageMarkup is null, the markup will be automatically created with * {@link #createFormPageMarkup(String, String)}. *

* Note: the instantiated component will have an auto-generated id. To * reach any of its children use their relative path to the component itself. For example * if the started component has a child a Link component with id "link" then after starting * the component you can click it with: tester.clickLink("link") *

* * @param * the type of the component * * @param componentClass * the class of the component to be tested * @param inputType * the type of HTML input to be associated with the component to be tested * @param pageMarkup * the markup for the Page that will be automatically created. May be {@code null}. * @return The component processed */ @SuppressWarnings("deprecation") public final C startComponentInForm(final Class componentClass, final String inputType, final IMarkupFragment pageMarkup) { Args.notNull(componentClass, "componentClass"); // Create the component instance from the class C comp = null; try { Constructor c = componentClass.getConstructor(String.class); comp = c.newInstance(ComponentInForm.ID); componentInForm = new ComponentInForm(); componentInForm.component = comp; componentInForm.isInstantiated = true; } catch (Exception e) { fail(String.format("Cannot instantiate component with type '%s' because of '%s'", componentClass.getName(), e.getMessage())); } // process the component return startComponentInForm(comp, inputType, pageMarkup); } /** * Process a component. A web page will be automatically created with markup created by the * {@link #createFormPageMarkup(String, String)}. *

* Note: the component id is set by the user. To * reach any of its children use this id + their relative path to the component itself. For example * if the started component has id compId and a Link child component component with id "link" * then after starting the component you can click it with: tester.clickLink("compId:link") *

* * @param * the type of the component * @param component * the component to be tested * @param inputType * the type of HTML input to be associated with the component to be tested * @return The component processed * @see #startComponentInPage(Class) */ public final C startComponentInForm(final C component, final String inputType) { return startComponentInForm(component, inputType, null); } /** * Process a component. A web page will be automatically created with the {@code pageMarkup} * provided. In case {@code pageMarkup} is null, the markup will be automatically created with * {@link #createFormPageMarkup(String, String)}. *

* Note: the component id is set by the user. To * reach any of its children use this id + their relative path to the component itself. For example * if the started component has id compId and a Link child component component with id "link" * then after starting the component you can click it with: tester.clickLink("compId:link") *

* * @param * the type of the component * @param component * the component to be tested * @param inputType * the type of HTML input to be associated with the component to be tested * @param pageMarkup * the markup for the Page that will be automatically created. May be {@code null}. * @return The component processed */ @SuppressWarnings("deprecation") public final C startComponentInForm(final C component, final String inputType, IMarkupFragment pageMarkup) { Args.notNull(component, "component"); // Create a page object and assign the markup Page page = createFormPage(); if (page == null) { fail("The automatically created page should not be null."); } // Automatically create the page markup if not provided if (pageMarkup == null) { String markup = createFormPageMarkup(component.getId(), inputType); if (markup == null) { fail("The markup for the automatically created page should not be null."); } try { // set a ContainerInfo to be able to use HtmlHeaderContainer so header contribution // still work. WICKET-3700 ContainerInfo containerInfo = new ContainerInfo(page); MarkupResourceStream markupResourceStream = new MarkupResourceStream( new StringResourceStream(markup), containerInfo, page.getClass()); MarkupParser markupParser = getApplication().getMarkupSettings() .getMarkupFactory() .newMarkupParser(markupResourceStream); pageMarkup = markupParser.parse(); } catch (Exception e) { fail("Error while parsing the markup for the autogenerated page: " + e.getMessage()); } } if (page instanceof StartComponentInForm) { ((StartComponentInForm)page).setPageMarkup(pageMarkup); } else { page.setMarkup(pageMarkup); } // Add the child component Form form = new Form("form"); page.add(form); form.add(component); // Preserve 'componentInForm' because #startPage() needs to null-fy it ComponentInForm oldComponentInForm = componentInForm; // Process the page startPage(page); // Remember the "root" component processes and return it if (oldComponentInForm != null) { componentInForm = oldComponentInForm; } else { componentInForm = new ComponentInForm(); componentInForm.component = component; } return component; } /** * Creates the markup that will be used for the automatically created {@link Page} that will be * used to test a component with {@link #startComponentInPage(Class, IMarkupFragment)} * * @param componentId * the id of the component to be tested * @param inputType * the form input type ('text', 'checkbox', 'password', etc) * @return the markup for the {@link Page} as {@link String}. Cannot be {@code null}. */ protected String createFormPageMarkup(final String componentId, final String inputType) { return /*"" +*/ "
" /*+ ""*/; } /** * Creates a {@link Page} to test a component with * {@link #startComponentInForm(Component, String, IMarkupFragment)} * * @return a {@link Page} which will contain a form as a single child with the component under * test as a single input */ protected Page createFormPage() { return new StartComponentInForm(); } /** * A page that is used as the automatically created page for * {@link ExtendedWicketTester#startComponentInForm(Class, String)} and the other variations. *

* This page caches the generated markup so that it is available even after * {@link Component#detach()} where the {@link Component#markup component's markup cache} is * cleared. */ public static class StartComponentInForm extends WebPage { private static final long serialVersionUID = 1L; private transient IMarkupFragment pageMarkup = null; /** * Construct. */ public StartComponentInForm() { setStatelessHint(false); } @Override public IMarkupFragment getMarkup() { IMarkupFragment calculatedMarkup = null; if (pageMarkup == null) { IMarkupFragment markup = super.getMarkup(); if (markup != null && markup != Markup.NO_MARKUP) { calculatedMarkup = markup; pageMarkup = markup; } } else { calculatedMarkup = pageMarkup; } return calculatedMarkup; } public void setPageMarkup(IMarkupFragment markup) { setMarkup(markup); pageMarkup = markup; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy