org.javalite.activeweb.ViewSpec Maven / Gradle / Ivy
package org.javalite.activeweb;
import com.google.inject.Injector;
import org.javalite.activeweb.freemarker.ContentTL;
import org.javalite.activeweb.freemarker.FreeMarkerTag;
import org.javalite.activeweb.freemarker.FreeMarkerTemplateManager;
import org.junit.After;
import org.junit.Before;
import org.springframework.mock.web.MockFilterConfig;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.javalite.common.Collections.map;
/**
* This is a spec used to test templates and custom tags.
*
* @author Max Artyukhov
*/
public abstract class ViewSpec extends SpecHelper {
private FreeMarkerTemplateManager manager;
public ViewSpec(){
manager = new FreeMarkerTemplateManager();
manager.setTemplateLocation("src/main/webapp/WEB-INF/views");
}
@Before
public final void beforeTest(){
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContextPath("/test_context");
RequestContext.setTLs(request, new MockHttpServletResponse(), new MockFilterConfig(), new AppContext(), new RequestVo(), null);
}
@After
public final void afterTest(){
RequestContext.clear();
}
/**
* By default the template location is set to src/main/webapp/WEB-INF/views
.
* However in some cases you want to have test templates that are different
* from runtime templates. In those cases you can override that default
* location with your value,
*
* @param templateLocation location of your templates relative to the directory
* where test is executed, usually a root of your Maven module
*/
@Override
public void setTemplateLocation(String templateLocation){
manager.setTemplateLocation(templateLocation);
}
/**
* Sets injector for tags if they require dependencies.
*
* @param injector injector to source dependencies form.
*/
@Override
protected void setInjector(Injector injector){
Configuration.setInjector(injector);
}
/**
* Use to register a tag before the test.
*
* @param name name of tag as used in a template.
* @param tag tag instance
*/
@Override
protected void registerTag(String name, FreeMarkerTag tag) {
manager.registerTag(name, tag);
Injector injector = Configuration.getInjector();
if(injector != null)
injector.injectMembers(tag);
}
/**
* Renders a template by name
*
* @param templateName name of template to render
* @return rendered template
*/
protected String render(String templateName) {
return render(templateName, new HashMap());
}
/**
* Renders a template by name
*
* @param templateName name of template to render
* @param values values to be passed into template
* @return rendered template content as string
*/
protected String render(String templateName, Map values) {
StringWriter stringWriter = new StringWriter();
ParamCopy.copyInto(values);
manager.merge(values, templateName, stringWriter);
return stringWriter.toString();
}
/**
* Renders a template by name.
*
* @param templateName name of template to render
* @param namesAndValues - list of names and values, where first, third, etc argument is a name and second,
* fourth, etc. argument is a corresponding value.
* @return rendered template content as string
*/
protected String render(String templateName, String ... namesAndValues) {
return render(templateName, map(namesAndValues));
}
/**
* This method is only needed as a hint to the {@link org.javalite.activeweb.freemarker.LinkToTag}. If the link_to
* tag is used in a template without the controller
attribute, it needs a current controller in context
* to generate a proper link. At runtime as well as in controller tests, a controller is always present in context, and
* link_to
works as expected. However, since view specs are executed outside of controller execution,
* if you have a link_to
in the template you are testing, you will need to provide a clue to your view
* before the test is executed.
*
* @param controllerClass controller class to aid to the link_to
tag to generate a proper link.
*/
protected void setCurrentController(Class controllerClass){
try{
AppController instance = controllerClass.newInstance();
RequestContext.setRoute(new Route(instance));
}catch(Exception e){
throw new ViewException(e);
}
}
/**
* This method returns chunks of content that was assigned from a tested template. Call this method after rendering a view
* in order to verify that the view did set appropriate text chunks with the {@link org.javalite.activeweb.freemarker.ContentForTag}
* when it is used in a template, example:
*
*
*<@content for="title">Book title</@content>
*
*
*
* @param name name of a content piece as was specified by the "for" attribute of the "content" tag.
* @return piece of content assigned from "content" tag if one was used in a tested view.
*/
protected List contentFor(String name){
return ContentTL.getAllContent().get(name);
}
}