/sitebricks/src/test/java/com/google/sitebricks/compiler/HtmlTemplateCompilerTest.java
http://github.com/dhanji/sitebricks · Java · 432 lines · 289 code · 75 blank · 68 comment · 10 complexity · 6da522ed9bdc2e4bed67a04da53efba3 MD5 · raw file
- package com.google.sitebricks.compiler;
- import com.google.common.collect.ImmutableMap;
- import com.google.common.collect.Maps;
- import com.google.inject.AbstractModule;
- import com.google.inject.Guice;
- import com.google.inject.Injector;
- import com.google.inject.Provider;
- import com.google.inject.TypeLiteral;
- import com.google.sitebricks.Bricks;
- import com.google.sitebricks.Renderable;
- import com.google.sitebricks.Respond;
- import com.google.sitebricks.RespondersForTesting;
- import com.google.sitebricks.Template;
- import com.google.sitebricks.TestRequestCreator;
- import com.google.sitebricks.conversion.MvelTypeConverter;
- import com.google.sitebricks.conversion.TypeConverter;
- import com.google.sitebricks.headless.Request;
- import com.google.sitebricks.http.Delete;
- import com.google.sitebricks.http.Get;
- import com.google.sitebricks.http.Patch;
- import com.google.sitebricks.http.Post;
- import com.google.sitebricks.http.Put;
- import com.google.sitebricks.rendering.EmbedAs;
- import com.google.sitebricks.rendering.control.Chains;
- import com.google.sitebricks.rendering.control.WidgetRegistry;
- import com.google.sitebricks.routing.PageBook;
- import com.google.sitebricks.routing.SystemMetrics;
- import org.testng.annotations.BeforeMethod;
- import org.testng.annotations.DataProvider;
- import org.testng.annotations.Test;
- import java.lang.annotation.Annotation;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import static org.easymock.EasyMock.createNiceMock;
- import static org.easymock.EasyMock.expect;
- import static org.easymock.EasyMock.replay;
- import static org.testng.Assert.assertEquals;
- import static org.testng.Assert.fail;
- /**
- * @author Dhanji R. Prasanna (dhanji@gmail.com)
- */
- public class HtmlTemplateCompilerTest {
- private static final String ANNOTATION_EXPRESSIONS = "Annotation expressions";
- private Injector injector;
- private WidgetRegistry registry;
- private PageBook pageBook;
- private SystemMetrics metrics;
- private final Map<String, Class<? extends Annotation>> methods = Maps.newHashMap();
- private HtmlTemplateCompiler compiler() {
- registry = injector.getInstance(WidgetRegistry.class);
- registry.addEmbed("myfave");
- pageBook = injector.getInstance(PageBook.class);
- pageBook.at("/somewhere", MyEmbeddedPage.class).apply(Chains.terminal());
- return new HtmlTemplateCompiler(registry, pageBook, metrics);
- }
-
- @BeforeMethod
- public void pre() {
- methods.put("get", Get.class);
- methods.put("post", Post.class);
- methods.put("put", Put.class);
- methods.put("patch", Patch.class);
- methods.put("delete", Delete.class);
- injector = Guice.createInjector(new AbstractModule() {
- protected void configure() {
- bind(new TypeLiteral<Request>(){}).toProvider(mockRequestProviderForContext());
- bind(new TypeLiteral<Map<String, Class<? extends Annotation>>>() {
- })
- .annotatedWith(Bricks.class)
- .toInstance(methods);
- }
- });
- pageBook = createNiceMock(PageBook.class);
- metrics = createNiceMock(SystemMetrics.class);
- }
- @Test
- public final void annotationKeyExtraction() {
- assert "link".equals(Dom.extractKeyAndContent("@Link")[0]) : "Extraction wrong: ";
- assert "thing".equals(Dom.extractKeyAndContent("@Thing()")[0]) : "Extraction wrong: ";
- assert "thing".equals(Dom.extractKeyAndContent("@Thing(asodkoas)")[0]) : "Extraction wrong: ";
- assert "thing".equals(Dom.extractKeyAndContent("@Thing(asodkoas) ")[0]) : "Extraction wrong: ";
- assert "thing".equals(Dom.extractKeyAndContent("@Thing(asodkoas) kko")[0]) : "Extraction wrong: ";
- assert "".equals(Dom.extractKeyAndContent("@Link")[1]) : "Extraction wrong: ";
- final String val = Dom.extractKeyAndContent("@Thing()")[1];
- assert null == (val) : "Extraction wrong: " + val;
- assert "asodkoas".equals(Dom.extractKeyAndContent("@Thing(asodkoas)")[1]) : "Extraction wrong: ";
- assert "asodkoas".equals(Dom.extractKeyAndContent("@Thing(asodkoas) ")[1]) : "Extraction wrong: ";
- assert "asodkoas".equals(Dom.extractKeyAndContent("@Thing(asodkoas) kko")[1]) : "Extraction wrong: ";
- }
- @Test
- public final void readShowIfWidgetTrue() {
- Renderable widget = compiler()
- .compile(Object.class, new Template("<html>@ShowIf(true)<p>hello</p></html>"));
- // .compile("<!doctype html>\n" +
- // "<html><head><meta charset=\"UTF-8\"><title>small test</title></head><body>\n" +
- // "@ShowIf(true)<p>hello</p>" +
- // "\n</body></html>");
- assert null != widget : " null ";
- final Respond mockRespond = RespondersForTesting.newRespond();
- // final Respond mockRespond = new StringBuilderRespond() {
- // @Override
- // public void write(String text) {
- // builder.append(text);
- // }
- //
- // @Override
- // public void write(char text) {
- // builder.append(text);
- // }
- //
- // @Override
- // public void chew() {
- // builder.deleteCharAt(builder.length() - 1);
- // }
- // };
- widget.render(new Object(), mockRespond);
- final String value = mockRespond.toString();
- System.out.println(value);
- assert "<html><p>hello</p></html>".equals(value) : "Did not write expected output, instead: " + value;
- // assert "<!doctype html><html><head><meta charset=\"UTF-8\"><title>small test</title></head><body><p>hello</p></body></html>".equals(value) : "Did not write expected output, instead: " + value;
- }
- @DataProvider(name = ANNOTATION_EXPRESSIONS)
- public Object[][] get() {
- return new Object[][]{
- {"true"},
- {"java.lang.Boolean.TRUE"},
- {"java.lang.Boolean.valueOf('true')"},
- // {"true ? true : true"}, @TODO (BD): Disabled until I actually investigate if this is a valid test.
- {"'x' == 'x'"},
- {"\"x\" == \"x\""},
- {"'hello' instanceof java.io.Serializable"},
- {"true; return true"},
- {" 5 >= 2 "},
- };
- }
- @Test(dataProvider = ANNOTATION_EXPRESSIONS)
- public final void readAWidgetWithVariousExpressions(String expression) {
- Renderable widget = compiler()
- .compile(Object.class, new Template(String.format("<html>@ShowIf(%s)<p>hello</p></html>", expression)));
-
- assert null != widget : " null ";
- final Respond mockRespond = RespondersForTesting.newRespond();
- widget.render(new Object(), mockRespond);
- final String value = mockRespond.toString();
- assert "<html><p>hello</p></html>".equals(value) : "Did not write expected output, instead: " + value;
- }
- @Test
- public final void readShowIfWidgetFalse() {
- Renderable widget = compiler()
- .compile(Object.class, new Template("<html>@ShowIf(false)<p>hello</p></html>"));
- assert null != widget : " null ";
- final Respond mockRespond = RespondersForTesting.newRespond();
- widget.render(new Object(), mockRespond);
- final String value = mockRespond.toString();
- assert "<html></html>".equals(value) : "Did not write expected output, instead: " + value;
- }
- @Test
- public final void readTextWidgetValues() {
- // make a basic type converter without creating
- TypeConverter converter = new MvelTypeConverter();
- Parsing.setTypeConverter(converter);
- Renderable widget = compiler()
- .compile(TestBackingType.class, new Template("<html><div class='${clazz}'>hello <a href='/people/${id}'>${name}</a></div></html>"));
- assert null != widget : " null ";
- final Respond mockRespond = RespondersForTesting.newRespond();
- widget.render(new TestBackingType("Dhanji", "content", 12), mockRespond);
- final String value = mockRespond.toString();
- assert "<html><div class='content'>hello <a href='/people/12'>Dhanji</a></div></html>"
- .replaceAll("'", "\"")
- .equals(value) : "Did not write expected output, instead: " + value;
- }
- public static class TestBackingType {
- private String name;
- private String clazz;
- private Integer id;
- public TestBackingType(String name, String clazz, Integer id) {
- this.name = name;
- this.clazz = clazz;
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public String getClazz() {
- return clazz;
- }
- public Integer getId() {
- return id;
- }
- }
- @Test
- public final void readAndRenderRequireWidget() {
-
- // make a basic type converter without creating
- TypeConverter converter = new MvelTypeConverter();
- Parsing.setTypeConverter(converter);
- Renderable widget = compiler()
- //new HtmlTemplateCompiler(registry, pageBook, metrics)
- .compile(TestBackingType.class, new Template("<html> <head>" +
- " @Require <script type='text/javascript' src='my.js'> </script>" +
- " @Require <script type='text/javascript' src='my.js'> </script>" +
- "</head><body>" +
- "<div class='${clazz}'>hello <a href='/people/${id}'>${name}</a></div>" +
- "</body></html>"));
-
- assert null != widget : " null ";
- final Respond respond = RespondersForTesting.newRespond();
- widget.render(new TestBackingType("Dhanji", "content", 12), respond);
- final String value = respond.toString();
- String expected = "<html> <head>" +
- " <script type='text/javascript' src='my.js'> </script>" +
- "</head><body>" +
- "<div class='content'>hello <a href='/people/12'>Dhanji</a></div></body></html>";
- expected = expected.replaceAll("'", "\"");
- assertEquals(value, expected);
- }
- @Test
- public final void readHtmlWidgetWithError() {
- try{
- Renderable widget = compiler()
- .compile(TestBackingType.class, new Template("<html>\n<div class='${clazz}'>hello</div>\n</html>${qwe}"));
- fail();
- } catch (Exception ex){
- assertEquals(ex.getClass(), TemplateCompileException.class);
- TemplateCompileException te = (TemplateCompileException) ex;
- assertEquals(te.getErrors().size(), 1);
- CompileError error = te.getErrors().get(0);
- assertEquals(error.getLine(), 2);
- }
- }
- @Test
- public final void readHtmlWidgetWithErrorAndWidget() {
- try{
- Renderable widget = compiler()
- .compile(TestBackingType.class, new Template("<html>\n<div class='${clazz}'>hello</div>\n\n</html>@ShowIf(true)\n${qwe}"));
- fail();
- } catch (Exception ex){
- assertEquals(ex.getClass(), TemplateCompileException.class);
- TemplateCompileException te = (TemplateCompileException) ex;
- assertEquals(te.getErrors().size(), 1);
- CompileError error = te.getErrors().get(0);
- assertEquals(error.getLine(), 4);
- }
- }
- @Test
- public final void readHtmlWidget() {
- Renderable widget = compiler()
- .compile(TestBackingType.class, new Template("<html><div class='${clazz}'>hello</div></html>"));
- assert null != widget : " null ";
- final Respond mockRespond = RespondersForTesting.newRespond();
- widget.render(new TestBackingType("Dhanji", "content", 12), mockRespond);
- final String s = mockRespond.toString();
- assert "<html><div class=\"content\">hello</div></html>"
- .equals(s) : "Did not write expected output, instead: " + s;
- }
- @Test
- public final void readHtmlWidgetWithChildren() {
- Renderable widget = compiler()
- .compile(TestBackingType.class, new Template("<!doctype html><html><body><div class='${clazz}'>hello @ShowIf(false)<a href='/hi/${id}'>hideme</a></div></body></html>"));
- assert null != widget : " null ";
- final Respond mockRespond = RespondersForTesting.newRespond();
- widget.render(new TestBackingType("Dhanji", "content", 12), mockRespond);
- final String s = mockRespond.toString();
- assertEquals(s, "<!doctype html><html><body><div class=\"content\">hello </div></body></html>");
- }
- @EmbedAs(MyEmbeddedPage.MY_FAVE_ANNOTATION)
- public static class MyEmbeddedPage {
- protected static final String MY_FAVE_ANNOTATION = "MyFave";
- private boolean should = true;
- public boolean isShould() {
- return should;
- }
- public void setShould(boolean should) {
- this.should = should;
- }
- }
- @Test
- public final void readEmbedWidgetAndStoreAsPage() {
- Renderable widget = compiler()
- .compile(TestBackingType.class, new Template("<xml><div class='content'>hello @MyFave(should=false)<a href='/hi/${id}'>hideme</a></div></xml>"));
- assert null != widget : " null ";
- //tell pagebook to track this as an embedded widget
- pageBook.embedAs(MyEmbeddedPage.class, MyEmbeddedPage.MY_FAVE_ANNOTATION)
- .apply(Chains.terminal());
- final Respond mockRespond = RespondersForTesting.newRespond();
- widget.render(new TestBackingType("Dhanji", "content", 12), mockRespond);
- final String s = mockRespond.toString();
- assert "<xml><div class=\"content\">hello </div></xml>"
- .equals(s) : "Did not write expected output, instead: " + s;
- }
- @Test
- public final void readEmbedWidgetOnly() {
- Renderable widget = compiler()
- .compile(TestBackingType.class, new Template("<html><div class='content'>hello @MyFave(should=false)<a href='/hi/${id}'>hideme</a></div></html>"));
- assert null != widget : " null ";
- //tell pagebook to track this as an embedded widget
- pageBook.embedAs(MyEmbeddedPage.class, MyEmbeddedPage.MY_FAVE_ANNOTATION)
- .apply(Chains.terminal());
- final Respond mockRespond = RespondersForTesting.newRespond();
- widget.render(new TestBackingType("Dhanji", "content", 12), mockRespond);
- final String s = mockRespond.toString();
- assert "<html><div class=\"content\">hello </div></html>"
- .equals(s) : "Did not write expected output, instead: " + s;
- }
- //TODO Fix this test!
- // @Test
- // public final void readEmbedWidgetWithArgs() throws ExpressionCompileException {
- //
- // final Evaluator evaluator = new MvelEvaluator();
- // final Injector injector = Guice.createInjector(new AbstractModule() {
- // protected void configure() {
- // bind(HttpServletRequest.class).toProvider(mockRequestProviderForContext());
- // }
- // });
- // final PageBook book = injector.getInstance(PageBook.class); //hacky, where are you super-packages!
- //
- // final WidgetRegistry registry = injector.getInstance(WidgetRegistry.class);
- //
- // final MvelEvaluatorCompiler compiler = new MvelEvaluatorCompiler(TestBackingType.class);
- // Renderable widget =
- // new HtmlTemplateCompiler(Object.class, compiler, registry, book, metrics)
- // .compile("<xml><div class='content'>hello @MyFave(should=true)<a href='/hi/${id}'> @With(\"me\")<p>showme</p></a></div></xml>");
- //
- // assert null != widget : " null ";
- //
- //
- // HtmlWidget bodyWrapper = new XmlWidget(Chains.proceeding().addWidget(new IncludeWidget(new TerminalWidgetChain(), "'me'", evaluator)),
- // "body", compiler, Collections.<String, String>emptyMap());
- //
- // bodyWrapper.setRequestProvider(mockRequestProviderForContext());
- //
- // //should include the @With("me") annotated widget from the template above (discarding the <p> tag).
- // book.embedAs(MyEmbeddedPage.class).apply(bodyWrapper);
- //
- // final Respond mockRespond = new StringBuilderRespond();
- //
- // widget.render(new TestBackingType("Dhanji", "content", 12), mockRespond);
- //
- // final String s = mockRespond.toString();
- // assert "<xml><div class=\"content\">hello showme</div></xml>"
- // .equals(s) : "Did not write expected output, instead: " + s;
- // }
- public static Provider<Request> mockRequestProviderForContext() {
- return new Provider<Request>() {
- public Request get() {
- final HttpServletRequest request = createNiceMock(HttpServletRequest.class);
- expect(request.getContextPath())
- .andReturn("")
- .anyTimes();
- expect(request.getMethod())
- .andReturn("POST")
- .anyTimes();
- expect(request.getParameterMap())
- .andReturn(ImmutableMap.of())
- .anyTimes();
- replay(request);
- return TestRequestCreator.from(request, null);
- }
- };
- }
- }