EngineTest.php 12 KB

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