/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.web; import java.util.Locale; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.ajax.AjaxEventBehavior; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.feedback.IFeedbackMessageFilter; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.util.tester.WicketTester; import org.apache.wicket.util.visit.IVisit; import org.apache.wicket.util.visit.IVisitor; import org.geoserver.data.test.SystemTestData; import org.geoserver.security.GeoServerSecurityTestSupport; import org.geoserver.web.wicket.WicketHierarchyPrinter; import org.junit.After; import org.junit.BeforeClass; public abstract class GeoServerWicketTestSupport extends GeoServerSecurityTestSupport { public static WicketTester tester; @BeforeClass public static void disableBrowserDetection() { // disable browser detection, makes testing harder for nothing GeoServerApplication.DETECT_BROWSER = false; } @Override protected void onSetUp(SystemTestData testData) throws Exception { // prevent Wicket from bragging about us being in dev mode (and run // the tests as if we were in production all the time) System.setProperty("wicket.configuration", "deployment"); // make sure that we check the english i18n when needed Locale.setDefault(Locale.ENGLISH); GeoServerApplication app = (GeoServerApplication) applicationContext.getBean("webApplication"); tester = new WicketTester(app, false); app.init(); } @After public void clearErrorMessages() { if(tester != null && !tester.getFeedbackMessages(IFeedbackMessageFilter.ALL).isEmpty()) { tester.cleanupFeedbackMessages(); } } @Override protected void onTearDown(SystemTestData testData) throws Exception { super.onTearDown(testData); tester.destroy(); } public GeoServerApplication getGeoServerApplication(){ return GeoServerApplication.get(); } /** * Logs in as administrator. */ public void login(){ login("admin", "geoserver", "ROLE_ADMINISTRATOR"); } public void logout(){ login("anonymousUser","", "ROLE_ANONYMOUS"); } /** * Prints the specified component/page containment hierarchy to the standard output * <p> * Each line in the dump looks like: <componentId>(class) 'value' * @param c the component to be printed * @param dumpClass if enabled, the component classes are printed as well * @param dumpValue if enabled, the component values are printed as well */ public void print(Component c, boolean dumpClass, boolean dumpValue) { if (isQuietTests()) { return; } WicketHierarchyPrinter.print(c, dumpClass, dumpValue); } /** * Prints the specified component/page containment hierarchy to the standard output * <p> * Each line in the dump looks like: <componentId>(class) 'value' * @param c the component to be printed * @param dumpClass if enabled, the component classes are printed as well * @param dumpValue if enabled, the component values are printed as well */ public void print(Component c, boolean dumpClass, boolean dumpValue, boolean dumpPath) { if (isQuietTests()) { return; } WicketHierarchyPrinter.print(c, dumpClass, dumpValue); } /** * Finds the component whose model value equals to the specified content, and * the component class is equal, subclass or implementor of the specified class * @param root the component under which the search is to be performed * @param content * @param componentClass the target class, or null if any component will do * */ public Component findComponentByContent(MarkupContainer root, Object content, Class<?> componentClass) { ComponentContentFinder finder = new ComponentContentFinder(content); root.visitChildren(componentClass, finder); return finder.candidate; } class ComponentContentFinder implements IVisitor<Component, Void> { Component candidate; Object content; ComponentContentFinder(Object content) { this.content = content; } @Override public void component(Component component, IVisit<Void> visit) { if(content.equals(component.getDefaultModelObject())) { this.candidate = component; visit.stop(); } } } /** * Helper method to initialize a standalone WicketTester with the proper * customizations to do message lookups. */ public static void initResourceSettings(WicketTester tester) { tester.getApplication().getResourceSettings().setResourceStreamLocator(new GeoServerResourceStreamLocator()); tester.getApplication().getResourceSettings().getStringResourceLoaders().add(0, new GeoServerStringResourceLoader()); } /** * Get Ajax Event Behavior attached to a component. * * @param path path to component * @param event the name of the event * */ protected AjaxEventBehavior getAjaxBehavior(String path, String event) { for (Behavior b : tester.getComponentFromLastRenderedPage(path).getBehaviors()) { if (b instanceof AjaxEventBehavior && ((AjaxEventBehavior) b).getEvent().equals(event)) { return (AjaxEventBehavior) b; } } return null; } /** * Execute Ajax Event Behavior with attached value. * * @param path * @param event * @param value */ protected void executeAjaxEventBehavior(String path, String event, String value) { String[] ids = path.split(":"); String id = ids[ids.length-1]; tester.getRequest().setParameter(id, value); tester.executeAjaxEvent(path, event); } /** * Sets the value of a form component that might not be included in a form (because maybe we * are using it via Ajax). By itself it just prepares the stage for a subsequent Ajax request * * @param component The {@link FormComponent} whose value we are going to set * @param value The form value (as we'd set it in a HTML form) */ protected void setFormComponentValue(FormComponent component, String value) { tester.getRequest().getPostParameters().setParameterValue(component.getInputName(), value); } }