/*
* Copyright 2015 Google Inc.
*
* 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 com.google.template.soy.jssrc.internal;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.template.soy.SoyFileSetParserBuilder;
import com.google.template.soy.SoyModule;
import com.google.template.soy.base.internal.UniqueNameGenerator;
import com.google.template.soy.error.ExplodingErrorReporter;
import com.google.template.soy.jssrc.dsl.CodeChunk;
import com.google.template.soy.shared.SharedTestUtils;
import com.google.template.soy.shared.internal.GuiceSimpleScope;
import com.google.template.soy.soytree.CallNode;
import com.google.template.soy.soytree.SoyFileSetNode;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Unit tests for {@link GenCallCodeUtils}.
*
*/
@RunWith(JUnit4.class)
public final class GenCallCodeUtilsTest {
private static final Joiner JOINER = Joiner.on('\n');
private static final Injector INJECTOR = Guice.createInjector(new SoyModule());
@Test
public void testGenCallExprForBasicCalls() {
assertThat(getCallExprTextHelper("{call some.func data=\"all\" /}"))
.isEqualTo("some.func(opt_data, null, opt_ijData)");
assertThat(
getCallExprTextHelper(
"{@param boo : ?}",
"{call some.func data=\"$boo.foo\" /}"))
.isEqualTo("some.func(opt_data.boo.foo, null, opt_ijData)");
assertThat(
getCallExprTextHelper(
"{@param moo : ?}",
"{call some.func}",
" {param goo: $moo /}",
"{/call}"))
.isEqualTo("some.func({goo: opt_data.moo}, null, opt_ijData)");
assertThat(
getCallExprTextHelper(
"{@param boo : ?}",
"{call some.func data=\"$boo\"}",
" {param goo}Blah{/param}",
"{/call}"))
.isEqualTo(
"some.func(soy.$$assignDefaults({goo: 'Blah'}, opt_data.boo), null, opt_ijData)");
String callExprText =
getCallExprTextHelper(
"{call some.func}\n"
+ " {param goo}\n"
+ " {for $i in range(3)}{$i}{/for}\n"
+ " {/param}\n"
+ "{/call}\n");
assertThat(callExprText).matches("some[.]func[(][{]goo: param[0-9]+[}], null, opt_ijData[)]");
}
@Test
public void testGenCallExprForBasicCallsWithTypedParamBlocks() {
assertThat(
getCallExprTextHelper(
"{@param boo : ?}",
"{call some.func data=\"$boo\"}",
" {param goo kind=\"html\"}Blah{/param}",
"{/call}"))
.isEqualTo(
"some.func(soy.$$assignDefaults("
+ "{goo: soydata.VERY_UNSAFE.$$ordainSanitizedHtmlForInternalBlocks('Blah')}, "
+ "opt_data.boo), null, opt_ijData)");
final String callExprText =
getCallExprTextHelper(
"{call some.func}\n"
+ " {param goo kind=\"html\"}\n"
+ " {for $i in range(3)}{$i}{/for}\n"
+ " {/param}\n"
+ "{/call}\n");
// NOTE: Soy generates a param### variable to store the output of the for loop.
assertWithMessage("Actual result: " + callExprText)
.that(
callExprText.matches(
"some[.]func[(][{]goo: soydata.VERY_UNSAFE.[$][$]"
+ "ordainSanitizedHtmlForInternalBlocks["
+ "(]param[0-9]+[)][}], null, opt_ijData[)]"))
.isTrue();
}
@Test
public void testGenCallExprForDelegateCalls() {
assertThat(getCallExprTextHelper("{delcall myDelegate data=\"all\" /}"))
.isEqualTo(
"soy.$$getDelegateFn("
+ "soy.$$getDelTemplateId('myDelegate'), '', false)(opt_data, null, opt_ijData)");
assertThat(
getCallExprTextHelper("{delcall myDelegate data=\"all\" allowemptydefault=\"true\" /}"))
.isEqualTo(
"soy.$$getDelegateFn("
+ "soy.$$getDelTemplateId('myDelegate'), '', true)(opt_data, null, opt_ijData)");
assertThat(
getCallExprTextHelper(
"{@param moo : ?}",
"{delcall my.other.delegate}",
" {param goo: $moo /}",
"{/delcall}"))
.isEqualTo(
"soy.$$getDelegateFn("
+ "soy.$$getDelTemplateId('my.other.delegate'), '', false)({goo: opt_data.moo}, "
+ "null, opt_ijData)");
}
@Test
public void testGenCallExprForDelegateVariantCalls() {
assertThat(getCallExprTextHelper("{delcall myDelegate variant=\"'voo'\" data=\"all\" /}"))
.isEqualTo(
"soy.$$getDelegateFn(soy.$$getDelTemplateId('myDelegate'), 'voo', false)"
+ "(opt_data, null, opt_ijData)");
assertThat(
getCallExprTextHelper(
"{@param voo : ?}",
"{delcall myDelegate variant=\"$voo\" data=\"all\" allowemptydefault=\"true\" /}"))
.isEqualTo(
"soy.$$getDelegateFn(soy.$$getDelTemplateId('myDelegate'), opt_data.voo, true)"
+ "(opt_data, null, opt_ijData)");
assertThat(
getCallExprTextHelper(
"{@param moo : ?}",
"{delcall my.other.delegate variant=\"'voo' + $ij.voo\"}",
" {param goo: $moo /}",
"{/delcall}"))
.isEqualTo(
"soy.$$getDelegateFn("
+ "soy.$$getDelTemplateId('my.other.delegate'), 'voo' + opt_ijData.voo, false)"
+ "({goo: opt_data.moo}, null, opt_ijData)");
}
@Test
public void testGenCallExprForDelegateCallsWithTypedParamBlocks() {
assertThat(
getCallExprTextHelper(
"{delcall my.other.delegate}",
" {param goo kind=\"html\"}Blah{/param}",
"{/delcall}"))
.isEqualTo(
"soy.$$getDelegateFn(soy.$$getDelTemplateId('my.other.delegate'), '', false)("
+ "{goo: soydata.VERY_UNSAFE.$$ordainSanitizedHtmlForInternalBlocks('Blah')}, "
+ "null, opt_ijData)");
String callExprText =
getCallExprTextHelper(
"{delcall my.other.delegate}",
" {param goo kind=\"html\"}",
" {for $i in range(3)}{$i}{/for}",
" {/param}",
"{/delcall}");
assertWithMessage("Actual text:" + callExprText)
.that(
callExprText.matches(
"soy.\\$\\$getDelegateFn\\("
+ "soy.\\$\\$getDelTemplateId\\('my.other.delegate'\\), '', false\\)"
+ "[(][{]goo: soydata.VERY_UNSAFE.[$][$]ordainSanitizedHtmlForInternalBlocks"
+ "[(]param[0-9]+[)][}], null, opt_ijData[)]"))
.isTrue();
}
@Test
public void testGenCallExprForStrictCall() {
assertThat(getCallExprTextHelper("{call some.func /}\n", ImmutableList.of("|escapeHtml")))
.isEqualTo("soy.$$escapeHtml(some.func(null, null, opt_ijData))");
}
private static String getCallExprTextHelper(String... callSourceLines) {
return getCallExprTextHelper(Joiner.on('\n').join(callSourceLines), ImmutableList.<String>of());
}
private static String getCallExprTextHelper(
String callSource, ImmutableList<String> escapingDirectives) {
SoyFileSetNode soyTree =
SoyFileSetParserBuilder.forTemplateContents(callSource)
.parse()
.fileSet();
CallNode callNode = (CallNode) SharedTestUtils.getNode(soyTree, 0);
// Manually setting the escaping directives.
callNode.setEscapingDirectiveNames(escapingDirectives);
try (GuiceSimpleScope.InScope inScope = JsSrcTestUtils.simulateNewApiCall(INJECTOR)) {
GenCallCodeUtils genCallCodeUtils = INJECTOR.getInstance(GenCallCodeUtils.class);
UniqueNameGenerator nameGenerator = JsSrcNameGenerators.forLocalVariables();
CodeChunk call =
genCallCodeUtils.gen(
callNode,
AliasUtils.IDENTITY_ALIASES,
TranslationContext.of(
SoyToJsVariableMappings.forNewTemplate(),
CodeChunk.Generator.create(nameGenerator),
nameGenerator),
ExplodingErrorReporter.get());
return call.getExpressionTestOnly();
}
}
}