/* * 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 com.google.template.soy.SoyFileSetParserBuilder; import com.google.template.soy.basetree.ParentNode; import com.google.template.soy.error.ErrorReporter; import com.google.template.soy.error.ExplodingErrorReporter; import com.google.template.soy.soytree.ForNode; import com.google.template.soy.soytree.ForeachIfemptyNode; import com.google.template.soy.soytree.ForeachNode; import com.google.template.soy.soytree.ForeachNonemptyNode; import com.google.template.soy.soytree.IfCondNode; import com.google.template.soy.soytree.IfElseNode; import com.google.template.soy.soytree.IfNode; import com.google.template.soy.soytree.LetContentNode; import com.google.template.soy.soytree.MsgFallbackGroupNode; import com.google.template.soy.soytree.MsgHtmlTagNode; import com.google.template.soy.soytree.MsgNode; import com.google.template.soy.soytree.MsgPlaceholderNode; import com.google.template.soy.soytree.PrintNode; import com.google.template.soy.soytree.RawTextNode; import com.google.template.soy.soytree.SoyFileSetNode; import com.google.template.soy.soytree.SwitchCaseNode; import com.google.template.soy.soytree.SwitchDefaultNode; import com.google.template.soy.soytree.SwitchNode; import com.google.template.soy.soytree.TemplateNode; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Unit tests for ReplaceMsgsWithGoogMsgsVisitor. * */ @RunWith(JUnit4.class) public final class ExtractMsgVariablesVisitorTest { private static TemplateNode parseTemplate(String soyCode) { ErrorReporter boom = ExplodingErrorReporter.get(); SoyFileSetNode soyTree = SoyFileSetParserBuilder.forTemplateContents(soyCode).errorReporter(boom).parse().fileSet(); new ExtractMsgVariablesVisitor().exec(soyTree); return soyTree.getChild(0).getChild(0); } /** Gets the MsgFallbackGroupNode at the specified index, unwrapping its surrounding {let} node */ private MsgFallbackGroupNode getMsgFallbackGroupNode(ParentNode<?> parent, int index) { return (MsgFallbackGroupNode) ((LetContentNode) parent.getChild(index)).getChild(0); } @Test public void testReplacement() { TemplateNode template = parseTemplate( "" + "{@param userName: ?}\n" + "{@param url: ?}\n" + "{msg desc=\"Tells the user to click a link.\"}\n" + " Hello {$userName}, please click <a href=\"{$url}\">here</a>.\n" + "{/msg}\n" + "{msg meaning=\"blah\" desc=\"A span with generated id.\" hidden=\"true\"}\n" + " <span id=\"{for $i in range(3)}{$i}{/for}\">\n" + "{/msg}\n"); MsgFallbackGroupNode gmd0 = getMsgFallbackGroupNode(template, 1); MsgNode m0 = gmd0.getChild(0); assertThat(m0.getMeaning()).isNull(); assertThat(m0.getDesc()).isEqualTo("Tells the user to click a link."); assertThat(m0.isHidden()).isFalse(); assertThat(m0.numChildren()).isEqualTo(7); assertThat(((RawTextNode) m0.getChild(0)).getRawText()).isEqualTo("Hello "); MsgPlaceholderNode gm0p1 = (MsgPlaceholderNode) m0.getChild(1); assertThat(m0.getRepPlaceholderNode("USER_NAME")).isEqualTo(gm0p1); assertThat(m0.getPlaceholderName(gm0p1)).isEqualTo("USER_NAME"); PrintNode gm0pc1 = (PrintNode) gm0p1.getChild(0); assertThat(gm0pc1.getExprText()).isEqualTo("$userName"); assertThat(((RawTextNode) m0.getChild(2)).getRawText()).isEqualTo(", please click "); MsgPlaceholderNode gm0p3 = (MsgPlaceholderNode) m0.getChild(3); assertThat(m0.getRepPlaceholderNode("START_LINK")).isEqualTo(gm0p3); assertThat(m0.getPlaceholderName(gm0p3)).isEqualTo("START_LINK"); MsgHtmlTagNode gm0pc3 = (MsgHtmlTagNode) gm0p3.getChild(0); assertThat(gm0pc3.numChildren()).isEqualTo(3); assertThat(((PrintNode) gm0pc3.getChild(1)).getExprText()).isEqualTo("$url"); assertThat(((RawTextNode) m0.getChild(4)).getRawText()).isEqualTo("here"); MsgPlaceholderNode gm0p5 = (MsgPlaceholderNode) m0.getChild(5); assertThat(m0.getRepPlaceholderNode("END_LINK")).isEqualTo(gm0p5); assertThat(m0.getPlaceholderName(gm0p5)).isEqualTo("END_LINK"); MsgHtmlTagNode gm0pc5 = (MsgHtmlTagNode) gm0p5.getChild(0); assertThat(gm0pc5.numChildren()).isEqualTo(1); assertThat(((RawTextNode) gm0pc5.getChild(0)).getRawText()).isEqualTo("</a>"); assertThat(((RawTextNode) m0.getChild(6)).getRawText()).isEqualTo("."); MsgFallbackGroupNode gmd2 = getMsgFallbackGroupNode(template, 0); MsgNode m2 = gmd2.getChild(0); assertThat(m2.getMeaning()).isEqualTo("blah"); assertThat(m2.getDesc()).isEqualTo("A span with generated id."); assertThat(m2.isHidden()).isTrue(); assertThat(m2.numChildren()).isEqualTo(1); MsgPlaceholderNode gm2p0 = (MsgPlaceholderNode) m2.getChild(0); assertThat(m2.getRepPlaceholderNode("START_SPAN")).isEqualTo(gm2p0); assertThat(m2.getPlaceholderName(gm2p0)).isEqualTo("START_SPAN"); MsgHtmlTagNode gm2pc0 = (MsgHtmlTagNode) gm2p0.getChild(0); assertThat(gm2pc0.numChildren()).isEqualTo(3); assertThat(gm2pc0.getChild(1)).isInstanceOf(ForNode.class); } @Test public void testLetPositionBasic() { TemplateNode template = parseTemplate( "" + "{@param goo: ?}\n" + "{msg desc=\"msg1\"}blah{/msg}\n" + "blah\n" + "{msg desc=\"msg2\"}{$goo}{/msg}\n" + "{$goo}\n" + "{msg desc=\"msg3\"}blah{/msg}\n"); // Expected: // [TemplateNode] // |--[MsgFallbackGroupNode] msg3 // |--[MsgFallbackGroupNode] msg2 // |--[MsgFallbackGroupNode] msg1 // |--[PrintNode] // |--[RawTextNode] "blah" // |--[PrintNode] // |--[PrintNode] $goo // +--[PrintNode] assertThat(template.numChildren()).isEqualTo(8); assertThat(getMsgFallbackGroupNode(template, 0).getChild(0).getDesc()).isEqualTo("msg3"); assertThat(getMsgFallbackGroupNode(template, 1).getChild(0).getDesc()).isEqualTo("msg2"); assertThat(getMsgFallbackGroupNode(template, 2).getChild(0).getDesc()).isEqualTo("msg1"); } @Test public void testLetPositionIf() { TemplateNode template = parseTemplate( "" + "{@param goo1: ?}\n" + "{@param goo2: ?}\n" + "{if $goo1}\n" + " {msg desc=\"msg1\"}blah{/msg}\n" + " {msg desc=\"msg2\"}blah{/msg}\n" + "{elseif $goo2}\n" + " {msg desc=\"msg3\"}blah{/msg}\n" + " {msg desc=\"msg4\"}blah{/msg}\n" + "{else}\n" + " {msg desc=\"msg5\"}blah{/msg}\n" + " {msg desc=\"msg6\"}blah{/msg}\n" + "{/if}\n"); // Expected: // [TemplateNode] // +--[IfNode] // |--[IfCondNode] $goo1 // | |--[MsgFallbackGroupNode] msg2 // | |--[MsgFallbackGroupNode] msg1 // | |--[PrintNode] // | +--[PrintNode] // |--[IfCondNode] $goo2 // | |--[MsgFallbackGroupNode] msg4 // | |--[MsgFallbackGroupNode] msg3 // | |--[PrintNode] // | +--[PrintNode] // +--[IfElseNode] // |--[MsgFallbackGroupNode] msg6 // |--[MsgFallbackGroupNode] msg5 // |--[PrintNode] // +--[PrintNode] assertThat(template.numChildren()).isEqualTo(1); IfNode ifNode = (IfNode) template.getChild(0); assertThat(ifNode.numChildren()).isEqualTo(3); IfCondNode icn0 = (IfCondNode) ifNode.getChild(0); assertThat(icn0.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(icn0, 0).getChild(0).getDesc()).isEqualTo("msg2"); assertThat(getMsgFallbackGroupNode(icn0, 1).getChild(0).getDesc()).isEqualTo("msg1"); IfCondNode icn1 = (IfCondNode) ifNode.getChild(1); assertThat(icn1.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(icn1, 0).getChild(0).getDesc()).isEqualTo("msg4"); assertThat(getMsgFallbackGroupNode(icn1, 1).getChild(0).getDesc()).isEqualTo("msg3"); IfElseNode ien2 = (IfElseNode) ifNode.getChild(2); assertThat(ien2.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(ien2, 0).getChild(0).getDesc()).isEqualTo("msg6"); assertThat(getMsgFallbackGroupNode(ien2, 1).getChild(0).getDesc()).isEqualTo("msg5"); } @Test public void testLetPositionSwitch() { TemplateNode template = parseTemplate( "" + "{@param goo: ?}\n" + "{switch $goo}\n" + " {case 0}\n" + " {msg desc=\"msg1\"}blah{/msg}\n" + " {msg desc=\"msg2\"}blah{/msg}\n" + " {case 1, 2, 3}\n" + " {msg desc=\"msg3\"}blah{/msg}\n" + " {msg desc=\"msg4\"}blah{/msg}\n" + " {default}\n" + " {msg desc=\"msg5\"}blah{/msg}\n" + " {msg desc=\"msg6\"}blah{/msg}\n" + "{/switch}\n"); // Expected: // [TemplateNode] // +--[SwitchNode] // |--[SwitchCaseNode] 0 // | |--[MsgFallbackGroupNode] msg2 // | |--[MsgFallbackGroupNode] msg1 // | |--[PrintNode] // | +--[PrintNode] // |--[SwitchCaseNode] 1, 2, 3 // | |--[MsgFallbackGroupNode] msg4 // | |--[MsgFallbackGroupNode] msg3 // | |--[PrintNode] // | +--[PrintNode] // +--[SwitchDefaultNode] // |--[MsgFallbackGroupNode] msg6 // |--[MsgFallbackGroupNode] msg5 // |--[PrintNode] // +--[PrintNode] assertThat(template.numChildren()).isEqualTo(1); SwitchNode switchNode = (SwitchNode) template.getChild(0); assertThat(switchNode.numChildren()).isEqualTo(3); SwitchCaseNode scn0 = (SwitchCaseNode) switchNode.getChild(0); assertThat(scn0.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(scn0, 0).getChild(0).getDesc()).isEqualTo("msg2"); assertThat(getMsgFallbackGroupNode(scn0, 1).getChild(0).getDesc()).isEqualTo("msg1"); SwitchCaseNode scn1 = (SwitchCaseNode) switchNode.getChild(1); assertThat(scn1.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(scn1, 0).getChild(0).getDesc()).isEqualTo("msg4"); assertThat(getMsgFallbackGroupNode(scn1, 1).getChild(0).getDesc()).isEqualTo("msg3"); SwitchDefaultNode sdn2 = (SwitchDefaultNode) switchNode.getChild(2); assertThat(sdn2.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(sdn2, 0).getChild(0).getDesc()).isEqualTo("msg6"); assertThat(getMsgFallbackGroupNode(sdn2, 1).getChild(0).getDesc()).isEqualTo("msg5"); } @Test public void testLetPositionForeach() { TemplateNode template = parseTemplate( "" + "{@param goose: ?}\n" + "{@param moo: ?}\n" + "{foreach $goo in $goose}\n" + " {msg desc=\"msg1\"}blah{/msg}\n" + " {msg desc=\"msg2\"}{$goo}{/msg}\n" + // dep on $goo " {msg desc=\"msg3\"}{$moo}{/msg}\n" + " {msg desc=\"msg4\"}{$goo}{/msg}\n" + // dep on $goo "{ifempty}\n" + " {msg desc=\"msg5\"}{$moo}{/msg}\n" + " {msg desc=\"msg6\"}blah{/msg}\n" + "{/foreach}\n"); // Expected: // [TemplateNode] // |--[MsgFallbackGroupNode] msg3 // |--[MsgFallbackGroupNode] msg1 // +--[ForeachNode] $goo in $goose // |--[ForeachNonemptyNode] // | |--[MsgFallbackGroupNode] msg4 // | |--[MsgFallbackGroupNode] msg2 // | |--[PrintNode] // | |--[PrintNode] // | |--[PrintNode] // | +--[PrintNode] // +--[ForeachIfemptyNode] // |--[MsgFallbackGroupNode] msg6 // |--[MsgFallbackGroupNode] msg5 // |--[PrintNode] // +--[PrintNode] assertThat(template.numChildren()).isEqualTo(3); assertThat(getMsgFallbackGroupNode(template, 0).getChild(0).getDesc()).isEqualTo("msg3"); assertThat(getMsgFallbackGroupNode(template, 1).getChild(0).getDesc()).isEqualTo("msg1"); ForeachNode foreachNode = (ForeachNode) template.getChild(2); ForeachNonemptyNode fnn0 = (ForeachNonemptyNode) foreachNode.getChild(0); assertThat(fnn0.numChildren()).isEqualTo(6); assertThat(getMsgFallbackGroupNode(fnn0, 0).getChild(0).getDesc()).isEqualTo("msg4"); assertThat(getMsgFallbackGroupNode(fnn0, 1).getChild(0).getDesc()).isEqualTo("msg2"); ForeachIfemptyNode fin1 = (ForeachIfemptyNode) foreachNode.getChild(1); assertThat(fin1.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(fin1, 0).getChild(0).getDesc()).isEqualTo("msg6"); assertThat(getMsgFallbackGroupNode(fin1, 1).getChild(0).getDesc()).isEqualTo("msg5"); } @Test public void testLetPositionFor() { TemplateNode template = parseTemplate( "" + "{@param moo: ?}\n" + "{for $i in range(3)}\n" + " {msg desc=\"msg1\"}blah{/msg}\n" + " {msg desc=\"msg2\"}{$i}{/msg}\n" + // dep on $i " {msg desc=\"msg3\"}{$moo}{/msg}\n" + " {msg desc=\"msg4\"}{$i}{/msg}\n" + // dep on $i "{/for}\n"); // Expected: // [TemplateNode] // |--[MsgFallbackGroupNode] msg3 // |--[MsgFallbackGroupNode] msg1 // +--[ForNode] $i in range(3) // |--[MsgFallbackGroupNode] msg4 // |--[MsgFallbackGroupNode] msg2 // |--[PrintNode] // |--[PrintNode] // |--[PrintNode] // +--[PrintNode] assertThat(template.numChildren()).isEqualTo(3); assertThat(getMsgFallbackGroupNode(template, 0).getChild(0).getDesc()).isEqualTo("msg3"); assertThat(getMsgFallbackGroupNode(template, 1).getChild(0).getDesc()).isEqualTo("msg1"); ForNode forNode = (ForNode) template.getChild(2); assertThat(forNode.numChildren()).isEqualTo(6); assertThat(getMsgFallbackGroupNode(forNode, 0).getChild(0).getDesc()).isEqualTo("msg4"); assertThat(getMsgFallbackGroupNode(forNode, 1).getChild(0).getDesc()).isEqualTo("msg2"); } @Test public void testLetPositionNested() { TemplateNode template = parseTemplate( "" + "{@param goo: ?}\n" + "{@param moose: ?}\n" + "{@param zoo: ?}\n" + "{if $goo}\n" + " {foreach $moo in $moose}\n" + " {for $i in range(3)}\n" + " {msg desc=\"msg1\"}blah{/msg}\n" + " {msg desc=\"msg2\"}{$goo}{/msg}\n" + // dep on $goo (irrelevant) " {msg desc=\"msg3\"}{$moo}{/msg}\n" + // dep on $moo " {msg desc=\"msg4\"}{$i}{/msg}\n" + // dep on $i " {msg desc=\"msg5\"}{$zoo}{/msg}\n" + " {msg desc=\"msg6\"}{$goo}{$moo}{/msg}\n" + // dep on $goo (irrelevant) and $moo " {msg desc=\"msg7\"}{$goo}{$i}{/msg}\n" + // dep on $goo (irrelevant) and $i " {msg desc=\"msg8\"}{$moo}{$i}{/msg}\n" + // dep on $moo and $i " {/for}\n" + " {/foreach}\n" + "{/if}\n" + "{msg desc=\"msg9\"}{$goo}{/msg}\n"); // dep on $goo (irrelevant) // Expected: // [TemplateNode] // |--[MsgFallbackGroupNode] msg9 // |--[IfNode] // | +--[IfCondNode] $goo // | |--[MsgFallbackGroupNode] msg5 // | |--[MsgFallbackGroupNode] msg2 // | |--[MsgFallbackGroupNode] msg1 // | +--[ForeachNode] $moo in $moose // | +--[ForeachNonemptyNode] // | |--[MsgFallbackGroupNode] msg6 // | |--[MsgFallbackGroupNode] msg3 // | +--[ForNode] // | |--[MsgFallbackGroupNode] msg8 // | |--[MsgFallbackGroupNode] msg7 // | |--[MsgFallbackGroupNode] msg4 // | |--[PrintNode] // | |--[PrintNode] // | |--[PrintNode] // | |--[PrintNode] // | |--[PrintNode] // | |--[PrintNode] // | |--[PrintNode] // | +--[PrintNode] // +--[PrintNode] assertThat(template.numChildren()).isEqualTo(3); assertThat(getMsgFallbackGroupNode(template, 0).getChild(0).getDesc()).isEqualTo("msg9"); IfCondNode ifCondNode = (IfCondNode) ((IfNode) template.getChild(1)).getChild(0); assertThat(ifCondNode.numChildren()).isEqualTo(4); assertThat(getMsgFallbackGroupNode(ifCondNode, 0).getChild(0).getDesc()).isEqualTo("msg5"); assertThat(getMsgFallbackGroupNode(ifCondNode, 1).getChild(0).getDesc()).isEqualTo("msg2"); assertThat(getMsgFallbackGroupNode(ifCondNode, 2).getChild(0).getDesc()).isEqualTo("msg1"); ForeachNonemptyNode foreachNonemptyNode = (ForeachNonemptyNode) ((ForeachNode) ifCondNode.getChild(3)).getChild(0); assertThat(foreachNonemptyNode.numChildren()).isEqualTo(3); assertThat(getMsgFallbackGroupNode(foreachNonemptyNode, 0).getChild(0).getDesc()) .isEqualTo("msg6"); assertThat(getMsgFallbackGroupNode(foreachNonemptyNode, 1).getChild(0).getDesc()) .isEqualTo("msg3"); ForNode forNode = (ForNode) foreachNonemptyNode.getChild(2); assertThat(forNode.numChildren()).isEqualTo(11); assertThat(getMsgFallbackGroupNode(forNode, 0).getChild(0).getDesc()).isEqualTo("msg8"); assertThat(getMsgFallbackGroupNode(forNode, 1).getChild(0).getDesc()).isEqualTo("msg7"); assertThat(getMsgFallbackGroupNode(forNode, 2).getChild(0).getDesc()).isEqualTo("msg4"); } }