InheritanceTest.php 11 KB

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