InheritanceTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /**
  3. * @group inheritance
  4. * @group functional
  5. */
  6. class Mustache_Test_Functional_InheritanceTest extends PHPUnit_Framework_TestCase
  7. {
  8. private $mustache;
  9. public function setUp()
  10. {
  11. $this->mustache = new Mustache_Engine(array(
  12. 'pragmas' => array(Mustache_Engine::PRAGMA_BLOCKS),
  13. ));
  14. }
  15. public function getIllegalInheritanceExamples()
  16. {
  17. return array(
  18. array(
  19. array(
  20. 'foo' => '{{$baz}}default content{{/baz}}',
  21. ),
  22. array(
  23. 'bar' => 'set by user',
  24. ),
  25. '{{< foo }}{{# bar }}{{$ baz }}{{/ baz }}{{/ bar }}{{/ foo }}',
  26. ),
  27. array(
  28. array(
  29. 'foo' => '{{$baz}}default content{{/baz}}',
  30. ),
  31. array(
  32. ),
  33. '{{<foo}}{{^bar}}{{$baz}}set by template{{/baz}}{{/bar}}{{/foo}}',
  34. ),
  35. array(
  36. array(
  37. 'foo' => '{{$baz}}default content{{/baz}}',
  38. 'qux' => 'I am a partial',
  39. ),
  40. array(
  41. ),
  42. '{{<foo}}{{>qux}}{{$baz}}set by template{{/baz}}{{/foo}}',
  43. ),
  44. array(
  45. array(
  46. 'foo' => '{{$baz}}default content{{/baz}}',
  47. ),
  48. array(),
  49. '{{<foo}}{{=<% %>=}}<%={{ }}=%>{{/foo}}',
  50. ),
  51. );
  52. }
  53. public function getLegalInheritanceExamples()
  54. {
  55. return array(
  56. array(
  57. array(
  58. 'foo' => '{{$baz}}default content{{/baz}}',
  59. ),
  60. array(
  61. 'bar' => 'set by user',
  62. ),
  63. '{{<foo}}{{bar}}{{$baz}}override{{/baz}}{{/foo}}',
  64. 'override',
  65. ),
  66. array(
  67. array(
  68. 'foo' => '{{$baz}}default content{{/baz}}',
  69. ),
  70. array(
  71. ),
  72. '{{<foo}}{{! ignore me }}{{$baz}}set by template{{/baz}}{{/foo}}',
  73. 'set by template',
  74. ),
  75. array(
  76. array(
  77. 'foo' => '{{$baz}}defualt content{{/baz}}',
  78. ),
  79. array(),
  80. '{{<foo}}set by template{{$baz}}also set by template{{/baz}}{{/foo}}',
  81. 'also set by template',
  82. ),
  83. );
  84. }
  85. public function testDefaultContent()
  86. {
  87. $tpl = $this->mustache->loadTemplate('{{$title}}Default title{{/title}}');
  88. $data = array();
  89. $this->assertEquals('Default title', $tpl->render($data));
  90. }
  91. public function testDefaultContentRendersVariables()
  92. {
  93. $tpl = $this->mustache->loadTemplate('{{$foo}}default {{bar}} content{{/foo}}');
  94. $data = array(
  95. 'bar' => 'baz',
  96. );
  97. $this->assertEquals('default baz content', $tpl->render($data));
  98. }
  99. public function testDefaultContentRendersTripleMustacheVariables()
  100. {
  101. $tpl = $this->mustache->loadTemplate('{{$foo}}default {{{bar}}} content{{/foo}}');
  102. $data = array(
  103. 'bar' => '<baz>',
  104. );
  105. $this->assertEquals('default <baz> content', $tpl->render($data));
  106. }
  107. public function testDefaultContentRendersSections()
  108. {
  109. $tpl = $this->mustache->loadTemplate(
  110. '{{$foo}}default {{#bar}}{{baz}}{{/bar}} content{{/foo}}'
  111. );
  112. $data = array(
  113. 'bar' => array('baz' => 'qux'),
  114. );
  115. $this->assertEquals('default qux content', $tpl->render($data));
  116. }
  117. public function testDefaultContentRendersNegativeSections()
  118. {
  119. $tpl = $this->mustache->loadTemplate(
  120. '{{$foo}}default {{^bar}}{{baz}}{{/bar}} content{{/foo}}'
  121. );
  122. $data = array(
  123. 'foo' => array('bar' => 'qux'),
  124. 'baz' => 'three',
  125. );
  126. $this->assertEquals('default three content', $tpl->render($data));
  127. }
  128. public function testMustacheInjectionInDefaultContent()
  129. {
  130. $tpl = $this->mustache->loadTemplate(
  131. '{{$foo}}default {{#bar}}{{baz}}{{/bar}} content{{/foo}}'
  132. );
  133. $data = array(
  134. 'bar' => array('baz' => '{{qux}}'),
  135. );
  136. $this->assertEquals('default {{qux}} content', $tpl->render($data));
  137. }
  138. public function testDefaultContentRenderedInsideIncludedTemplates()
  139. {
  140. $partials = array(
  141. 'include' => '{{$foo}}default content{{/foo}}',
  142. );
  143. $this->mustache->setPartials($partials);
  144. $tpl = $this->mustache->loadTemplate(
  145. '{{<include}}{{/include}}'
  146. );
  147. $data = array();
  148. $this->assertEquals('default content', $tpl->render($data));
  149. }
  150. public function testOverriddenContent()
  151. {
  152. $partials = array(
  153. 'super' => '...{{$title}}Default title{{/title}}...',
  154. );
  155. $this->mustache->setPartials($partials);
  156. $tpl = $this->mustache->loadTemplate(
  157. '{{<super}}{{$title}}sub template title{{/title}}{{/super}}'
  158. );
  159. $data = array();
  160. $this->assertEquals('...sub template title...', $tpl->render($data));
  161. }
  162. public function testOverriddenPartial()
  163. {
  164. $partials = array(
  165. 'partial' => '|{{$stuff}}...{{/stuff}}{{$default}} default{{/default}}|',
  166. );
  167. $this->mustache->setPartials($partials);
  168. $tpl = $this->mustache->loadTemplate(
  169. 'test {{<partial}}{{$stuff}}override1{{/stuff}}{{/partial}} {{<partial}}{{$stuff}}override2{{/stuff}}{{/partial}}'
  170. );
  171. $data = array();
  172. $this->assertEquals('test |override1 default| |override2 default|', $tpl->render($data));
  173. }
  174. public function testDataDoesNotOverrideBlock()
  175. {
  176. $partials = array(
  177. 'include' => '{{$var}}var in include{{/var}}',
  178. );
  179. $this->mustache->setPartials($partials);
  180. $tpl = $this->mustache->loadTemplate(
  181. '{{<include}}{{$var}}var in template{{/var}}{{/include}}'
  182. );
  183. $data = array(
  184. 'var' => 'var in data',
  185. );
  186. $this->assertEquals('var in template', $tpl->render($data));
  187. }
  188. public function testDataDoesNotOverrideDefaultBlockValue()
  189. {
  190. $partials = array(
  191. 'include' => '{{$var}}var in include{{/var}}',
  192. );
  193. $this->mustache->setPartials($partials);
  194. $tpl = $this->mustache->loadTemplate(
  195. '{{<include}}{{/include}}'
  196. );
  197. $data = array(
  198. 'var' => 'var in data',
  199. );
  200. $this->assertEquals('var in include', $tpl->render($data));
  201. }
  202. public function testOverridePartialWithNewlines()
  203. {
  204. $partials = array(
  205. 'partial' => '{{$ballmer}}peaking{{/ballmer}}',
  206. );
  207. $this->mustache->setPartials($partials);
  208. $tpl = $this->mustache->loadTemplate(
  209. "{{<partial}}{{\$ballmer}}\npeaked\n\n:(\n{{/ballmer}}{{/partial}}"
  210. );
  211. $data = array();
  212. $this->assertEquals("peaked\n\n:(\n", $tpl->render($data));
  213. }
  214. public function testInheritIndentationWhenOverridingAPartial()
  215. {
  216. $partials = array(
  217. 'partial' => 'stop:
  218. {{$nineties}}collaborate and listen{{/nineties}}',
  219. );
  220. $this->mustache->setPartials($partials);
  221. $tpl = $this->mustache->loadTemplate(
  222. '{{<partial}}{{$nineties}}hammer time{{/nineties}}{{/partial}}'
  223. );
  224. $data = array();
  225. $this->assertEquals(
  226. 'stop:
  227. hammer time',
  228. $tpl->render($data)
  229. );
  230. }
  231. public function testOverrideOneSubstitutionButNotTheOther()
  232. {
  233. $partials = array(
  234. 'partial' => '{{$stuff}}default one{{/stuff}}, {{$stuff2}}default two{{/stuff2}}',
  235. );
  236. $this->mustache->setPartials($partials);
  237. $tpl = $this->mustache->loadTemplate(
  238. '{{<partial}}{{$stuff2}}override two{{/stuff2}}{{/partial}}'
  239. );
  240. $data = array();
  241. $this->assertEquals('default one, override two', $tpl->render($data));
  242. }
  243. public function testSuperTemplatesWithNoParameters()
  244. {
  245. $partials = array(
  246. 'include' => '{{$foo}}default content{{/foo}}',
  247. );
  248. $this->mustache->setPartials($partials);
  249. $tpl = $this->mustache->loadTemplate(
  250. '{{>include}}|{{<include}}{{/include}}'
  251. );
  252. $data = array();
  253. $this->assertEquals('default content|default content', $tpl->render($data));
  254. }
  255. public function testRecursionInInheritedTemplates()
  256. {
  257. $partials = array(
  258. 'include' => '{{$foo}}default content{{/foo}} {{$bar}}{{<include2}}{{/include2}}{{/bar}}',
  259. 'include2' => '{{$foo}}include2 default content{{/foo}} {{<include}}{{$bar}}don\'t recurse{{/bar}}{{/include}}',
  260. );
  261. $this->mustache->setPartials($partials);
  262. $tpl = $this->mustache->loadTemplate(
  263. '{{<include}}{{$foo}}override{{/foo}}{{/include}}'
  264. );
  265. $data = array();
  266. $this->assertEquals('override override override don\'t recurse', $tpl->render($data));
  267. }
  268. public function testTopLevelSubstitutionsTakePrecedenceInMultilevelInheritance()
  269. {
  270. $partials = array(
  271. 'parent' => '{{<older}}{{$a}}p{{/a}}{{/older}}',
  272. 'older' => '{{<grandParent}}{{$a}}o{{/a}}{{/grandParent}}',
  273. 'grandParent' => '{{$a}}g{{/a}}',
  274. );
  275. $this->mustache->setPartials($partials);
  276. $tpl = $this->mustache->loadTemplate(
  277. '{{<parent}}{{$a}}c{{/a}}{{/parent}}'
  278. );
  279. $data = array();
  280. $this->assertEquals('c', $tpl->render($data));
  281. }
  282. public function testMultiLevelInheritanceNoSubChild()
  283. {
  284. $partials = array(
  285. 'parent' => '{{<older}}{{$a}}p{{/a}}{{/older}}',
  286. 'older' => '{{<grandParent}}{{$a}}o{{/a}}{{/grandParent}}',
  287. 'grandParent' => '{{$a}}g{{/a}}',
  288. );
  289. $this->mustache->setPartials($partials);
  290. $tpl = $this->mustache->loadTemplate(
  291. '{{<parent}}{{/parent}}'
  292. );
  293. $data = array();
  294. $this->assertEquals('p', $tpl->render($data));
  295. }
  296. public function testIgnoreTextInsideSuperTemplatesButParseArgs()
  297. {
  298. $partials = array(
  299. 'include' => '{{$foo}}default content{{/foo}}',
  300. );
  301. $this->mustache->setPartials($partials);
  302. $tpl = $this->mustache->loadTemplate(
  303. '{{<include}} asdfasd {{$foo}}hmm{{/foo}} asdfasdfasdf {{/include}}'
  304. );
  305. $data = array();
  306. $this->assertEquals('hmm', $tpl->render($data));
  307. }
  308. public function testIgnoreTextInsideSuperTemplates()
  309. {
  310. $partials = array(
  311. 'include' => '{{$foo}}default content{{/foo}}',
  312. );
  313. $this->mustache->setPartials($partials);
  314. $tpl = $this->mustache->loadTemplate(
  315. '{{<include}} asdfasd asdfasdfasdf {{/include}}'
  316. );
  317. $data = array();
  318. $this->assertEquals('default content', $tpl->render($data));
  319. }
  320. /**
  321. * @dataProvider getIllegalInheritanceExamples
  322. * @expectedException Mustache_Exception_SyntaxException
  323. * @expectedExceptionMessage Illegal content in < parent tag
  324. */
  325. public function testIllegalInheritanceExamples($partials, $data, $template)
  326. {
  327. $this->mustache->setPartials($partials);
  328. $tpl = $this->mustache->loadTemplate($template);
  329. $tpl->render($data);
  330. }
  331. /**
  332. * @dataProvider getLegalInheritanceExamples
  333. */
  334. public function testLegalInheritanceExamples($partials, $data, $template, $expect)
  335. {
  336. $this->mustache->setPartials($partials);
  337. $tpl = $this->mustache->loadTemplate($template);
  338. $this->assertSame($expect, $tpl->render($data));
  339. }
  340. }