EngineTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <?php
  2. /*
  3. * This file is part of Mustache.php.
  4. *
  5. * (c) 2010-2014 Justin Hileman
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * @group unit
  12. */
  13. class Mustache_Test_EngineTest extends Mustache_Test_FunctionalTestCase
  14. {
  15. public function testConstructor()
  16. {
  17. $logger = new Mustache_Logger_StreamLogger(tmpfile());
  18. $loader = new Mustache_Loader_StringLoader;
  19. $partialsLoader = new Mustache_Loader_ArrayLoader;
  20. $mustache = new Mustache_Engine(array(
  21. 'template_class_prefix' => '__whot__',
  22. 'cache' => self::$tempDir,
  23. 'cache_file_mode' => 777,
  24. 'logger' => $logger,
  25. 'loader' => $loader,
  26. 'partials_loader' => $partialsLoader,
  27. 'partials' => array(
  28. 'foo' => '{{ foo }}',
  29. ),
  30. 'helpers' => array(
  31. 'foo' => array($this, 'getFoo'),
  32. 'bar' => 'BAR',
  33. ),
  34. 'escape' => 'strtoupper',
  35. 'entity_flags' => ENT_QUOTES,
  36. 'charset' => 'ISO-8859-1',
  37. ));
  38. $this->assertSame($logger, $mustache->getLogger());
  39. $this->assertSame($loader, $mustache->getLoader());
  40. $this->assertSame($partialsLoader, $mustache->getPartialsLoader());
  41. $this->assertEquals('{{ foo }}', $partialsLoader->load('foo'));
  42. $this->assertContains('__whot__', $mustache->getTemplateClassName('{{ foo }}'));
  43. $this->assertEquals('strtoupper', $mustache->getEscape());
  44. $this->assertEquals(ENT_QUOTES, $mustache->getEntityFlags());
  45. $this->assertEquals('ISO-8859-1', $mustache->getCharset());
  46. $this->assertTrue($mustache->hasHelper('foo'));
  47. $this->assertTrue($mustache->hasHelper('bar'));
  48. $this->assertFalse($mustache->hasHelper('baz'));
  49. $this->assertInstanceOf('Mustache_Cache_FilesystemCache', $mustache->getCache());
  50. }
  51. public static function getFoo()
  52. {
  53. return 'foo';
  54. }
  55. public function testRender()
  56. {
  57. $source = '{{ foo }}';
  58. $data = array('bar' => 'baz');
  59. $output = 'TEH OUTPUT';
  60. $template = $this->getMockBuilder('Mustache_Template')
  61. ->disableOriginalConstructor()
  62. ->getMock();
  63. $mustache = new MustacheStub;
  64. $mustache->template = $template;
  65. $template->expects($this->once())
  66. ->method('render')
  67. ->with($data)
  68. ->will($this->returnValue($output));
  69. $this->assertEquals($output, $mustache->render($source, $data));
  70. $this->assertEquals($source, $mustache->source);
  71. }
  72. public function testSettingServices()
  73. {
  74. $logger = new Mustache_Logger_StreamLogger(tmpfile());
  75. $loader = new Mustache_Loader_StringLoader;
  76. $tokenizer = new Mustache_Tokenizer;
  77. $parser = new Mustache_Parser;
  78. $compiler = new Mustache_Compiler;
  79. $mustache = new Mustache_Engine;
  80. $cache = new Mustache_Cache_FilesystemCache(self::$tempDir);
  81. $this->assertNotSame($logger, $mustache->getLogger());
  82. $mustache->setLogger($logger);
  83. $this->assertSame($logger, $mustache->getLogger());
  84. $this->assertNotSame($loader, $mustache->getLoader());
  85. $mustache->setLoader($loader);
  86. $this->assertSame($loader, $mustache->getLoader());
  87. $this->assertNotSame($loader, $mustache->getPartialsLoader());
  88. $mustache->setPartialsLoader($loader);
  89. $this->assertSame($loader, $mustache->getPartialsLoader());
  90. $this->assertNotSame($tokenizer, $mustache->getTokenizer());
  91. $mustache->setTokenizer($tokenizer);
  92. $this->assertSame($tokenizer, $mustache->getTokenizer());
  93. $this->assertNotSame($parser, $mustache->getParser());
  94. $mustache->setParser($parser);
  95. $this->assertSame($parser, $mustache->getParser());
  96. $this->assertNotSame($compiler, $mustache->getCompiler());
  97. $mustache->setCompiler($compiler);
  98. $this->assertSame($compiler, $mustache->getCompiler());
  99. $this->assertNotSame($cache, $mustache->getCache());
  100. $mustache->setCache($cache);
  101. $this->assertSame($cache, $mustache->getCache());
  102. }
  103. /**
  104. * @group functional
  105. */
  106. public function testCache()
  107. {
  108. $mustache = new Mustache_Engine(array(
  109. 'template_class_prefix' => '__whot__',
  110. 'cache' => self::$tempDir,
  111. ));
  112. $source = '{{ foo }}';
  113. $template = $mustache->loadTemplate($source);
  114. $className = $mustache->getTemplateClassName($source);
  115. $this->assertInstanceOf($className, $template);
  116. }
  117. public function testLambdaCache()
  118. {
  119. $mustache = new MustacheStub(array(
  120. 'cache' => self::$tempDir,
  121. 'cache_lambda_templates' => true,
  122. ));
  123. $this->assertNotInstanceOf('Mustache_Cache_NoopCache', $mustache->getProtectedLambdaCache());
  124. $this->assertSame($mustache->getCache(), $mustache->getProtectedLambdaCache());
  125. }
  126. public function testWithoutLambdaCache()
  127. {
  128. $mustache = new MustacheStub(array(
  129. 'cache' => self::$tempDir
  130. ));
  131. $this->assertInstanceOf('Mustache_Cache_NoopCache', $mustache->getProtectedLambdaCache());
  132. $this->assertNotSame($mustache->getCache(), $mustache->getProtectedLambdaCache());
  133. }
  134. /**
  135. * @expectedException Mustache_Exception_InvalidArgumentException
  136. * @dataProvider getBadEscapers
  137. */
  138. public function testNonCallableEscapeThrowsException($escape)
  139. {
  140. new Mustache_Engine(array('escape' => $escape));
  141. }
  142. public function getBadEscapers()
  143. {
  144. return array(
  145. array('nothing'),
  146. array('foo', 'bar'),
  147. );
  148. }
  149. /**
  150. * @expectedException Mustache_Exception_RuntimeException
  151. */
  152. public function testImmutablePartialsLoadersThrowException()
  153. {
  154. $mustache = new Mustache_Engine(array(
  155. 'partials_loader' => new Mustache_Loader_StringLoader,
  156. ));
  157. $mustache->setPartials(array('foo' => '{{ foo }}'));
  158. }
  159. public function testMissingPartialsTreatedAsEmptyString()
  160. {
  161. $mustache = new Mustache_Engine(array(
  162. 'partials_loader' => new Mustache_Loader_ArrayLoader(array(
  163. 'foo' => 'FOO',
  164. 'baz' => 'BAZ',
  165. ))
  166. ));
  167. $this->assertEquals('FOOBAZ', $mustache->render('{{>foo}}{{>bar}}{{>baz}}', array()));
  168. }
  169. public function testHelpers()
  170. {
  171. $foo = array($this, 'getFoo');
  172. $bar = 'BAR';
  173. $mustache = new Mustache_Engine(array('helpers' => array(
  174. 'foo' => $foo,
  175. 'bar' => $bar,
  176. )));
  177. $helpers = $mustache->getHelpers();
  178. $this->assertTrue($mustache->hasHelper('foo'));
  179. $this->assertTrue($mustache->hasHelper('bar'));
  180. $this->assertTrue($helpers->has('foo'));
  181. $this->assertTrue($helpers->has('bar'));
  182. $this->assertSame($foo, $mustache->getHelper('foo'));
  183. $this->assertSame($bar, $mustache->getHelper('bar'));
  184. $mustache->removeHelper('bar');
  185. $this->assertFalse($mustache->hasHelper('bar'));
  186. $mustache->addHelper('bar', $bar);
  187. $this->assertSame($bar, $mustache->getHelper('bar'));
  188. $baz = array($this, 'wrapWithUnderscores');
  189. $this->assertFalse($mustache->hasHelper('baz'));
  190. $this->assertFalse($helpers->has('baz'));
  191. $mustache->addHelper('baz', $baz);
  192. $this->assertTrue($mustache->hasHelper('baz'));
  193. $this->assertTrue($helpers->has('baz'));
  194. // ... and a functional test
  195. $tpl = $mustache->loadTemplate('{{foo}} - {{bar}} - {{#baz}}qux{{/baz}}');
  196. $this->assertEquals('foo - BAR - __qux__', $tpl->render());
  197. $this->assertEquals('foo - BAR - __qux__', $tpl->render(array('qux' => "won't mess things up")));
  198. }
  199. public static function wrapWithUnderscores($text)
  200. {
  201. return '__'.$text.'__';
  202. }
  203. /**
  204. * @expectedException Mustache_Exception_InvalidArgumentException
  205. */
  206. public function testSetHelpersThrowsExceptions()
  207. {
  208. $mustache = new Mustache_Engine;
  209. $mustache->setHelpers('monkeymonkeymonkey');
  210. }
  211. /**
  212. * @expectedException Mustache_Exception_InvalidArgumentException
  213. */
  214. public function testSetLoggerThrowsExceptions()
  215. {
  216. $mustache = new Mustache_Engine;
  217. $mustache->setLogger(new StdClass);
  218. }
  219. public function testLoadPartialCascading()
  220. {
  221. $loader = new Mustache_Loader_ArrayLoader(array(
  222. 'foo' => 'FOO',
  223. ));
  224. $mustache = new Mustache_Engine(array('loader' => $loader));
  225. $tpl = $mustache->loadTemplate('foo');
  226. $this->assertSame($tpl, $mustache->loadPartial('foo'));
  227. $mustache->setPartials(array(
  228. 'foo' => 'f00',
  229. ));
  230. // setting partials overrides the default template loading fallback.
  231. $this->assertNotSame($tpl, $mustache->loadPartial('foo'));
  232. // but it didn't overwrite the original template loader templates.
  233. $this->assertSame($tpl, $mustache->loadTemplate('foo'));
  234. }
  235. public function testPartialLoadFailLogging()
  236. {
  237. $name = tempnam(sys_get_temp_dir(), 'mustache-test');
  238. $mustache = new Mustache_Engine(array(
  239. 'logger' => new Mustache_Logger_StreamLogger($name, Mustache_Logger::WARNING),
  240. 'partials' => array(
  241. 'foo' => 'FOO',
  242. 'bar' => 'BAR',
  243. ),
  244. ));
  245. $result = $mustache->render('{{> foo }}{{> bar }}{{> baz }}', array());
  246. $this->assertEquals('FOOBAR', $result);
  247. $this->assertContains('WARNING: Partial not found: "baz"', file_get_contents($name));
  248. }
  249. public function testCacheWarningLogging()
  250. {
  251. list($name, $mustache) = $this->getLoggedMustache(Mustache_Logger::WARNING);
  252. $mustache->render('{{ foo }}', array('foo' => 'FOO'));
  253. $this->assertContains('WARNING: Template cache disabled, evaluating', file_get_contents($name));
  254. }
  255. public function testLoggingIsNotTooAnnoying()
  256. {
  257. list($name, $mustache) = $this->getLoggedMustache();
  258. $mustache->render('{{ foo }}{{> bar }}', array('foo' => 'FOO'));
  259. $this->assertEmpty(file_get_contents($name));
  260. }
  261. public function testVerboseLoggingIsVerbose()
  262. {
  263. list($name, $mustache) = $this->getLoggedMustache(Mustache_Logger::DEBUG);
  264. $mustache->render('{{ foo }}{{> bar }}', array('foo' => 'FOO'));
  265. $log = file_get_contents($name);
  266. $this->assertContains("DEBUG: Instantiating template: ", $log);
  267. $this->assertContains("WARNING: Partial not found: \"bar\"", $log);
  268. }
  269. private function getLoggedMustache($level = Mustache_Logger::ERROR)
  270. {
  271. $name = tempnam(sys_get_temp_dir(), 'mustache-test');
  272. $mustache = new Mustache_Engine(array(
  273. 'logger' => new Mustache_Logger_StreamLogger($name, $level)
  274. ));
  275. return array($name, $mustache);
  276. }
  277. }
  278. class MustacheStub extends Mustache_Engine
  279. {
  280. public $source;
  281. public $template;
  282. public function loadTemplate($source)
  283. {
  284. $this->source = $source;
  285. return $this->template;
  286. }
  287. public function getProtectedLambdaCache()
  288. {
  289. return $this->getLambdaCache();
  290. }
  291. }