/**
* Copyright (C) 2013-2015 all@code-story.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package net.codestory.http.templating;
import static java.util.Arrays.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import net.codestory.http.compilers.*;
import net.codestory.http.io.Resources;
import net.codestory.http.markdown.*;
import net.codestory.http.misc.*;
import net.codestory.http.templating.helpers.*;
import org.junit.*;
import com.github.jknack.handlebars.*;
public class HandlebarsCompilerTest {
static Env env = Env.prod();
static Resources resources = new Resources(env);
static MarkdownCompiler markdownCompiler = new MarkdownCompiler();
static HandlebarsCompiler compiler = new HandlebarsCompiler(env, resources, new CompilerFacade(env, resources), markdownCompiler);
private String compile(String content, Map<String, Object> variables) throws IOException {
return compiler.compile(content, variables);
}
@Test
public void compile() throws IOException {
String result = compile("-[[greeting]]-", map("greeting", "Hello"));
assertThat(result).isEqualTo("-Hello-");
}
@Test
public void partials() throws IOException {
String result = compile("-[[>partial.txt]] [[>partial.txt]]-", map("name", "Bob"));
assertThat(result).isEqualTo("-Hello Bob Hello Bob-");
}
@Test
public void partial_with_context() throws IOException {
String result = compile("[[>partialWithContext ctx]]", map("ctx", map("firstName", "Bob", "age", "42")));
assertThat(result).isEqualTo("Hello Bob/42");
}
@Test
public void partial_with_loop() throws IOException {
String result = compile("[[>partialWithLoop ctx]]", map("ctx", map("terminal", false, "name", map("name", "bob", "terminal", true))));
assertThat(result).isEqualTo("Hello\n\n Hello\n\n bob\n\n\n\n");
}
@Test
public void find_partial() throws IOException {
String result = compile("[[>partial]]", map("name", "Bob"));
assertThat(result).isEqualTo("Hello Bob");
}
@Test
public void markdown_partial() throws IOException {
String result = compile("[[>map city]]", map("city", "Paris"));
assertThat(result).isEqualTo("<p><a href=\"https://maps.google.com/maps?q=+Paris\"> Paris</a></p>\n");
}
@Test(expected = HandlebarsException.class)
public void unknown_partial() throws IOException {
compile("[[>unknown]]", map("", ""));
}
@Test
public void string_helpers() throws IOException {
String result = compile("Hello [[capitalizeFirst name]]", map("name", "joe"));
assertThat(result).isEqualTo("Hello Joe");
}
@Test
public void java_getters_and_fields() throws IOException {
String result = compile("[[bean.name]] is [[bean.age]]", map("bean", new JavaBean("Bob", 12)));
assertThat(result).isEqualTo("Bob is 12");
}
@Test
public void java_getter_method() throws IOException {
String result = compile("[[bean.fullDescription]]", map("bean", new JavaBean("Bob", 12)));
assertThat(result).isEqualTo("Bob-12");
}
@Test
public void java_plain_method() throws IOException {
String result = compile("[[bean.description]]", map("bean", new JavaBean("Bob", 12)));
assertThat(result).isEqualTo("Bob");
}
@Test
public void each() throws IOException {
String result = compile("[[#each list]][[.]][[/each]]", map("list", asList("A", "B")));
assertThat(result).isEqualTo("AB");
}
@Test
public void each_reverse() throws IOException {
String result = compile("[[#each_reverse list]][[.]][[/each_reverse]]", map("list", asList("A", "B")));
assertThat(result).isEqualTo("BA");
}
@Test
public void values_by_key() throws IOException {
Map<String, Object> variables = new TreeMap<>();
variables.put("letters", asList("A", "B"));
variables.put("descriptions", new TreeMap<String, Object>() {{
put("A", "Letter A");
put("B", "Letter B");
put("C", "Letter C");
}});
String result = compile("[[#each_value descriptions letters]][[@key]]=[[.]][[/each_value]]", variables);
assertThat(result).isEqualTo("A=Letter AB=Letter B");
}
@Test
public void values_by_hash_key() throws IOException {
Map<String, Object> variables = new TreeMap<>();
variables.put("letters", new TreeMap<String, Object>() {{
put("A", map("id", "idA"));
put("B", map("id", "idB"));
}});
variables.put("descriptions", new TreeMap<String, Object>() {{
put("A", "Description A");
put("B", "Description B");
put("C", "Description C");
}});
String result = compile("[[#each_value descriptions letters]][[@value.id]]=[[.]][[/each_value]]", variables);
assertThat(result).isEqualTo("idA=Description AidB=Description B");
}
@Test
public void unescaped_content() throws IOException {
String result = compile("[[&html]]", map("html", "<div>Hello</div>"));
assertThat(result).isEqualTo("<div>Hello</div>");
}
@Test
public void custom_resolver() throws IOException {
compiler.addResolver(new BasicResolver() {
@Override
public String tag() {
return "additional";
}
@Override
public Object resolve(Object context) {
return "SUCCESS";
}
});
String result = compile("[[additional]]", new TreeMap<>());
assertThat(result).isEqualTo("SUCCESS");
}
@Test
public void google_analytics_with_fixed_id() throws IOException {
compiler.configure(hb -> hb.registerHelpers(new GoogleAnalyticsHelper("ID")));
String result = compile("[[google_analytics]]", new TreeMap<>());
assertThat(result).startsWith("<script>").contains("ID").endsWith("</script>");
}
@Test
public void google_analytics_with_dynamic_id() throws IOException {
compiler.configure(hb -> hb.registerHelpers(new GoogleAnalyticsHelper()));
String result = compile("[[google_analytics UA]]", map("UA", "12345"));
assertThat(result).startsWith("<script>").contains("12345").endsWith("</script>");
}
@Test
public void skip_google_analytics_in_dev_mode() throws IOException {
Env env = mock(Env.class);
when(env.prodMode()).thenReturn(false);
compiler.configure(hb -> hb.registerHelpers(new GoogleAnalyticsHelper("ID")));
String result = compile("[[google_analytics UA]]", map("env", env));
assertThat(result).isEmpty();
}
@Test
public void can_override_helper() throws IOException {
compiler.configure(hb -> hb.registerHelpers(new GoogleAnalyticsHelper("DEFAULT_ID")));
compiler.configure(hb -> hb.registerHelpers(new GoogleAnalyticsHelper("OVERRIDEN")));
String result = compile("[[google_analytics]]", new TreeMap<>());
assertThat(result).contains("OVERRIDEN").doesNotContain("DEFAULT_ID");
}
@Test
public void compatibility_with_templating() {
assertThat(compiler.supports(Paths.get("index.html"))).isTrue();
assertThat(compiler.supports(Paths.get("data.xml"))).isTrue();
assertThat(compiler.supports(Paths.get("data.json"))).isTrue();
assertThat(compiler.supports(Paths.get("test.md"))).isTrue();
assertThat(compiler.supports(Paths.get("test.markdown"))).isTrue();
assertThat(compiler.supports(Paths.get("text.txt"))).isTrue();
assertThat(compiler.supports(Paths.get("style.css.map"))).isFalse();
assertThat(compiler.supports(Paths.get("style.css"))).isFalse();
assertThat(compiler.supports(Paths.get("style.less"))).isFalse();
assertThat(compiler.supports(Paths.get("text.zip"))).isFalse();
assertThat(compiler.supports(Paths.get("text.gz"))).isFalse();
assertThat(compiler.supports(Paths.get("text.pdf"))).isFalse();
assertThat(compiler.supports(Paths.get("image.gif"))).isFalse();
assertThat(compiler.supports(Paths.get("image.jpeg"))).isFalse();
assertThat(compiler.supports(Paths.get("image.jpg"))).isFalse();
assertThat(compiler.supports(Paths.get("image.png"))).isFalse();
assertThat(compiler.supports(Paths.get("font.svg"))).isFalse();
assertThat(compiler.supports(Paths.get("font.eot"))).isFalse();
assertThat(compiler.supports(Paths.get("font.ttf"))).isFalse();
assertThat(compiler.supports(Paths.get("font.woff"))).isFalse();
assertThat(compiler.supports(Paths.get("font.woff2"))).isFalse();
assertThat(compiler.supports(Paths.get("script.js"))).isFalse();
assertThat(compiler.supports(Paths.get("script.coffee"))).isFalse();
assertThat(compiler.supports(Paths.get("script.litcoffee"))).isFalse();
assertThat(compiler.supports(Paths.get("favicon.ico"))).isFalse();
assertThat(compiler.supports(Paths.get("unknown"))).isFalse();
}
private static Map<String, Object> map(String key, Object value) {
return new TreeMap<String, Object>() {{
put(key, value);
}};
}
private static Map<String, Object> map(String key1, Object value1, String key2, Object value2) {
return new TreeMap<String, Object>() {{
put(key1, value1);
put(key2, value2);
}};
}
public static class JavaBean {
private final String name;
public final int age;
private JavaBean(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getFullDescription() {
return name + "-" + age;
}
public String description() {
return name;
}
}
}