///////////////////////////////////////////////////////////////////////////// // // Project ProjectForge Community Edition // www.projectforge.org // // Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de) // // ProjectForge is dual-licensed. // // This community edition is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 3 of the License. // // This community edition 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 General // Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, see http://www.gnu.org/licenses/. // ///////////////////////////////////////////////////////////////////////////// package org.projectforge.web.wicket; import java.util.MissingResourceException; import org.apache.commons.lang.ClassUtils; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.Page; import org.apache.wicket.Session; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.form.LabeledWebMarkupContainer; import org.apache.wicket.markup.html.link.AbstractLink; import org.apache.wicket.model.IModel; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.request.Request; import org.apache.wicket.request.Response; import org.apache.wicket.resource.loader.BundleStringResourceLoader; import org.apache.wicket.spring.injection.annot.SpringComponentInjector; import org.apache.wicket.util.tester.FormTester; import org.apache.wicket.util.tester.WicketTester; import org.apache.wicket.util.visit.IVisit; import org.apache.wicket.util.visit.IVisitor; import org.junit.Before; import org.projectforge.test.TestBase; import org.projectforge.user.UserXmlPreferencesCache; import org.projectforge.web.LoginPage; import org.projectforge.web.MenuBuilder; import org.projectforge.web.wicket.components.ContentMenuEntryPanel; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Your wicket tester class must extends this or any derived class from TestBase for correct initialization of Spring, data-base, resource * locator etc. Before your tests a new data-base is initialized and set-up with test data. * @author Kai Reinhard (k.reinhard@micromata.de) * */ public class WicketPageTestBase extends TestBase { protected static final String KEY_LOGINPAGE_BUTTON_LOGIN = "loginButton:button"; protected WicketTester tester; protected MenuBuilder menuBuilder; private UserXmlPreferencesCache userXmlPreferencesCache; private class WicketTestApplication extends WebApplication implements WicketApplicationInterface { @Override protected void init() { super.init(); final ClassPathXmlApplicationContext context = getTestConfiguration().getApplicationContext(); getComponentInstantiationListeners().add(new SpringComponentInjector(this, context, true)); getResourceSettings().getStringResourceLoaders().add(new BundleStringResourceLoader(WicketApplication.RESOURCE_BUNDLE_NAME)); final ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false); UserXmlPreferencesCache.setInternalInstance(userXmlPreferencesCache); } @Override public Class< ? extends Page> getHomePage() { return WicketUtils.getDefaultPage(); } @Override public Session newSession(final Request request, final Response response) { return new MySession(request); } /** * @see org.projectforge.web.wicket.WicketApplicationInterface#isDevelopmentSystem() */ @Override public boolean isDevelopmentSystem() { return false; } /** * @see org.projectforge.web.wicket.WicketApplicationInterface#isStripWicketTags() */ @Override public boolean isStripWicketTags() { return true; } }; @Before public void setUpWicketApplication() { tester = new WicketTester(new WicketTestApplication()); } /** * Logs the user in, if not already logged-in. If an user is already logged in then nothing is done. Therefore you must log-out an user * before any new login. * @param username * @param password not encrypted. */ public void login(final String username, final String password) { login(username, password, true); } /** * Logs the user in, if not already logged-in. If an user is already logged in then nothing is done. Therefore you must log-out an user * before any new login. * @param username * @param password not encrypted. */ public void login(final String username, final String password, final boolean checkDefaultPage) { // start and render the test page tester.startPage(LoginPage.class); if (ClassUtils.isAssignable(tester.getLastRenderedPage().getClass(), WicketUtils.getDefaultPage()) == true) { // Already logged-in. return; } // assert rendered page class tester.assertRenderedPage(LoginPage.class); final FormTester form = tester.newFormTester("body:form"); form.setValue(findComponentByLabel(form, "username"), username); form.setValue(findComponentByLabel(form, "password"), password); form.submit(KEY_LOGINPAGE_BUTTON_LOGIN); if (checkDefaultPage == true) { tester.assertRenderedPage(WicketUtils.getDefaultPage()); } } public void loginTestAdmin() { login(TestBase.TEST_ADMIN_USER, TestBase.TEST_ADMIN_USER_PASSWORD); } /** * Searches FormComponents (model object), LabeledWebmarkupContainers (label model) and ContentMenuEntryPanels (label). * @param container * @param label i18n key of the label or label (for buttons). * @return Found component with the given label or null if no such component found. * @see FormComponent#getModelObject() * @see LabeledWebMarkupContainer#getLabel() * @see ContentMenuEntryPanel#getLabel() */ public Component findComponentByLabel(final MarkupContainer container, final String label) { String str = label; try { str = container.getString(label); } catch (final MissingResourceException ex) { // OK } final String locLabel = str; final Component[] component = new Component[1]; container.visitChildren(new IVisitor<Component, Void>() { @Override public void component(final Component object, final IVisit<Void> visit) { if (object instanceof AbstractLink) { final MarkupContainer parent = object.getParent(); if (parent instanceof ContentMenuEntryPanel) { if (labelEquals(((ContentMenuEntryPanel) parent).getLabel(), label, locLabel) == true) { component[0] = object; visit.stop(); } } else if (object.getId().equals(locLabel) == true) { component[0] = object; visit.stop(); } } else { if (object instanceof LabeledWebMarkupContainer) { final IModel<String> labelModel = ((LabeledWebMarkupContainer) object).getLabel(); if (labelModel != null) { if (labelEquals(labelModel.getObject(), label, locLabel) == true) { component[0] = object; visit.stop(); } } } if (object instanceof FormComponent< ? >) { final Object modelObject = ((FormComponent< ? >) object).getModelObject(); if (modelObject instanceof String) { if (labelEquals((String) modelObject, label, locLabel) == true) { component[0] = object; visit.stop(); } } } } } }); return component[0]; } /** * Searches ContentMenuEntryPanels. * @param container * @param accessKey * @return Found component with the given label or null if no such component found. * @see FormComponent#getModelObject() * @see LabeledWebMarkupContainer#getLabel() * @see ContentMenuEntryPanel#getLabel() */ public Component findComponentByAccessKey(final MarkupContainer container, final char accessKey) { final Component[] component = new Component[1]; container.visitChildren(new IVisitor<Component, Void>() { @Override public void component(final Component object, final IVisit<Void> visit) { if (object instanceof AbstractLink) { final AbstractLink link = (AbstractLink) object; final AttributeModifier attrMod = WicketUtils.getAttributeModifier(link, "accesskey"); if (attrMod == null || attrMod.toString().contains("object=[n]") == false) { return; } component[0] = object; visit.stop(); } } }); return component[0]; } private boolean labelEquals(final String label, final String l1, final String l2) { if (label == null) { return false; } return l1 != null && label.equals(l1) == true || l2 != null && label.equals(l2) == true; } public Component findComponentByLabel(final FormTester form, final String label) { return findComponentByLabel(form.getForm(), label); } /** * * @param tester WicketTester with the last rendered page. * @param containerPath path of the container to search in. * @param label * @see #findComponentByLabel(MarkupContainer, String) */ public Component findComponentByLabel(final WicketTester tester, final String containerPath, final String label) { return findComponentByLabel((MarkupContainer) tester.getComponentFromLastRenderedPage(containerPath), label); } /** * * @param tester WicketTester with the last rendered page. * @param containerPath path of the container to search in. * @param label * @see #findComponentByLabel(MarkupContainer, String) */ public Component findComponentByAccessKey(final WicketTester tester, final String containerPath, final char accessKey) { return findComponentByAccessKey((MarkupContainer) tester.getComponentFromLastRenderedPage(containerPath), accessKey); } /** * Logs any current logged-in user out and calls log-in page. */ protected void logout() { LoginPage.logout((MySession) tester.getSession(), tester.getRequest(), tester.getResponse(), userXmlPreferencesCache, menuBuilder); tester.startPage(LoginPage.class); tester.assertRenderedPage(LoginPage.class); } public void setUserXmlPreferencesCache(final UserXmlPreferencesCache userXmlPreferencesCache) { this.userXmlPreferencesCache = userXmlPreferencesCache; } public void setMenuBuilder(final MenuBuilder menuBuilder) { this.menuBuilder = menuBuilder; } }