/** * Render the given template using the given context bindings. This method returns some metadata about the render process, including any errors which may have been encountered such as unknown variables or syntax errors. This method will * not throw any exceptions; it is up to the caller to inspect the renderResult.errors collection if necessary / desired. * * @param template * jinja source template * @param bindings * map of objects to put into scope for this rendering action * @return result object containing rendered output, render context, and any encountered errors */ public RenderResult renderForResult(String template, Map<String, ?> bindings) { return renderForResult(template, bindings, globalConfig); }
private RenderResult render(final Path path, final GraphContainer container) throws IOException { final Map<String, Object> context = this.createContext(container); try (final Stream<String> lines = Files.lines(path, Charset.defaultCharset())) { final String template = lines.collect(Collectors.joining("\n")); return withClassLoaderFix(() -> jinjava.renderForResult(template, context)); } } }
private RenderResult render(final Path path, final GraphContainer container) throws IOException { final Map<String, Object> context = this.createContext(container); try (final Stream<String> lines = Files.lines(path, Charset.defaultCharset())) { final String template = lines.collect(Collectors.joining("\n")); return withClassLoaderFix(() -> jinjava.renderForResult(template, context)); } } }
@Test public void itHasIncludesReferenceInContext() throws Exception { RenderResult renderResult = jinjava.renderForResult(Resources.toString(Resources.getResource("tags/includetag/include-tag-dependencies.html"), StandardCharsets.UTF_8), new HashMap<String, Object>()); SetMultimap<String, String> dependencies = renderResult.getContext().getDependencies(); assertThat(dependencies.size()).isEqualTo(2); assertThat(dependencies.get("coded_files")).isNotEmpty(); assertThat(dependencies.get("coded_files").contains("{% include \"tags/includetag/hello.html\" %}")); assertThat(dependencies.get("coded_files").contains("{% include \"tags/includetag/cat.html\" %}")); }
@Test public void itHasIncludesReferenceInContext() throws Exception { RenderResult renderResult = jinjava.renderForResult(Resources.toString(Resources.getResource("tags/includetag/include-tag-dependencies.html"), StandardCharsets.UTF_8), new HashMap<String, Object>()); SetMultimap<String, String> dependencies = renderResult.getContext().getDependencies(); assertThat(dependencies.size()).isEqualTo(2); assertThat(dependencies.get("coded_files")).isNotEmpty(); assertThat(dependencies.get("coded_files").contains("{% include \"tags/includetag/hello.html\" %}")); assertThat(dependencies.get("coded_files").contains("{% include \"tags/includetag/cat.html\" %}")); }
@Test public void itErrorsOnInvalidTemporalUnit() { long timestamp = 1543352736000L; Map<String, Object> vars = ImmutableMap.of("test", ZonedDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC)); RenderResult renderResult = jinjava.renderForResult("{{ test|plus_time(1, 'parsec')|unixtimestamp }}", vars); assertThat(renderResult.getErrors()).hasSize(1); } }
@Test public void itSetsFieldNameCaseForSyntaxErrorInFor() { RenderResult renderResult = new Jinjava().renderForResult("{% for item inna navigation %}{% endfor %}", ImmutableMap.of()); assertThat(renderResult.getErrors().get(0).getFieldName()).isEqualTo("item inna navigation"); }
@Test public void itHasExtendsReferenceInContext() throws Exception { RenderResult renderResult = jinjava.renderForResult(locator.fixture("super-child.html"), new HashMap<String, Object>()); SetMultimap<String, String> dependencies = renderResult.getContext().getDependencies(); assertThat(dependencies.size()).isEqualTo(1); assertThat(dependencies.get("coded_files")).isNotEmpty(); assertThat(dependencies.get("coded_files").contains("super-base.html")); }
@Test public void itErrorsOnNonStringInput() { int datetime = 123123; String format = "yyyy-MM-dd'T'HH:mm:ssZ"; Map<String, Object> vars = ImmutableMap.of("datetime", datetime, "format", format); assertThat(jinjava.renderForResult("{{ datetime|strtotime(format) }}", vars).getErrors()).hasSize(1); } }
@Test public void itLimitsOutputSize() { JinjavaConfig outputSizeLimitedConfig = JinjavaConfig.newBuilder().withMaxOutputSize(20).build(); String output = "123456789012345678901234567890"; RenderResult renderResult = new Jinjava().renderForResult(output, new HashMap<>()); assertThat(renderResult.getOutput()).isEqualTo(output); assertThat(renderResult.hasErrors()).isFalse(); renderResult = new Jinjava(outputSizeLimitedConfig).renderForResult(output, new HashMap<>()); assertThat(renderResult.getErrors().get(0).getMessage()).contains("OutputTooBigException"); }
@Test public void itLimitsOutputSizeWhenSumOfNodeSizesExceedsMax() { JinjavaConfig outputSizeLimitedConfig = JinjavaConfig.newBuilder().withMaxOutputSize(19).build(); String input = "1234567890{% block testchild %}1234567890{% endblock %}"; String output = "12345678901234567890"; // Note that this exceeds the max size RenderResult renderResult = new Jinjava().renderForResult(input, new HashMap<>()); assertThat(renderResult.getOutput()).isEqualTo(output); assertThat(renderResult.hasErrors()).isFalse(); renderResult = new Jinjava(outputSizeLimitedConfig).renderForResult(input, new HashMap<>()); assertThat(renderResult.hasErrors()).isTrue(); assertThat(renderResult.getErrors().get(0).getMessage()).contains("OutputTooBigException"); } }
@Test public void forTag1() { script = "{% for %}{{item}}{% endfor%}"; RenderResult r = jinjava.renderForResult(script, bindings); assertThat(r.getErrors()).hasSize(1); assertThat(r.getErrors().get(0).getReason()).isEqualTo(ErrorReason.SYNTAX_ERROR); }
@Test public void parseWithSyntaxError() { RenderResult result = new Jinjava().renderForResult("{%}", new HashMap<>()); assertThat(result.getErrors()).isNotEmpty(); assertThat(result.getErrors().get(0).getReason()).isEqualTo(ErrorReason.SYNTAX_ERROR); }
@Test public void forTag1() { script = "{% for %}{{item}}{% endfor%}"; RenderResult r = jinjava.renderForResult(script, bindings); assertThat(r.getErrors()).hasSize(1); assertThat(r.getErrors().get(0).getReason()).isEqualTo(ErrorReason.SYNTAX_ERROR); }
@Test public void ifTag8() { script = "{%if %}hello{%else%}world{%endif%}"; RenderResult r = jinjava.renderForResult(script, bindings); assertThat(r.getErrors()).hasSize(1); assertThat(r.getErrors().get(0).getReason()).isEqualTo(ErrorReason.SYNTAX_ERROR); }
@Test public void parseWithSyntaxError() { RenderResult result = new Jinjava().renderForResult("{%}", new HashMap<>()); assertThat(result.getErrors()).isNotEmpty(); assertThat(result.getErrors().get(0).getReason()).isEqualTo(ErrorReason.SYNTAX_ERROR); }
@Test public void itTruncatesStringToConfigLimit() { jinjava = new Jinjava(JinjavaConfig.newBuilder() .withMaxStringLength(5) .build()); RenderResult result = jinjava.renderForResult("{{ [1, 2, 3, 4, 5]|join('|') }}", new HashMap<String, Object>()); assertThat(result.getOutput()).isEqualTo("1|2|3"); assertThat(result.getErrors().size()).isEqualTo(1); assertThat(result.getErrors().get(0).getMessage()).contains("filter has been truncated to the max String length"); }
@Test public void itStoresResolvedFunctions() { context.put("datetime", 12345); final JinjavaConfig config = JinjavaConfig.newBuilder().build(); String template = "{% for i in range(1, 5) %}{{i}} {% endfor %}\n{{ unixtimestamp(datetime) }}"; final RenderResult renderResult = jinjava.renderForResult(template, context, config); assertThat(renderResult.getOutput()).isEqualTo("1 2 3 4 \n12000"); assertThat(renderResult.getContext().getResolvedFunctions()).hasSameElementsAs(ImmutableSet.of(":range", ":unixtimestamp")); }
@Test public void itResetsGlobalContextAfterRender() { Jinjava jinjava = new Jinjava(); Context globalContext = jinjava.getGlobalContext(); RenderResult result = jinjava.renderForResult("{{ foo + 1 }}", ImmutableMap.of("foo", 1)); assertThat(result.getOutput()).isEqualTo("2"); assertThat(result.getContext().getResolvedExpressions()).containsOnly("foo + 1"); assertThat(result.getContext().getResolvedValues()).containsOnly("foo"); assertThat(globalContext.getResolvedExpressions()).isEmpty(); assertThat(globalContext.getResolvedValues()).isEmpty(); } }
@Test public void itResetsGlobalContextAfterRender() { Jinjava jinjava = new Jinjava(); Context globalContext = jinjava.getGlobalContext(); RenderResult result = jinjava.renderForResult("{{ foo + 1 }}", ImmutableMap.of("foo", 1)); assertThat(result.getOutput()).isEqualTo("2"); assertThat(result.getContext().getResolvedExpressions()).containsOnly("foo + 1"); assertThat(result.getContext().getResolvedValues()).containsOnly("foo"); assertThat(globalContext.getResolvedExpressions()).isEmpty(); assertThat(globalContext.getResolvedValues()).isEmpty(); } }