/* vim: set ts=2 et sw=2 cindent fo=qroca: */ package com.globant.katari.tools; import java.io.File; import java.io.FileOutputStream; import org.apache.commons.lang.Validate; import org.apache.wicket.protocol.http.WebRequestCycle; import org.apache.wicket.spring.injection.annot.SpringComponentInjector; import org.apache.wicket.util.tester.WicketTester; import org.springframework.context.ApplicationContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Support class to test wicket pages integrated in katari with spring. * * This class also dumps the generated html to target/wicket-test. The file * name is composed by the calling class name, the calling method and the * wicket page name. */ public class KatariWicketTester extends WicketTester { /** The class logger. */ private static Logger log = LoggerFactory.getLogger(KatariWicketTester.class); /** Prepares a wicket tester to use a spring application context to inject * dependencies into pages. * * @param applicationContext The spring application context, usually an * instance of ApplicationContextMock. It cannot be null. */ public KatariWicketTester(final ApplicationContext applicationContext) { Validate.notNull(applicationContext, "The application context cannot be null."); getApplication().addComponentInstantiationListener( new SpringComponentInjector(getApplication(), applicationContext, true)); } /** Overridden to generate the html dump of processed pages. * * {@inheritDoc} */ @Override public final void processRequestCycle(final WebRequestCycle cycle) { super.processRequestCycle(cycle); dumpResult(getServletResponse().getDocument()); } /** Dumps the html result to a file named after the test method that uses * this WicketTester. * * @param output The html output to dump. It cannot be null. */ private void dumpResult(final String output) { log.trace("Entering dumpResult"); Validate.notNull(output, "The output cannot be null"); // Creates the output directory if it does not exist. File directory = new File("target/wicket-test"); directory.mkdirs(); // Iterates the stack trace of the current thread. StackTraceElement[] stack = Thread.currentThread().getStackTrace(); // The first element corresponds to getStackTrace. int i = 0; // Skips until a stack frame in this class. for (; i < stack.length; ++i) { if (stack[i].getClassName().equals(getClass().getName())) { break; } } for (; i < stack.length; ++i) { String name = buildOutputName(stack[i]); log.debug("Candidate html dump file name {}", name); // Finds the dumpResult method call in the stack trace. if (isTestMethod(stack[i])) { // Writes the output to the file. name = buildOutputName(stack[i]); FileOutputStream stream = null; try { try { stream = new FileOutputStream("target/wicket-test/" + name); stream.write(output.getBytes()); } finally { if (stream != null) { stream.close(); } } } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException("Error creating html dump file.", e); } break; } } log.trace("Leaving dumpResult"); } /** Determines if the stack entry corresponds to a candidate test method. * * This implementation simply checks that the package is not * org.apache.wicket.util.tester and the class is not this one. * * @param entry The stack trace element used to generate the file name. It * cannot be null. * * @return true if the stack trace element corresponds to a calling test * method. */ private boolean isTestMethod(final StackTraceElement entry) { if (entry.getClassName().equals(getClass().getName())) { return false; } if (entry.getClassName().startsWith("org.apache.wicket.util.tester")) { return false; } return true; } /** Builds an output file name base on a stack trace element. * * The name is the fully qualified class name, followed by a dot, followed by * the method name, with an '.html' extension. * * @param entry The stack trace element used to generate the file name. It * cannot be null. * * @return a string with the output file name, never returns null. */ private String buildOutputName(final StackTraceElement entry) { Validate.notNull(entry, "The stack trace entry cannot be null."); return entry.getClassName() + "." + entry.getMethodName() + "." + getLastRenderedPage().getClass().getName() + ".html"; } }