package de.flower.common.test.wicket; import org.apache.wicket.Component; import org.apache.wicket.Page; import org.apache.wicket.markup.ContainerInfo; 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.util.resource.StringResourceStream; import org.apache.wicket.util.string.Strings; import org.apache.wicket.util.visit.IVisit; import org.apache.wicket.util.visit.IVisitor; import java.util.ArrayList; import java.util.List; /** * Duplicates WicketTesterHelper#getComponentData but avoids reading out model values. * Using the original version of the method inside unit tests might lead to * error logs and even test failure cause model-objects are messed up when they are read. * * @author flowerrrr */ public class WicketTesterHelper { public static class ComponentData extends org.apache.wicket.util.tester.WicketTesterHelper.ComponentData { public Component component; } /** * Gets recursively all <code>Component</code>s of a given <code>Page</code>, extracts the * information relevant to us, and adds them to a <code>List</code>. * * @param page the <code>Page</code> to analyze * @param readModelValues if true the model values of the components are accessed. * WARNING: might lead to unexpected sideeffects. Method should only be called at end of unit tests * when this flag is set. * @return a <code>List</code> of <code>Component</code> data objects */ public static List<ComponentData> getComponentData(final Page page, final boolean readModelValues) { final List<ComponentData> data = new ArrayList<ComponentData>(); if (page != null) { page.visitChildren(new IVisitor<Component, Void>() { public void component(final Component component, final IVisit<Void> visit) { final ComponentData object = new ComponentData(); // anonymous class? Get the parent's class name String name = component.getClass().getName(); if (name.indexOf("$") > 0) { name = component.getClass().getSuperclass().getName(); } // remove the path component name = Strings.lastPathComponent(name, Component.PATH_SEPARATOR); object.path = component.getPageRelativePath(); object.type = name; if (readModelValues) { try { object.value = component.getDefaultModelObjectAsString(); } catch (Exception e) { object.value = e.getMessage(); } } else { object.value = "<not read>"; } object.component = component; data.add(object); } }); } return data; } /** * Create markup based on a string. * * Replacement for Markup.of(string). Markup.of(string) has issues with header contribution, * the markup parser does not add HtmlHeaderSectionHandler to the parsers filter list. * * @param html * @param testPage * @return */ public static Markup creatPageMarkup(final String html, final WebPage page) { final ContainerInfo containerInfo = new ContainerInfo(page); MarkupResourceStream markupResourceStream = new MarkupResourceStream( new StringResourceStream(html), containerInfo, page.getClass()); MarkupParser markupParser = page.getApplication().getMarkupSettings() .getMarkupFactory() .newMarkupParser(markupResourceStream); try { Markup markup = markupParser.parse(); return markup; } catch (Exception e) { throw new RuntimeException(e); } } }