package com.hubspot.jinjava.tree.parse;
import static com.hubspot.jinjava.tree.parse.TokenScannerSymbols.TOKEN_EXPR_START;
import static com.hubspot.jinjava.tree.parse.TokenScannerSymbols.TOKEN_FIXED;
import static com.hubspot.jinjava.tree.parse.TokenScannerSymbols.TOKEN_NOTE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.io.Resources;
import com.hubspot.jinjava.JinjavaConfig;
public class TokenScannerTest {
private JinjavaConfig config;
private String script;
private TokenScanner scanner;
@Before
public void setup() {
config = JinjavaConfig.newBuilder().build();
}
@Test
public void test2() {
script = "{{abc.b}}{% if x %}{{abc{%endif";
scanner = new TokenScanner(script, config);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("{{abc{%endif", scanner.next().content.trim());
}
@Test
public void test3() {
script = "{{abc.b}}{% if x %}{{{abc}}{%endif%}";
scanner = new TokenScanner(script, config);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
Token tk = scanner.next();
assertEquals("{{{abc}}", tk.image);
assertEquals(TOKEN_EXPR_START, tk.getType());
assertEquals("{%endif%}", scanner.next().image);
}
@Test
public void test4() {
script = "{{abc.b}}{% if x %}{{!abc}}{%endif%}";
scanner = new TokenScanner(script, config);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
Token tk = scanner.next();
assertEquals("{{!abc}}", tk.image);
assertEquals(TOKEN_EXPR_START, tk.getType());
assertEquals("{%endif%}", scanner.next().image);
}
@Test
public void test5() {
script = "{{abc.b}}{% if x %}a{{abc}\\}{%endif%}";
scanner = new TokenScanner(script, config);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("a", scanner.next().content.trim());
assertEquals("{{abc}\\}{%endif%}", scanner.next().content.trim());
}
@Test
public void test7() {
script = "a{{abc.b}}{% if x %}a{{abc!}#}%}}}{%endif";
scanner = new TokenScanner(script, config);
assertEquals("a", scanner.next().image);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("a", scanner.next().content.trim());
assertEquals("{{abc!}#}%}}", scanner.next().image);
assertEquals("}", scanner.next().content.trim());
assertEquals(TOKEN_FIXED, scanner.next().getType());
}
@Test
public void test8() {
script = "a{{abc.b}}{% if x %}a{{abc}}{%endif{{";
scanner = new TokenScanner(script, config);
assertEquals("a", scanner.next().image);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("a", scanner.next().content.trim());
assertEquals(TOKEN_EXPR_START, scanner.next().getType());
assertEquals("{%endif{{", scanner.next().content.trim());
}
@Test
public void test9() {
script = "a{{abc.b}}{% if x %}a{{abc}\\}{%endif{";
scanner = new TokenScanner(script, config);
assertEquals("a", scanner.next().image);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("a", scanner.next().content.trim());
assertEquals(TOKEN_FIXED, scanner.next().getType());
}
@Test
public void test10() {
script = "a{{abc.b}}{% if x %}a{{abc}\\}{{#%endif{";
scanner = new TokenScanner(script, config);
assertEquals("a", scanner.next().image);
assertEquals("{{abc.b}}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("a", scanner.next().content.trim());
assertEquals("{{abc}\\}{", scanner.next().image);
assertEquals(TOKEN_NOTE, scanner.next().getType());
}
@Test
public void test11() {
script = "a{#abc.b#}{% if x %}a{{abc}\\}{{{{#endif{";
scanner = new TokenScanner(script, config);
assertEquals("a", scanner.next().image);
assertEquals("{#abc.b#}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("a", scanner.next().content.trim());
assertEquals("{{abc}\\}{{{", scanner.next().content.trim());
assertEquals("{#endif{", scanner.next().image);
}
@Test
public void test12() {
script = "{#abc.b#}{% if x %}a{{abc}\\}{{{{#endif{";
scanner = new TokenScanner(script, config);
assertEquals("{#abc.b#}", scanner.next().image);
assertEquals("if x", scanner.next().content.trim());
assertEquals("a", scanner.next().content.trim());
assertEquals("{{abc}\\}{{{", scanner.next().content.trim());
assertEquals(TOKEN_NOTE, scanner.next().getType());
}
@Test
public void test13() {
script = "{#abc{#.b#}{#xy{!ad!}{%dbc%}{{dff}}d{#bc#}d#}#}{% if x %}a{{abc}\\}{{{{#endif{";
scanner = new TokenScanner(script, config);
assertEquals("{#abc{#.b#}", scanner.next().image);
}
@Test
public void test14() {
script = "abc{#.b#}{#xy{!ad!}{%dbc%}{{dff}}d{#bc#}d#}#}{% if x %}a{{abc}\\}{{{{#endif{";
scanner = new TokenScanner(script, config);
assertEquals("abc", scanner.next().image);
assertEquals("{#.b#}", scanner.next().image);
assertEquals("{#xy{!ad!}{%dbc%}{{dff}}d{#bc#}", scanner.next().image);
}
@Test
public void test15() {
script = "abc{#.b#}{#xy{!ad!}{#DD#}{%dbc%}{{dff}}d{#bc#}d#}#}{% if x %}a{{abc}\\}{{{{#endif{";
scanner = new TokenScanner(script, config);
assertEquals("abc", scanner.next().image);
assertEquals("{#.b#}", scanner.next().image);
assertEquals("{#xy{!ad!}{#DD#}", scanner.next().image);
}
@Test
public void test16() {
script = "{#{#abc{#.b#}{#xy{!ad!}{%dbc%}{{dff}}d{#bc#}d#}#}{% if x %}a{{abc}\\}{{{{#endif{";
scanner = new TokenScanner(script, config);
assertEquals("{#{#abc{#.b#}", scanner.next().image);
}
@Test
public void test17() {
script = "{#abc{#.b#}{#xy{!ad!}{%dbc%}{{dff}}d{#bc#}d#}#}{% if x %}#}a#}{{abc}\\}#}{{{{#endif{";
scanner = new TokenScanner(script, config);
assertEquals("{#abc{#.b#}", scanner.next().image);
}
@Test
public void itProperlyTokenizesCommentBlocksContainingTags() {
List<Token> tokens = tokens("comment-with-tags");
assertThat(tokens).hasSize(5);
assertThat(tokens.get(4)).isInstanceOf(TagToken.class);
assertThat(StringUtils.substringBetween(tokens.get(4).toString(), "{%", "%}").trim()).isEqualTo("endif");
}
@Test
public void itProperlyTokenizesCommentWithTrailingTokens() {
List<Token> tokens = tokens("comment-plus");
assertThat(tokens).hasSize(2);
assertThat(tokens.get(tokens.size() - 1)).isInstanceOf(TextToken.class);
assertThat(StringUtils.substringBetween(tokens.get(tokens.size() - 1).toString(), "{~", "~}").trim()).isEqualTo("and here's some extra.");
}
@Test
public void itProperlyTokenizesMultilineCommentTokens() {
List<Token> tokens = tokens("multiline-comment");
assertThat(tokens).hasSize(3);
assertThat(tokens.get(2)).isInstanceOf(TextToken.class);
assertThat(StringUtils.substringBetween(tokens.get(2).toString(), "{~", "~}").trim()).isEqualTo("goodbye.");
}
@Test
public void itProperlyTokenizesCommentWithStartCommentTokenWithin() {
List<Token> tokens = tokens("comment-with-start-comment-within");
assertThat(tokens).hasSize(2);
assertThat(tokens.get(1)).isInstanceOf(TagToken.class);
assertThat(tokens.get(1).getImage()).contains("color");
}
@Test
public void itProperlyTokenizesTagTokenWithTagTokenCharsWithinString() {
List<Token> tokens = tokens("tag-with-tag-tokens-within-string");
assertThat(tokens).hasSize(1);
assertThat(tokens.get(0).getType()).isEqualTo(TokenScannerSymbols.TOKEN_TAG);
assertThat(tokens.get(0).content).contains("label='Blog Comments'");
}
@Test
public void testQuotedTag() {
List<Token> tokens = tokens("html-with-tag-in-attr");
assertThat(tokens).hasSize(3);
assertThat(tokens.get(0).getType()).isEqualTo(TokenScannerSymbols.TOKEN_FIXED);
assertThat(tokens.get(1).getType()).isEqualTo(TokenScannerSymbols.TOKEN_TAG);
assertThat(tokens.get(2).getType()).isEqualTo(TokenScannerSymbols.TOKEN_FIXED);
}
@Test
public void testEscapedQuoteWithinAttrValue() {
List<Token> tokens = tokens("tag-with-quot-in-attr");
assertThat(tokens).hasSize(1);
assertThat(tokens.get(0).getType()).isEqualTo(TokenScannerSymbols.TOKEN_TAG);
assertThat(tokens.get(0).content.trim()).isEqualTo("widget_block rich_text \"module\" overrideable=True, label='<p>We\\'ve included a great symbol</p>'");
}
@Test
public void testEscapedBackslashWithinAttrValue() {
List<Token> tokens = tokens("escape-char-tokens");
List<String> tagHelpers = tokens.stream()
.filter(t -> t.getType() == TokenScannerSymbols.TOKEN_TAG)
.map(t -> ((TagToken) t).getHelpers().trim().substring(1, 26))
.collect(Collectors.toList());
assertThat(tagHelpers).containsExactly(
"module_143819779285827357",
"module_143819780991527688",
"module_143819781983527999");
}
@Test
public void testLstripBlocks() {
config = JinjavaConfig.newBuilder()
.withLstripBlocks(true)
.withTrimBlocks(true)
.build();
List<Token> tokens = tokens("tag-with-trim-chars");
assertThat(tokens).isNotEmpty();
}
private List<Token> tokens(String fixture) {
TokenScanner t = fixture(fixture);
return Lists.newArrayList(t);
}
private TokenScanner fixture(String fixture) {
try {
TokenScanner t = new TokenScanner(
Resources.toString(Resources.getResource(String.format("parse/tokenizer/%s.jinja", fixture)),
StandardCharsets.UTF_8),
config);
return t;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}