Skip to content

Commit

Permalink
syntax class unit tests (PebbleTemplates#519)
Browse files Browse the repository at this point in the history
* PebbleTemplates#422: Added inline verbatim description to Verbatim tag documentation

* Added tests for whitespace control for templates when New Line Trimming is enabled. Also added assertj and commons-io Maven dependencies for use in the tests. Commons IO is used to compare template output to expected output that is loaded from a file. Loading the expected template output from a file is useful for testing multiline template output, which is necessary to test various scenarios. These are a form of Integration Test rather than Unit Tests and so it is practical and reasonable to verify the template output in this way.

* Added javadoc to describe the purpose of several existing tests and changed the test method names in some cases to make the purpose of each test method more clear.

* Added a 3rd elseif in the template for the For Loop with Nested If Statement Thatis Skipped test

* Added tests with 2 ifelse in a nested if and also 3 ifelse in a nested if.

* Added test of Nested If with One ifelse statement

* Improved and added additional whitespace control tests.

* Changed Token.toString() implementation to include the line number, which I found useful to see in log statements.

* Added unit test and formatting standards to Contributing documentation page.

* Added a reference to the Jinja Python template engine, which I think provides more evidence that the Pebble syntax is good. Jinja is a very popular Python template engine.

* Added unit tests for the LexerImpl class. Also added log4j debug level log statements in LexerImpl, PebbleEngine and LexerImpl that were useful to me when trying to follow the code. Added logback-test.xml to configure the logging level. Disabled the debug logging by default.  Also removed Hamcrest Matchers and replaced references to Hamcrest in exception testing code with AssertJ. Also, changed the name of a few private methods in LexerImpl for improve clarity.

* Fixed minor text formatting in the summary statement at the top of the Home page.

* Changed log statements from debug level to trace level because debug statements were being output by default. Trace statements are not output unless configured to do so.

* Added newline in debug statement when logging template output at debug level in PebbleTestContext used in unit tests.

* Started adding unit tests for the Syntax class in the lexer package.

* Added unit tests for Trailing Whiltespace Trim Regex defined in the Syntax class in the Lexer package.

* Tests for several regex Syntax.java in the lexer package.

* Added test for start delimiters

Co-authored-by: Nathan Ward <nathanward1234@gmail.com>
  • Loading branch information
nolwad and nward1234 authored Jun 26, 2020
1 parent ffd36f9 commit ed03fae
Show file tree
Hide file tree
Showing 2 changed files with 266 additions and 1 deletion.
265 changes: 265 additions & 0 deletions pebble/src/test/java/com/mitchellbosecke/pebble/lexer/SyntaxTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
package com.mitchellbosecke.pebble.lexer;

import static org.assertj.core.api.Assertions.assertThat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// NOTE: Use regex101.com to test regular expressions through a web site

class SyntaxTest {

private static final String POSSIBLE_NEW_LINE = "(\r\n|\n\r|\r|\n|\u0085|\u2028|\u2029)?";
@SuppressWarnings("unused")
private final Logger logger = LoggerFactory.getLogger(SyntaxTest.class);

private Syntax syntax;

@BeforeEach
void setup() {
this.syntax = new Syntax.Builder().build();
}

@Test
void testDelimiters() {
assertThat(this.syntax.getCommentOpenDelimiter()).isEqualTo("{#");

assertThat(this.syntax.getCommentCloseDelimiter()).isEqualTo("#}");

assertThat(this.syntax.getExecuteOpenDelimiter()).isEqualTo("{%");

assertThat(this.syntax.getExecuteCloseDelimiter()).isEqualTo("%}");

assertThat(this.syntax.getPrintOpenDelimiter()).isEqualTo("{{");

assertThat(this.syntax.getPrintCloseDelimiter()).isEqualTo("}}");

assertThat(this.syntax.getInterpolationCloseDelimiter()).isEqualTo("}");

assertThat(this.syntax.getInterpolationOpenDelimiter()).isEqualTo("#{");

assertThat(this.syntax.getWhitespaceTrim()).isEqualTo("-");
}

@Test
void tesCommentCloseDelimiter() {
assertThat(this.syntax.getCommentCloseDelimiter()).isEqualTo("#}");
}

@Test
void tesCommentOpenDelimiter() {
assertThat(this.syntax.getCommentOpenDelimiter()).isEqualTo("{#");
}

@Test
void testExecuteOpenDelimiter() {
assertThat(this.syntax.getExecuteOpenDelimiter()).isEqualTo("{%");
}

@Test
void testExecuteCloseDelimiter() {
assertThat(this.syntax.getExecuteCloseDelimiter()).isEqualTo("%}");
}

@Test
void testPrintOpenDelimiter() {
assertThat(this.syntax.getPrintCloseDelimiter()).isEqualTo("}}");
}

@Test
void testPrintCloseDelimiter() {
assertThat(this.syntax.getPrintCloseDelimiter()).isEqualTo("}}");
}

@Test
void testInterpolationCloseDelimiter() {
assertThat(this.syntax.getInterpolationCloseDelimiter()).isEqualTo("}");
}

@Test
void testInterpolationOpenDelimiter() {
assertThat(this.syntax.getInterpolationOpenDelimiter()).isEqualTo("#{");
}

@Test
void testWhitespaceTrim() {
assertThat(this.syntax.getWhitespaceTrim()).isEqualTo("-");
}

@Test
void testTrailingWhitespaceTrimRegex() {

Pattern pattern = syntax.getRegexTrailingWhitespaceTrim();

/*
matching from start of string, zero of more space characters, followed by a dash,
followed by one of the following: "}}", "%}", or "#}"
*/
String expectedPatternString = "^\\s*\\Q-\\E(\\Q}}\\E|\\Q%}\\E|\\Q#}\\E)";
// verify that the TrailingWhitepaceTrim regex in the Syntax class is the expected pattern string
assertThat(pattern.toString()).isEqualTo(expectedPatternString);

StringBuilder templateText = null;
Matcher whitespaceTrimMatcher = null;

// Whitespace Trim character with Execution Close Delimiter should match
templateText = new StringBuilder().append("-%}");
whitespaceTrimMatcher = pattern.matcher(templateText);
assertThat(whitespaceTrimMatcher.lookingAt()).isEqualTo(true);

// Whitespace Trim character with Print Close Delimiter should match
templateText = new StringBuilder().append("-}}");
whitespaceTrimMatcher = pattern.matcher(templateText);
assertThat(whitespaceTrimMatcher.lookingAt()).isEqualTo(true);

// leading space characters with Whitespace Trim character with Execution Close Delimiter should match
templateText = new StringBuilder().append(" -%}");
whitespaceTrimMatcher = pattern.matcher(templateText);
assertThat(whitespaceTrimMatcher.lookingAt()).isEqualTo(true);

// Whitespace Trim character with Comment Close Delimiter should match
templateText = new StringBuilder().append("-#}");
whitespaceTrimMatcher = pattern.matcher(templateText);
assertThat(whitespaceTrimMatcher.lookingAt()).isEqualTo(true);

// End of expression without Whitespace Trim character should not match
templateText = new StringBuilder().append("%}");
whitespaceTrimMatcher = pattern.matcher(templateText);
assertThat(whitespaceTrimMatcher.lookingAt()).isEqualTo(false);

// Leading non space characters should not match
templateText = new StringBuilder().append("abcd -%}");
whitespaceTrimMatcher = pattern.matcher(templateText);
assertThat(whitespaceTrimMatcher.lookingAt()).isEqualTo(false);
}

@Test
void testLeadingWhitespaceTrimRegex() {

Pattern pattern = syntax.getRegexLeadingWhitespaceTrim();

/*
"-" followed by one more whitespace characters
*/
String expectedPatternString = "\\Q-\\E\\s+";
// verify that the regex in the Syntax class is the expected pattern string
assertThat(pattern.toString()).isEqualTo(expectedPatternString);

StringBuilder templateText = null;
Matcher matcher = null;

// Dash followed by spaces should match
templateText = new StringBuilder().append("- ");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

// Dash character followed by whitespace characters should match
templateText = new StringBuilder().append("- \n\r\t");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

// Trailing non-whitespace after whitespace characters should match
templateText = new StringBuilder().append("- abcd");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

// No leading dash character should not match
templateText = new StringBuilder().append(" ");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(false);

// No trailing space character should not match
templateText = new StringBuilder().append("-");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(false);

// Leading characters should not match
templateText = new StringBuilder().append(" abcd - }");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(false);
}

@Test
void testRegexVerbatimEnd() {

Pattern pattern = this.syntax.getRegexVerbatimEnd();

/*
"{%" followed by an optional "-" and/or zero or more whitespace characters, followed by "endverbatim",
followed by zero or more whitespace characters and/or an optional "-" followed by "%}"
followed by an optional possible new line character
*/
String expectedPatternString = "\\Q{%\\E(\\Q-\\E)?\\s*endverbatim\\s*(\\Q-\\E)?\\Q%}\\E" + POSSIBLE_NEW_LINE;
// verify that the regex in the Syntax class is the expected pattern string
assertThat(pattern.toString()).isEqualTo(expectedPatternString);

StringBuilder templateText = null;
Matcher matcher = null;

// Space and whitespacetrim characters should match
templateText = new StringBuilder().append("{%- endverbatim -%}abcd\r\n");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

// No spaces or whitespacetrim characters should match
templateText = new StringBuilder().append("{%endverbatim%}");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

// Missing delimiters should not match
templateText = new StringBuilder().append("endverbatim");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(false);
}

@Test
void testRegexStartDelimiters() {

Pattern pattern = this.syntax.getRegexStartDelimiters();

/*
Start delimiters must match "{{" or "{%" or "{#"
*/
String expectedPatternString = "\\Q{{\\E|\\Q{%\\E|\\Q{#\\E";

// verify that the regex in the Syntax class is the expected pattern string
assertThat(pattern.toString()).isEqualTo(expectedPatternString);

StringBuilder templateText = null;
Matcher matcher = null;

// "{{", "{%", and "{#" should match
templateText = new StringBuilder().append("{{");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

templateText = new StringBuilder().append("{%");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

templateText = new StringBuilder().append("{#");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

// Text after a start delimiter should match
templateText = new StringBuilder().append("{{ abcd");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(true);

// Text before the start delimiter should not match
templateText = new StringBuilder().append("abcd {{");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(false);

// No start delimiter should not match
templateText = new StringBuilder().append("abcd");
matcher = pattern.matcher(templateText);
assertThat(matcher.lookingAt()).isEqualTo(false);
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public String executeTemplate(String templateName, PebbleEngine pebbleEngine) th
Writer writer = new StringWriter();
template.evaluate(writer, this.templateContext);
String templateOutput = writer.toString();
logger.debug("Template Output: {}", templateOutput);
logger.debug("Template Output:\n{}", templateOutput);
return templateOutput;
}

Expand Down

0 comments on commit ed03fae

Please sign in to comment.