EngineTest.php 11 KB

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