HandlebarsTest

Class Handlebars_Class.

Defined (4)

The class is defined in the following location(s).

/vendor/calderawp/metaplate-core/vendor/xamin/handlebars.php/tests/fixture/Handlebars/Test.php  
  1. class Test 
  2.  
/vendor/calderawp/metaplate-core/vendor/xamin/handlebars.php/tests/Xamin/HandlebarsTest.php  
  1. class HandlebarsTest extends \PHPUnit_Framework_TestCase 
  2. public function setUp() 
  3. \Handlebars\Autoloader::register(); 
  4.  
  5. /** 
  6. * Test handlebars autoloader 
  7. * @return void 
  8. */ 
  9. public function testAutoLoad() 
  10. Handlebars\Autoloader::register(realpath(__DIR__ . '/../fixture/')); 
  11.  
  12. $this->assertTrue(class_exists('Handlebars\\Test')); 
  13. $this->assertTrue(class_exists('\\Handlebars\\Test')); 
  14. $this->assertTrue(class_exists('Handlebars\\Example\\Test')); 
  15. $this->assertTrue(class_exists('\\Handlebars\\Example\\Test')); 
  16. $this->assertFalse(class_exists('\\Another\\Example\\Test')); 
  17.  
  18. /** 
  19. * Test basic tags 
  20. * @param string $src handlebars source 
  21. * @param array $data data 
  22. * @param string $result expected data 
  23. * @dataProvider simpleTagdataProvider 
  24. * @return void 
  25. */ 
  26. public function testBasicTags($src, $data, $result) 
  27. $loader = new \Handlebars\Loader\StringLoader(); 
  28. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  29. $this->assertEquals($result, $engine->render($src, $data)); 
  30.  
  31. /** 
  32. * Simple tag provider 
  33. * @return array 
  34. */ 
  35. public function simpleTagdataProvider() 
  36. return array( 
  37. array( 
  38. '{{! This is comment}}',  
  39. array(),  
  40. '' 
  41. ),  
  42. array( 
  43. '{{data}}',  
  44. array('data' => 'result'),  
  45. 'result' 
  46. ),  
  47. array( 
  48. '{{data.key}}',  
  49. array('data' => array('key' => 'result')),  
  50. 'result' 
  51. ),  
  52. array( 
  53. '{{data.length}}',  
  54. array("data" => array(1, 2, 3, 4)),  
  55. '4' 
  56. ),  
  57. array( 
  58. '{{data.length}}',  
  59. array("data" => (object)array(1, 2, 3, 4)),  
  60. '' 
  61. ),  
  62. array( 
  63. '{{data.length}}',  
  64. array("data" => array("length" => "15 inches", "test", "test", "test")),  
  65. "15 inches" 
  66. ),  
  67. array( 
  68. '{{data.0}}',  
  69. array("data" => array(1, 2, 3, 4)),  
  70. '1' 
  71. ),  
  72. array( 
  73. '{{data.property.3}}',  
  74. array("data" => array("property" => array(1, 2, 3, 4))),  
  75. '4' 
  76. ),  
  77. array( 
  78. '{{data.unsafe}}',  
  79. array('data' => array('unsafe' => '<strong>Test</strong>')),  
  80. '<strong>Test</strong>' 
  81. ),  
  82. array( 
  83. '{{{data.safe}}}',  
  84. array('data' => array('safe' => '<strong>Test</strong>')),  
  85. '<strong>Test</strong>' 
  86. ),  
  87. array( 
  88. "\{{data}}", // is equal to \\{{data}} 
  89. array('data' => 'foo'),  
  90. '{{data}}',  
  91. ),  
  92. array( 
  93. '\\\\{{data}}',  
  94. array('data' => 'foo'),  
  95. '\\\\foo' 
  96. ),  
  97. array( 
  98. '\\\{{data}}', // is equal to \\\\{{data}} in php 
  99. array('data' => 'foo'),  
  100. '\\\\foo' 
  101. ),  
  102. array( 
  103. '\{{{data}}}',  
  104. array('data' => 'foo'),  
  105. '{{{data}}}' 
  106. ),  
  107. array( 
  108. '\pi',  
  109. array(),  
  110. '\pi' 
  111. ),  
  112. array( 
  113. '\\\\\\\\qux',  
  114. array(),  
  115. '\\\\\\\\qux' 
  116. ),  
  117. array( 
  118. "var jsVar = 'It\'s a phrase in apos';",  
  119. array(),  
  120. "var jsVar = 'It\'s a phrase in apos';" 
  121. ),  
  122. array( 
  123. 'var jsVar = "A \"quoted\" text";',  
  124. array(),  
  125. 'var jsVar = "A \"quoted\" text";',  
  126. ),  
  127. array( 
  128. '{{#if first}}The first{{else}}{{#if second}}The second{{/if}}{{/if}}',  
  129. array('first' => false, 'second' => true),  
  130. 'The second' 
  131. ); 
  132.  
  133. /** 
  134. * Test helpers (internal helpers) 
  135. * @param string $src handlebars source 
  136. * @param array $data data 
  137. * @param string $result expected data 
  138. * @dataProvider internalHelpersdataProvider 
  139. * @return void 
  140. */ 
  141. public function testSimpleHelpers($src, $data, $result) 
  142. $loader = new \Handlebars\Loader\StringLoader(); 
  143. $helpers = new \Handlebars\Helpers(); 
  144. $engine = new \Handlebars\Handlebars(array('loader' => $loader, 'helpers' => $helpers)); 
  145.  
  146. $this->assertEquals($result, $engine->render($src, $data)); 
  147.  
  148. /** 
  149. * Simple helpers provider 
  150. * @return array 
  151. */ 
  152. public function internalHelpersdataProvider() 
  153. return array( 
  154. array( 
  155. '{{#if data}}Yes{{/if}}',  
  156. array('data' => true),  
  157. 'Yes' 
  158. ),  
  159. # see the issue #76 
  160. array( 
  161. '{{#if data}}0{{/if}}',  
  162. array('data' => true),  
  163. '0' 
  164. ),  
  165. array( 
  166. '{{#if data}}Yes{{/if}}',  
  167. array('data' => false),  
  168. '' 
  169. ),  
  170. array( 
  171. '{{#with data}}{{key}}{{/with}}',  
  172. array('data' => array('key' => 'result')),  
  173. 'result' 
  174. ),  
  175. array( 
  176. '{{#each data}}{{this}}{{/each}}',  
  177. array('data' => array(1, 2, 3, 4)),  
  178. '1234' 
  179. ),  
  180. array( 
  181. '{{#each data}}{{@key}}{{/each}}',  
  182. array('data' => array('the_only_key' => 1)),  
  183. 'the_only_key' 
  184. ),  
  185. array( 
  186. '{{#each data}}{{@key}}=>{{this}}{{/each}}',  
  187. array('data' => array('key1' => 1, 'key2' => 2, )),  
  188. 'key1=>1key2=>2' 
  189. ),  
  190. array( 
  191. '{{#each data}}{{@key}}=>{{this}}{{/each}}',  
  192. array('data' => new \ArrayIterator(array('key1' => 1, 'key2' => 2))),  
  193. 'key1=>1key2=>2' 
  194. ),  
  195. array( 
  196. '{{#each data}}{{@index}}=>{{this}}, {{/each}}',  
  197. array('data' => array('key1' => 1, 'key2' => 2, )),  
  198. '0=>1, 1=>2, ' 
  199. ),  
  200. array( 
  201. '{{#each data}}{{#if @first}}the first is {{this}}{{/if}}{{/each}}',  
  202. array('data' => array('one', 'two', 'three')),  
  203. 'the first is one' 
  204. ),  
  205. array( 
  206. '{{#each data}}{{#if @last}}the last is {{this}}{{/if}}{{/each}}',  
  207. array('data' => array('one', 'two', 'three')),  
  208. 'the last is three' 
  209. ),  
  210. array( 
  211. '{{#each data}}{{this}}{{else}}fail{{/each}}',  
  212. array('data' => array(1, 2, 3, 4)),  
  213. '1234' 
  214. ),  
  215. array( 
  216. '{{#each data}}fail{{else}}ok{{/each}}',  
  217. array('data' => false),  
  218. 'ok' 
  219. ),  
  220. array( 
  221. '{{#unless data}}ok{{/unless}}',  
  222. array('data' => true),  
  223. '' 
  224. ),  
  225. array( 
  226. '{{#unless data}}ok{{/unless}}',  
  227. array('data' => false),  
  228. 'ok' 
  229. ),  
  230. array( 
  231. '{{#unless data}}ok{{else}}fail{{/unless}}',  
  232. array('data' => false),  
  233. 'ok' 
  234. ),  
  235. array( 
  236. '{{#unless data}}fail{{else}}ok{{/unless}}',  
  237. array('data' => true),  
  238. 'ok' 
  239. ),  
  240. array( 
  241. '{{#bindAttr data}}',  
  242. array(),  
  243. 'data' 
  244. ),  
  245. array( 
  246. '{{#if 1}}ok{{else}}fail{{/if}}',  
  247. array(),  
  248. 'ok' 
  249. ),  
  250. array( 
  251. '{{#if 0}}ok{{else}}fail{{/if}}',  
  252. array(),  
  253. 'fail' 
  254. ),  
  255. array( 
  256. ' {{~#if 1}}OK {{~else~}} NO {{~/if~}} END',  
  257. array(),  
  258. 'OKEND' 
  259. ),  
  260. array( 
  261. 'XX {{~#bindAttr data}} XX',  
  262. array(),  
  263. 'XXdata XX' 
  264. ),  
  265. array( 
  266. '{{#each data}}{{#if @last}}the last is 
  267. {{~this}}{{/if}}{{/each}}',  
  268. array('data' => array('one', 'two', 'three')),  
  269. 'the last isthree' 
  270. ),  
  271. array( 
  272. '{{#with data}} 
  273.  
  274. {{~key~}} 
  275.  
  276. {{/with}}',  
  277. array('data' => array('key' => 'result')),  
  278. 'result' 
  279. ),  
  280. array( 
  281. '{{= (( )) =}}((#if 1))OK((else))NO((/if))',  
  282. array(),  
  283. 'OK' 
  284. ),  
  285. array( 
  286. '{{#each data~}} {{this}} {{~/each}}',  
  287. array('data' => array(1, 2, 3, 4)),  
  288. '1234' 
  289. ),  
  290. array( 
  291. '{{#each data}}{{this}} {{~/each}}',  
  292. array('data' => array(1, 2, 3, 4)),  
  293. '1234' 
  294. ),  
  295. array( 
  296. '{{#each data~}} {{this}}{{/each}}',  
  297. array('data' => array(1, 2, 3, 4)),  
  298. '1234' 
  299. ),  
  300. array( '{{#if first}}The first{{else}}{{#if second}}The second{{/if}}{{/if}}',  
  301. array('first' => false, 'second' => true),  
  302. 'The second' 
  303. ); 
  304.  
  305. /** 
  306. * Management helpers 
  307. */ 
  308. public function testHelpersManagement() 
  309. $helpers = new \Handlebars\Helpers(array('test' => function () { 
  310. }), false); 
  311. $engine = new \Handlebars\Handlebars(array('helpers' => $helpers)); 
  312. $this->assertTrue(is_callable($engine->getHelper('test'))); 
  313. $this->assertTrue($engine->hasHelper('test')); 
  314. $engine->removeHelper('test'); 
  315. $this->assertFalse($engine->hasHelper('test')); 
  316.  
  317. /** 
  318. * Custom helper test 
  319. */ 
  320. public function testCustomHelper() 
  321. $loader = new \Handlebars\Loader\StringLoader(); 
  322. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  323. $engine->addHelper('test', function () { 
  324. return 'Test helper is called'; 
  325. }); 
  326. $this->assertEquals('Test helper is called', $engine->render('{{#test}}', array())); 
  327. $this->assertEquals('Test helper is called', $engine->render('{{test}}', array())); 
  328.  
  329. $engine->addHelper('test2', function ($template, $context, $arg) { 
  330. return 'Test helper is called with ' . $arg; 
  331. }); 
  332. $this->assertEquals('Test helper is called with a b c', $engine->render('{{#test2 a b c}}', array())); 
  333. $this->assertEquals('Test helper is called with a b c', $engine->render('{{test2 a b c}}', array())); 
  334.  
  335. $engine->addHelper('renderme', function () { 
  336. return new \Handlebars\String("{{test}}"); 
  337. }); 
  338. $this->assertEquals('Test helper is called', $engine->render('{{#renderme}}', array())); 
  339.  
  340. $engine->addHelper('dontrenderme', function () { 
  341. return "{{test}}"; 
  342. }); 
  343. $this->assertEquals('{{test}}', $engine->render('{{#dontrenderme}}', array())); 
  344.  
  345. $engine->addHelper('markupHelper', function () { 
  346. return '<strong>Test</strong>'; 
  347. }); 
  348. $this->assertEquals('<strong>Test</strong>', $engine->render('{{{markupHelper}}}', array())); 
  349. $this->assertEquals('<strong>Test</strong>', $engine->render('{{markupHelper}}', array())); 
  350.  
  351. $engine->addHelper('safeStringTest', function () { 
  352. return new \Handlebars\SafeString('<strong>Test</strong>'); 
  353. }); 
  354. $this->assertEquals('<strong>Test</strong>', $engine->render('{{safeStringTest}}', array())); 
  355.  
  356. $engine->addHelper('argsTest', function ($template, $context, $arg) { 
  357. $parsedArgs = $template->parseArguments($arg); 
  358.  
  359. return implode(' ', $parsedArgs); 
  360. }); 
  361. $this->assertEquals("a \"b\" c", $engine->render('{{{argsTest "a" "\"b\"" \'c\'}}}', array())); 
  362.  
  363. // This is just a fun thing to do :) 
  364. $that = $this; 
  365. $engine->addHelper('stopToken',  
  366. function ($template, $context, $arg) use ($that) { 
  367. /** @var $template \Handlebars\Template */ 
  368. $parsedArgs = $template->parseArguments($arg); 
  369. $first = array_shift($parsedArgs); 
  370. $last = array_shift($parsedArgs); 
  371. if ($last == 'yes') { 
  372. $template->setStopToken($first); 
  373. $that->assertEquals($first, $template->getStopToken()); 
  374. $buffer = $template->render($context); 
  375. $template->setStopToken(false); 
  376. $template->discard($context); 
  377. } else { 
  378. $template->setStopToken($first); 
  379. $that->assertEquals($first, $template->getStopToken()); 
  380. $template->discard($context); 
  381. $template->setStopToken(false); 
  382. $buffer = $template->render($context); 
  383.  
  384. return $buffer; 
  385. }); 
  386.  
  387. $this->assertEquals("Used", $engine->render('{{# stopToken fun no}}Not used{{ fun }}Used{{/stopToken }}', array())); 
  388. $this->assertEquals("Not used", $engine->render('{{# stopToken any yes}}Not used{{ any }}Used{{/stopToken }}', array())); 
  389.  
  390. $this->setExpectedException('InvalidArgumentException'); 
  391. $engine->getHelpers()->call('invalid', $engine->loadTemplate(''), new \Handlebars\Context(), '', ''); 
  392.  
  393. public function testInvalidHelperMustacheStyle() 
  394. $this->setExpectedException('RuntimeException'); 
  395. $loader = new \Handlebars\Loader\StringLoader(); 
  396. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  397. $engine->render('{{#NOTVALID}}XXX{{/NOTVALID}}', array()); 
  398.  
  399. public function testInvalidHelper() 
  400. $this->setExpectedException('RuntimeException'); 
  401. $loader = new \Handlebars\Loader\StringLoader(); 
  402. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  403. $engine->render('{{#NOTVALID argument}}XXX{{/NOTVALID}}', array()); 
  404.  
  405. /** 
  406. * Test mustache style loop and if 
  407. */ 
  408. public function testMustacheStyle() 
  409. $loader = new \Handlebars\Loader\StringLoader(); 
  410. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  411. $this->assertEquals('yes', $engine->render('{{#x}}yes{{/x}}', array('x' => true))); 
  412. $this->assertEquals('', $engine->render('{{#x}}yes{{/x}}', array('x' => false))); 
  413. $this->assertEquals('yes', $engine->render('{{^x}}yes{{/x}}', array('x' => false))); 
  414. $this->assertEquals('', $engine->render('{{^x}}yes{{/x}}', array('x' => true))); 
  415. $this->assertEquals('1234', $engine->render('{{#x}}{{this}}{{/x}}', array('x' => array(1, 2, 3, 4)))); 
  416. $this->assertEquals('012', $engine->render('{{#x}}{{@index}}{{/x}}', array('x' => array('a', 'b', 'c')))); 
  417. $this->assertEquals('abc', $engine->render('{{#x}}{{@key}}{{/x}}', array('x' => array('a' => 1, 'b' => 2, 'c' => 3)))); 
  418. $this->assertEquals('the_only_key', $engine->render('{{#x}}{{@key}}{{/x}}', array('x' => array('the_only_key' => 1)))); 
  419. $std = new stdClass(); 
  420. $std->value = 1; 
  421. $this->assertEquals('1', $engine->render('{{#x}}{{value}}{{/x}}', array('x' => $std))); 
  422. $this->assertEquals('1', $engine->render('{{{x}}}', array('x' => 1))); 
  423.  
  424. /** 
  425. * @expectedException \LogicException 
  426. */ 
  427. public function testParserException() 
  428. $loader = new \Handlebars\Loader\StringLoader(); 
  429. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  430. $engine->render('{{#test}}{{#test2}}{{/test}}{{/test2}}', array()); 
  431.  
  432. /** 
  433. * Test add/get/has/clear functions on helper class 
  434. */ 
  435. public function testHelpersClass() 
  436. $helpers = new \Handlebars\Helpers(); 
  437. $helpers->add('test', function () { 
  438. }); 
  439. $this->assertTrue($helpers->has('test')); 
  440. $this->assertTrue(isset($helpers->test)); 
  441. $this->assertFalse($helpers->isEmpty()); 
  442. $helpers->test2 = function () { 
  443. }; 
  444. $this->assertTrue($helpers->has('test2')); 
  445. $this->assertTrue(isset($helpers->test2)); 
  446. $this->assertFalse($helpers->isEmpty()); 
  447. unset($helpers->test2); 
  448. $this->assertFalse($helpers->has('test2')); 
  449. $this->assertFalse(isset($helpers->test2)); 
  450. $helpers->clear(); 
  451. $this->assertFalse($helpers->has('test')); 
  452. $this->assertFalse(isset($helpers->test)); 
  453. $this->assertTrue($helpers->isEmpty()); 
  454.  
  455. /** 
  456. * @expectedException \InvalidArgumentException 
  457. */ 
  458. public function testHelperWrongConstructor() 
  459. $helper = new \Handlebars\Helpers("helper"); 
  460.  
  461. /** 
  462. * @expectedException \InvalidArgumentException 
  463. */ 
  464. public function testHelperWrongCallable() 
  465. $helper = new \Handlebars\Helpers(); 
  466. $helper->add('test', 1); 
  467.  
  468. /** 
  469. * @expectedException \InvalidArgumentException 
  470. */ 
  471. public function testHelperWrongGet() 
  472. $helper = new \Handlebars\Helpers(); 
  473. $x = $helper->test; 
  474.  
  475. /** 
  476. * @expectedException \InvalidArgumentException 
  477. */ 
  478. public function testHelperWrongUnset() 
  479. $helper = new \Handlebars\Helpers(); 
  480. unset($helper->test); 
  481.  
  482. /** 
  483. * test String class 
  484. */ 
  485. public function testStringClass() 
  486. $string = new \Handlebars\String('test'); 
  487. $this->assertEquals('test', $string->getString()); 
  488. $string->setString('new'); 
  489. $this->assertEquals('new', $string->getString()); 
  490.  
  491. /** 
  492. * @param $dir 
  493. * @return bool 
  494. */ 
  495. private function delTree($dir) 
  496. $files = array_diff(scandir($dir), array('.', '..')); 
  497. foreach ($files as $file) { 
  498. (is_dir("$dir/$file")) ? $this->delTree("$dir/$file") : unlink("$dir/$file"); 
  499.  
  500. return rmdir($dir); 
  501.  
  502. /** 
  503. * Its not a good test :) but ok 
  504. */ 
  505. public function testCacheSystem() 
  506. $path = sys_get_temp_dir() . '/__cache__handlebars'; 
  507.  
  508. @$this->delTree($path); 
  509.  
  510. $dummy = new \Handlebars\Cache\Disk($path); 
  511. $engine = new \Handlebars\Handlebars(array('cache' => $dummy)); 
  512. $this->assertEquals(0, count(glob($path . '/*'))); 
  513. $engine->render('test', array()); 
  514. $this->assertEquals(1, count(glob($path . '/*'))); 
  515.   
  516. public function testArrayLoader() 
  517. $loader = new \Handlebars\Loader\ArrayLoader(array('test' => 'HELLO')); 
  518. $loader->addTemplate('another', 'GOODBYE'); 
  519. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  520. $this->assertEquals($engine->render('test', array()), 'HELLO'); 
  521. $this->assertEquals($engine->render('another', array()), 'GOODBYE'); 
  522.   
  523. $this->setExpectedException('RuntimeException'); 
  524. $engine->render('invalid-template', array()); 
  525.   
  526. /** 
  527. * Test file system loader 
  528. */ 
  529. public function testFileSystemLoader() 
  530. $loader = new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/data')); 
  531. $engine = new \Handlebars\Handlebars(); 
  532. $engine->setLoader($loader); 
  533. $this->assertEquals('test', $engine->render('loader', array())); 
  534.  
  535. /** 
  536. * Test file system loader 
  537. */ 
  538. public function testFileSystemLoaderMultipleFolder() 
  539. $paths = array( 
  540. realpath(__DIR__ . '/../fixture/data'),  
  541. realpath(__DIR__ . '/../fixture/another') 
  542. ); 
  543.  
  544. $options = array( 
  545. 'prefix' => '__',  
  546. 'extension' => 'hb' 
  547. ); 
  548. $loader = new \Handlebars\Loader\FilesystemLoader($paths, $options); 
  549. $engine = new \Handlebars\Handlebars(); 
  550. $engine->setLoader($loader); 
  551. $this->assertEquals('test_extra', $engine->render('loader', array())); 
  552. $this->assertEquals('another_extra', $engine->render('another', array())); 
  553.  
  554. /** 
  555. * Test file system loader 
  556. * @expectedException \InvalidArgumentException 
  557. */ 
  558. public function testFileSystemLoaderNotFound() 
  559. $loader = new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/data')); 
  560. $engine = new \Handlebars\Handlebars(); 
  561. $engine->setLoader($loader); 
  562. $engine->render('invalid_file', array()); 
  563.  
  564. /** 
  565. * Test file system loader 
  566. * @expectedException \RuntimeException 
  567. */ 
  568. public function testFileSystemLoaderInvalidFolder() 
  569. new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/') . 'invalid/path'); 
  570.  
  571. /** 
  572. * Test partial loader 
  573. */ 
  574. public function testPartialLoader() 
  575. $loader = new \Handlebars\Loader\StringLoader(); 
  576. $partialLoader = new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/data')); 
  577. $engine = new \Handlebars\Handlebars(); 
  578. $engine->setLoader($loader); 
  579. $engine->setPartialsLoader($partialLoader); 
  580.  
  581. $this->assertEquals('test', $engine->render('{{>loader}}', array())); 
  582.  
  583. public function testPartial() 
  584. $loader = new \Handlebars\Loader\StringLoader(); 
  585. $partialLoader = new \Handlebars\Loader\ArrayLoader(array('test' => '{{key}}', 'bar' => 'its foo')); 
  586. $partialAliasses = array('foo' => 'bar'); 
  587. $engine = new \Handlebars\Handlebars( 
  588. array( 
  589. 'loader' => $loader,  
  590. 'partials_loader' => $partialLoader,  
  591. 'partials_alias' => $partialAliasses 
  592. ); 
  593.  
  594. $this->assertEquals('HELLO', $engine->render('{{>test parameter}}', array('parameter' => array('key' => 'HELLO')))); 
  595. $this->assertEquals('its foo', $engine->render('{{>foo}}', array())); 
  596. $engine->registerPartial('foo-again', 'bar'); 
  597. $this->assertEquals('its foo', $engine->render('{{>foo-again}}', array())); 
  598. $engine->unRegisterPartial('foo-again'); 
  599.  
  600. $this->setExpectedException('RuntimeException'); 
  601. $engine->render('{{>foo-again}}', array()); 
  602.  
  603. /** 
  604. * test variable access 
  605. */ 
  606. public function testVariableAccess() 
  607. $loader = new \Handlebars\Loader\StringLoader(); 
  608. $engine = \Handlebars\Handlebars::factory(); 
  609. $engine->setLoader($loader); 
  610.  
  611. $var = new \StdClass(); 
  612. $var->x = 'var-x'; 
  613. $var->y = array( 
  614. 'z' => 'var-y-z' 
  615. ); 
  616. $this->assertEquals('test', $engine->render('{{var}}', array('var' => 'test'))); 
  617. $this->assertEquals('var-x', $engine->render('{{var.x}}', array('var' => $var))); 
  618. $this->assertEquals('var-y-z', $engine->render('{{var.y.z}}', array('var' => $var))); 
  619. // Access parent context in with helper 
  620. $this->assertEquals('var-x', $engine->render('{{#with var.y}}{{../var.x}}{{/with}}', array('var' => $var))); 
  621. // Reference array as string 
  622. $this->assertEquals('Array', $engine->render('{{var}}', array('var' => array('test')))); 
  623.  
  624. $obj = new DateTime(); 
  625. $time = $obj->getTimestamp(); 
  626. $this->assertEquals($time, $engine->render('{{time.getTimestamp}}', array('time' => $obj))); 
  627.  
  628. public function testContext() 
  629. $test = new stdClass(); 
  630. $test->value = 'value'; 
  631. $test->array = array( 
  632. 'a' => '1',  
  633. 'b' => '2',  
  634. '!"#%&\'()*+, ./;<=>@[\\^`{|}~ ' => '3',  
  635. ); 
  636. $context = new \Handlebars\Context($test); 
  637. $this->assertEquals('value', $context->get('value')); 
  638. $this->assertEquals('value', $context->get('value', true)); 
  639. $this->assertEquals('value', $context->get('[value]', true)); 
  640. $this->assertEquals('1', $context->get('array.a', true)); 
  641. $this->assertEquals('2', $context->get('array.b', true)); 
  642. $this->assertEquals('3', $context->get('array.[!"#%&\'()*+, ./;<=>@[\\^`{|}~ ]', true)); 
  643. $new = array('value' => 'new value'); 
  644. $context->push($new); 
  645. $this->assertEquals('new value', $context->get('value')); 
  646. $this->assertEquals('new value', $context->get('value', true)); 
  647. $this->assertEquals('value', $context->get('../value')); 
  648. $this->assertEquals('value', $context->get('../value', true)); 
  649. $this->assertEquals($new, $context->last()); 
  650. $this->assertEquals($new, $context->get('.')); 
  651. $this->assertEquals($new, $context->get('this')); 
  652. $this->assertEquals($new, $context->get('this.')); 
  653. $this->assertEquals($test, $context->get('../.')); 
  654. $context->pop(); 
  655. $this->assertEquals('value', $context->get('value')); 
  656. $this->assertEquals('value', $context->get('value', true)); 
  657.  
  658. /** 
  659. * @expectedException \InvalidArgumentException 
  660. * @dataProvider getInvalidData 
  661. */ 
  662. public function testInvalidAccessContext($invalid) 
  663. $context = new \Handlebars\Context(array()); 
  664. $this->assertEmpty($context->get($invalid)); 
  665. $context->get($invalid, true); 
  666.  
  667. public function getInvalidData() 
  668. return array( 
  669. array('../../data'),  
  670. array('data'),  
  671. array(''),  
  672. array('data.key.key'),  
  673. ); 
  674.  
  675. /** 
  676. * Test for proper handling of the length property 
  677. **/ 
  678. public function testArrayLengthEmulation() 
  679.  
  680. $data = array("numbers" => array(1, 2, 3, 4),  
  681. "object" => (object)array("prop1" => "val1", "prop2" => "val2"),  
  682. "object_with_length_property" => (object)array("length" => "15cm") 
  683. ); 
  684. $context = new \Handlebars\Context($data); 
  685. // make sure we are getting the array length when given an array 
  686. $this->assertEquals($context->get("numbers.length"), 4); 
  687. // make sure we are not getting a length when given an object 
  688. $this->assertEmpty($context->get("object.length")); 
  689. // make sure we can still get the length property when given an object 
  690. $this->assertEquals($context->get("object_with_length_property.length"), "15cm"); 
  691.  
  692. public function argumentParserProvider() 
  693. return array( 
  694. array('arg1 arg2', array("arg1", "arg2")),  
  695. array('"arg1 arg2"', array("arg1 arg2")),  
  696. array('arg1 arg2 "arg number 3"', array("arg1", "arg2", "arg number 3")),  
  697. array('arg1 "arg\"2" "\"arg3\""', array("arg1", 'arg"2', '"arg3"')),  
  698. array("'arg1 arg2'", array("arg1 arg2")),  
  699. array("arg1 arg2 'arg number 3'", array("arg1", "arg2", "arg number 3")),  
  700. array('arg1 "arg\"2" "\\\'arg3\\\'"', array("arg1", 'arg"2', "'arg3'")),  
  701. array('arg1 arg2.[value\'s "segment"].val', array("arg1", 'arg2.[value\'s "segment"].val')),  
  702. array('"arg1.[value 1]" arg2', array("arg1.[value 1]", 'arg2')),  
  703. array('0', array('0')),  
  704. ); 
  705.  
  706. /** 
  707. * Test Argument Parser 
  708. * @param string $arg_string argument text 
  709. * @param $expected_array 
  710. * @dataProvider argumentParserProvider 
  711. * @return void 
  712. */ 
  713. public function testArgumentParser($arg_string, $expected_array) 
  714. $engine = new \Handlebars\Handlebars(); 
  715. $template = new \Handlebars\Template($engine, null, null); 
  716. // get the string version of the arguments array 
  717. $args = $template->parseArguments($arg_string); 
  718. $args = array_map(function ($a) { 
  719. return (string)$a; 
  720. }, $args); 
  721. $this->assertEquals($args, $expected_array); 
  722.  
  723. public function namedArgumentParserProvider() 
  724. return array( 
  725. array('arg1="value" arg2="value 2"', array('arg1' => 'value', 'arg2' => 'value 2')),  
  726. array('arg1=var1', array('arg1' => 'var1')),  
  727. array('[arg "1"]="arg number 1"', array('arg "1"' => "arg number 1")),  
  728. array('arg1 = "value"', array('arg1' => "value")),  
  729. ); 
  730.  
  731. /** 
  732. * Test Named Argument Parser 
  733. * @param string $arg_string argument text 
  734. * @param $expected_array 
  735. * @dataProvider namedArgumentParserProvider 
  736. * @return void 
  737. */ 
  738. public function testNamedArgumentsParser($arg_string, $expected_array) 
  739. $engine = new \Handlebars\Handlebars(); 
  740. $template = new \Handlebars\Template($engine, null, null); 
  741. // get the string version of the arguments array 
  742. $args = $template->parseNamedArguments($arg_string); 
  743. $args = array_map(function ($a) { 
  744. return (string)$a; 
  745. }, $args); 
  746. $this->assertEquals($args, $expected_array); 
  747.  
  748. /** 
  749. * Test Combined Arguments Parser 
  750. * @param string $arg_string argument text 
  751. * @param $positional_args 
  752. * @param $named_args 
  753. * @dataProvider combinedArgumentsParserProvider 
  754. * @return void 
  755. */ 
  756. public function testCombinedArgumentsParser($arg_string, $positional_args, $named_args) 
  757. $args = new \Handlebars\Arguments($arg_string); 
  758.  
  759. // Get the string version of the arguments array 
  760. $stringify = function ($a) { 
  761. return (string)$a; 
  762. }; 
  763.  
  764. if ($positional_args !== false) { 
  765. $this->assertEquals( 
  766. array_map($stringify, $args->getPositionalArguments()),  
  767. $positional_args 
  768. ); 
  769. if ($named_args !== false) { 
  770. $this->assertEquals( 
  771. array_map($stringify, $args->getNamedArguments()),  
  772. $named_args 
  773. ); 
  774.  
  775. public function combinedArgumentsParserProvider() 
  776. $result = array(); 
  777.  
  778. // Use data provider for positional arguments parser 
  779. foreach ($this->argumentParserProvider() as $dataSet) { 
  780. $result[] = array( 
  781. $dataSet[0],  
  782. $dataSet[1],  
  783. false,  
  784. ); 
  785.  
  786. // Use data provider for named arguments parser 
  787. foreach ($this->namedArgumentParserProvider() as $dataSet) { 
  788. $result[] = array( 
  789. $dataSet[0],  
  790. false,  
  791. $dataSet[1],  
  792. ); 
  793.  
  794. // Add test cases with combined arguments 
  795. return array_merge( 
  796. $result,  
  797. array( 
  798. array( 
  799. 'arg1 arg2 arg3=value1 arg4="value2"',  
  800. array('arg1', 'arg2'),  
  801. array('arg3' => 'value1', 'arg4' => 'value2') 
  802. ),  
  803. array( 
  804. '@first arg=@last',  
  805. array('@first'),  
  806. array('arg' => '@last') 
  807. ),  
  808. array( 
  809. '[seg arg1] [seg arg2] = [seg value "1"]',  
  810. array('[seg arg1]'),  
  811. array('seg arg2' => '[seg value "1"]') 
  812. ); 
  813.  
  814. public function stringLiteralInCustomHelperProvider() 
  815. return array( 
  816. array('{{#test2 arg1 "Argument 2"}}', array("arg1" => "Argument 1"), "Argument 1:Argument 2"),  
  817. array('{{#test2 "Argument 1" "Argument 2"}}', array("arg1" => "Argument 1"), "Argument 1:Argument 2"),  
  818. array('{{#test2 "Argument 1" arg2}}', array("arg2" => "Argument 2"), "Argument 1:Argument 2") 
  819. ); 
  820.  
  821. /** 
  822. * Test String literals in the context of a helper 
  823. * @param string $template template text 
  824. * @param array $data context data 
  825. * @param string $results The Expected Results 
  826. * @dataProvider stringLiteralInCustomHelperProvider 
  827. * @return void 
  828. */ 
  829. public function testStringLiteralInCustomHelper($template, $data, $results) 
  830. $engine = new \Handlebars\Handlebars(); 
  831. $engine->addHelper('test2', function ($template, $context, $args) { 
  832. $args = $template->parseArguments($args); 
  833.  
  834. $args = array_map(function ($a) use ($context) { 
  835. return $context->get($a); 
  836. }, $args); 
  837.  
  838. return implode(':', $args); 
  839. }); 
  840. $res = $engine->render($template, $data); 
  841. $this->assertEquals($res, $results); 
  842.  
  843. public function integerLiteralInCustomHelperProvider() 
  844. return array( 
  845. array('{{test -5}}', array(), '-5'),  
  846. array('{{test 0}}', array(), '0'),  
  847. array('{{test 12}}', array(), '12'),  
  848. array('{{test 12 [12]}}', array('12' => 'foo'), '12:foo'),  
  849. ); 
  850.  
  851. /** 
  852. * Test integer literals in the context of a helper 
  853. * @param string $template template text 
  854. * @param array $data context data 
  855. * @param string $results The Expected Results 
  856. * @dataProvider integerLiteralInCustomHelperProvider 
  857. * @return void 
  858. */ 
  859. public function testIntegerLiteralInCustomHelper($template, $data, $results) 
  860. $engine = new \Handlebars\Handlebars(); 
  861. $engine->addHelper('test', function ($template, $context, $args) { 
  862. $args = $template->parseArguments($args); 
  863.  
  864. $args = array_map(function ($a) use ($context) { 
  865. return $context->get($a); 
  866. }, $args); 
  867.  
  868. return implode(':', $args); 
  869. }); 
  870. $res = $engine->render($template, $data); 
  871. $this->assertEquals($res, $results); 
  872.  
  873. public function testString() 
  874. $string = new \Handlebars\String("Hello World"); 
  875. $this->assertEquals((string)$string, "Hello World"); 
  876.  
  877. public function testInvalidNames() 
  878. $loader = new \Handlebars\Loader\StringLoader(); 
  879. $engine = new \Handlebars\Handlebars( 
  880. array( 
  881. 'loader' => $loader,  
  882. ); 
  883. $all = \Handlebars\Context::NOT_VALID_NAME_CHARS; 
  884.  
  885. for ($i = 0; $i < strlen($all); $i++) { 
  886. // Dot in string is valid, its an exception here 
  887. if ($all{$i} === '.') { 
  888. continue; 
  889. try { 
  890. $name = 'var' . $all{$i} . 'var'; 
  891. $engine->render('{{' . $name . '}}', array($name => 'VALUE')); 
  892. throw new Exception("Accept the $name :/"); 
  893. } catch (Exception $e) { 
  894. $this->assertInstanceOf("InvalidArgumentException", $e); 
  895.  
  896. /** 
  897. * Helper subexpressions test 
  898. */ 
  899. public function testHelperSubexpressions() 
  900. $loader = new \Handlebars\Loader\StringLoader(); 
  901. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  902. $engine->addHelper('test', function ($template, $context, $args) { 
  903. $parsedArgs = $template->parseArguments($args); 
  904.  
  905. return (count($parsedArgs) ? $context->get($parsedArgs[0]) : '') . 'Test.'; 
  906. }); 
  907.  
  908. // assert that nested syntax is accepted and sub-helper is run 
  909. $this->assertEquals('Test.Test.', $engine->render('{{test (test)}}', array())); 
  910.  
  911. $engine->addHelper('add', function ($template, $context, $args) { 
  912. $sum = 0; 
  913.  
  914. foreach ($template->parseArguments($args) as $value) { 
  915. $sum += intval($context->get($value)); 
  916.  
  917. return $sum; 
  918. }); 
  919.  
  920. // assert that subexpression result is inserted correctly as argument to top level helper 
  921. $this->assertEquals('42', $engine->render('{{add 21 (add 10 (add 5 6))}}', array())); 
  922.  
  923. // assert that bracketed expressions within string literals are treated correctly 
  924. $this->assertEquals("(test)Test.", $engine->render("{{test '(test)'}}", array())); 
  925. $this->assertEquals(")Test.Test.", $engine->render("{{test (test ')')}}", array())); 
  926.  
  927. $engine->addHelper('concat', function(\Handlebars\Template $template, \Handlebars\Context $context, $args) { 
  928. $result = ''; 
  929.  
  930. foreach($template->parseArguments($args) as $arg) { 
  931. $result .= $context->get($arg); 
  932.  
  933. return $result; 
  934. }); 
  935.  
  936. $this->assertEquals('ACB', $engine->render('{{concat a (concat c b)}}', array('a' => 'A', 'b' => 'B', 'c' => 'C'))); 
  937. $this->assertEquals('ACB', $engine->render('{{concat (concat a c) b}}', array('a' => 'A', 'b' => 'B', 'c' => 'C'))); 
  938. $this->assertEquals('A-B', $engine->render('{{concat (concat a "-") b}}', array('a' => 'A', 'b' => 'B'))); 
  939. $this->assertEquals('A-B', $engine->render('{{concat (concat a "-") b}}', array('a' => 'A', 'b' => 'B', 'A-' => '!'))); 
  940.  
  941. /** 
  942. * Test if and unless adding an extra layer when accessing parent 
  943. */ 
  944. public function testIfUnlessExtraLayer() 
  945. $loader = new \Handlebars\Loader\StringLoader(); 
  946. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  947.  
  948. $this->assertEquals('good', $engine->render('{{#with b}}{{#if this}}{{../../a}}{{/if}}{{/with}}', array('a' => 'good', 'b' => 'stump'))); 
  949. $this->assertEquals('good', $engine->render('{{#with b}}{{#unless false}}{{../../a}}{{/unless}}{{/with}}', array('a' => 'good', 'b' => 'stump'))); 
  950.  
  951. /** 
  952. * Test of Arguments to string conversion. 
  953. */ 
  954. public function testArgumentsString() 
  955. $argsString = 'foo bar [foo bar] baz="value"'; 
  956. $args = new \Handlebars\Arguments($argsString); 
  957. $this->assertEquals($argsString, (string)$args); 
/vendor/xamin/handlebars.php/tests/fixture/Handlebars/Test.php  
  1. class Test 
  2.  
/vendor/xamin/handlebars.php/tests/Xamin/HandlebarsTest.php  
  1. class HandlebarsTest extends \PHPUnit_Framework_TestCase 
  2. public function setUp() 
  3. \Handlebars\Autoloader::register(); 
  4.  
  5. /** 
  6. * Test handlebars autoloader 
  7. * @return void 
  8. */ 
  9. public function testAutoLoad() 
  10. Handlebars\Autoloader::register(realpath(__DIR__ . '/../fixture/')); 
  11.  
  12. $this->assertTrue(class_exists('Handlebars\\Test')); 
  13. $this->assertTrue(class_exists('\\Handlebars\\Test')); 
  14. $this->assertTrue(class_exists('Handlebars\\Example\\Test')); 
  15. $this->assertTrue(class_exists('\\Handlebars\\Example\\Test')); 
  16. $this->assertFalse(class_exists('\\Another\\Example\\Test')); 
  17.  
  18. /** 
  19. * Test basic tags 
  20. * @param string $src handlebars source 
  21. * @param array $data data 
  22. * @param string $result expected data 
  23. * @dataProvider simpleTagdataProvider 
  24. * @return void 
  25. */ 
  26. public function testBasicTags($src, $data, $result) 
  27. $loader = new \Handlebars\Loader\StringLoader(); 
  28. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  29. $this->assertEquals($result, $engine->render($src, $data)); 
  30.  
  31. /** 
  32. * Simple tag provider 
  33. * @return array 
  34. */ 
  35. public function simpleTagdataProvider() 
  36. return array( 
  37. array( 
  38. '{{! This is comment}}',  
  39. array(),  
  40. '' 
  41. ),  
  42. array( 
  43. '{{data}}',  
  44. array('data' => 'result'),  
  45. 'result' 
  46. ),  
  47. array( 
  48. '{{data.key}}',  
  49. array('data' => array('key' => 'result')),  
  50. 'result' 
  51. ),  
  52. array( 
  53. '{{data.length}}',  
  54. array("data" => array(1, 2, 3, 4)),  
  55. '4' 
  56. ),  
  57. array( 
  58. '{{data.length}}',  
  59. array("data" => (object)array(1, 2, 3, 4)),  
  60. '' 
  61. ),  
  62. array( 
  63. '{{data.length}}',  
  64. array("data" => array("length" => "15 inches", "test", "test", "test")),  
  65. "15 inches" 
  66. ),  
  67. array( 
  68. '{{data.0}}',  
  69. array("data" => array(1, 2, 3, 4)),  
  70. '1' 
  71. ),  
  72. array( 
  73. '{{data.property.3}}',  
  74. array("data" => array("property" => array(1, 2, 3, 4))),  
  75. '4' 
  76. ),  
  77. array( 
  78. '{{data.unsafe}}',  
  79. array('data' => array('unsafe' => '<strong>Test</strong>')),  
  80. '<strong>Test</strong>' 
  81. ),  
  82. array( 
  83. '{{{data.safe}}}',  
  84. array('data' => array('safe' => '<strong>Test</strong>')),  
  85. '<strong>Test</strong>' 
  86. ),  
  87. array( 
  88. "\{{data}}", // is equal to \\{{data}} 
  89. array('data' => 'foo'),  
  90. '{{data}}',  
  91. ),  
  92. array( 
  93. '\\\\{{data}}',  
  94. array('data' => 'foo'),  
  95. '\\\\foo' 
  96. ),  
  97. array( 
  98. '\\\{{data}}', // is equal to \\\\{{data}} in php 
  99. array('data' => 'foo'),  
  100. '\\\\foo' 
  101. ),  
  102. array( 
  103. '\{{{data}}}',  
  104. array('data' => 'foo'),  
  105. '{{{data}}}' 
  106. ),  
  107. array( 
  108. '\pi',  
  109. array(),  
  110. '\pi' 
  111. ),  
  112. array( 
  113. '\\\\\\\\qux',  
  114. array(),  
  115. '\\\\\\\\qux' 
  116. ),  
  117. array( 
  118. "var jsVar = 'It\'s a phrase in apos';",  
  119. array(),  
  120. "var jsVar = 'It\'s a phrase in apos';" 
  121. ),  
  122. array( 
  123. 'var jsVar = "A \"quoted\" text";',  
  124. array(),  
  125. 'var jsVar = "A \"quoted\" text";',  
  126. ),  
  127. array( 
  128. '{{#if first}}The first{{else}}{{#if second}}The second{{/if}}{{/if}}',  
  129. array('first' => false, 'second' => true),  
  130. 'The second' 
  131. ); 
  132.  
  133. /** 
  134. * Test helpers (internal helpers) 
  135. * @param string $src handlebars source 
  136. * @param array $data data 
  137. * @param string $result expected data 
  138. * @dataProvider internalHelpersdataProvider 
  139. * @return void 
  140. */ 
  141. public function testSimpleHelpers($src, $data, $result) 
  142. $loader = new \Handlebars\Loader\StringLoader(); 
  143. $helpers = new \Handlebars\Helpers(); 
  144. $engine = new \Handlebars\Handlebars(array('loader' => $loader, 'helpers' => $helpers)); 
  145.  
  146. $this->assertEquals($result, $engine->render($src, $data)); 
  147.  
  148. /** 
  149. * Simple helpers provider 
  150. * @return array 
  151. */ 
  152. public function internalHelpersdataProvider() 
  153. return array( 
  154. array( 
  155. '{{#if data}}Yes{{/if}}',  
  156. array('data' => true),  
  157. 'Yes' 
  158. ),  
  159. # see the issue #76 
  160. array( 
  161. '{{#if data}}0{{/if}}',  
  162. array('data' => true),  
  163. '0' 
  164. ),  
  165. array( 
  166. '{{#if data}}Yes{{/if}}',  
  167. array('data' => false),  
  168. '' 
  169. ),  
  170. array( 
  171. '{{#with data}}{{key}}{{/with}}',  
  172. array('data' => array('key' => 'result')),  
  173. 'result' 
  174. ),  
  175. array( 
  176. '{{#each data}}{{this}}{{/each}}',  
  177. array('data' => array(1, 2, 3, 4)),  
  178. '1234' 
  179. ),  
  180. array( 
  181. '{{#each data}}{{@key}}{{/each}}',  
  182. array('data' => array('the_only_key' => 1)),  
  183. 'the_only_key' 
  184. ),  
  185. array( 
  186. '{{#each data}}{{@key}}=>{{this}}{{/each}}',  
  187. array('data' => array('key1' => 1, 'key2' => 2, )),  
  188. 'key1=>1key2=>2' 
  189. ),  
  190. array( 
  191. '{{#each data}}{{@key}}=>{{this}}{{/each}}',  
  192. array('data' => new \ArrayIterator(array('key1' => 1, 'key2' => 2))),  
  193. 'key1=>1key2=>2' 
  194. ),  
  195. array( 
  196. '{{#each data}}{{@index}}=>{{this}}, {{/each}}',  
  197. array('data' => array('key1' => 1, 'key2' => 2, )),  
  198. '0=>1, 1=>2, ' 
  199. ),  
  200. array( 
  201. '{{#each data}}{{#if @first}}the first is {{this}}{{/if}}{{/each}}',  
  202. array('data' => array('one', 'two', 'three')),  
  203. 'the first is one' 
  204. ),  
  205. array( 
  206. '{{#each data}}{{#if @last}}the last is {{this}}{{/if}}{{/each}}',  
  207. array('data' => array('one', 'two', 'three')),  
  208. 'the last is three' 
  209. ),  
  210. array( 
  211. '{{#each data}}{{this}}{{else}}fail{{/each}}',  
  212. array('data' => array(1, 2, 3, 4)),  
  213. '1234' 
  214. ),  
  215. array( 
  216. '{{#each data}}fail{{else}}ok{{/each}}',  
  217. array('data' => false),  
  218. 'ok' 
  219. ),  
  220. array( 
  221. '{{#unless data}}ok{{/unless}}',  
  222. array('data' => true),  
  223. '' 
  224. ),  
  225. array( 
  226. '{{#unless data}}ok{{/unless}}',  
  227. array('data' => false),  
  228. 'ok' 
  229. ),  
  230. array( 
  231. '{{#unless data}}ok{{else}}fail{{/unless}}',  
  232. array('data' => false),  
  233. 'ok' 
  234. ),  
  235. array( 
  236. '{{#unless data}}fail{{else}}ok{{/unless}}',  
  237. array('data' => true),  
  238. 'ok' 
  239. ),  
  240. array( 
  241. '{{#bindAttr data}}',  
  242. array(),  
  243. 'data' 
  244. ),  
  245. array( 
  246. '{{#if 1}}ok{{else}}fail{{/if}}',  
  247. array(),  
  248. 'ok' 
  249. ),  
  250. array( 
  251. '{{#if 0}}ok{{else}}fail{{/if}}',  
  252. array(),  
  253. 'fail' 
  254. ),  
  255. array( 
  256. ' {{~#if 1}}OK {{~else~}} NO {{~/if~}} END',  
  257. array(),  
  258. 'OKEND' 
  259. ),  
  260. array( 
  261. 'XX {{~#bindAttr data}} XX',  
  262. array(),  
  263. 'XXdata XX' 
  264. ),  
  265. array( 
  266. '{{#each data}}{{#if @last}}the last is 
  267. {{~this}}{{/if}}{{/each}}',  
  268. array('data' => array('one', 'two', 'three')),  
  269. 'the last isthree' 
  270. ),  
  271. array( 
  272. '{{#with data}} 
  273.  
  274. {{~key~}} 
  275.  
  276. {{/with}}',  
  277. array('data' => array('key' => 'result')),  
  278. 'result' 
  279. ),  
  280. array( 
  281. '{{= (( )) =}}((#if 1))OK((else))NO((/if))',  
  282. array(),  
  283. 'OK' 
  284. ),  
  285. array( 
  286. '{{#each data~}} {{this}} {{~/each}}',  
  287. array('data' => array(1, 2, 3, 4)),  
  288. '1234' 
  289. ),  
  290. array( 
  291. '{{#each data}}{{this}} {{~/each}}',  
  292. array('data' => array(1, 2, 3, 4)),  
  293. '1234' 
  294. ),  
  295. array( 
  296. '{{#each data~}} {{this}}{{/each}}',  
  297. array('data' => array(1, 2, 3, 4)),  
  298. '1234' 
  299. ),  
  300. array('{{#if first}}The first{{else}}{{#if second}}The second{{/if}}{{/if}}',  
  301. array('first' => false, 'second' => true),  
  302. 'The second' 
  303. ); 
  304.  
  305. /** 
  306. * Management helpers 
  307. */ 
  308. public function testHelpersManagement() 
  309. $helpers = new \Handlebars\Helpers(array('test' => function () { 
  310. }), false); 
  311. $engine = new \Handlebars\Handlebars(array('helpers' => $helpers)); 
  312. $this->assertTrue(is_callable($engine->getHelper('test'))); 
  313. $this->assertTrue($engine->hasHelper('test')); 
  314. $engine->removeHelper('test'); 
  315. $this->assertFalse($engine->hasHelper('test')); 
  316.  
  317. /** 
  318. * Custom helper test 
  319. */ 
  320. public function testCustomHelper() 
  321. $loader = new \Handlebars\Loader\StringLoader(); 
  322. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  323. $engine->addHelper('test', function () { 
  324. return 'Test helper is called'; 
  325. }); 
  326. $this->assertEquals('Test helper is called', $engine->render('{{#test}}', array())); 
  327. $this->assertEquals('Test helper is called', $engine->render('{{test}}', array())); 
  328.  
  329. $engine->addHelper('test2', function ($template, $context, $arg) { 
  330. return 'Test helper is called with ' . $arg; 
  331. }); 
  332. $this->assertEquals('Test helper is called with a b c', $engine->render('{{#test2 a b c}}', array())); 
  333. $this->assertEquals('Test helper is called with a b c', $engine->render('{{test2 a b c}}', array())); 
  334.  
  335. $engine->addHelper('renderme', function () { 
  336. return new \Handlebars\String("{{test}}"); 
  337. }); 
  338. $this->assertEquals('Test helper is called', $engine->render('{{#renderme}}', array())); 
  339.  
  340. $engine->addHelper('dontrenderme', function () { 
  341. return "{{test}}"; 
  342. }); 
  343. $this->assertEquals('{{test}}', $engine->render('{{#dontrenderme}}', array())); 
  344.  
  345. $engine->addHelper('markupHelper', function () { 
  346. return '<strong>Test</strong>'; 
  347. }); 
  348. $this->assertEquals('<strong>Test</strong>', $engine->render('{{{markupHelper}}}', array())); 
  349. $this->assertEquals('<strong>Test</strong>', $engine->render('{{markupHelper}}', array())); 
  350.  
  351. $engine->addHelper('safeStringTest', function () { 
  352. return new \Handlebars\SafeString('<strong>Test</strong>'); 
  353. }); 
  354. $this->assertEquals('<strong>Test</strong>', $engine->render('{{safeStringTest}}', array())); 
  355.  
  356. $engine->addHelper('argsTest', function ($template, $context, $arg) { 
  357. $parsedArgs = $template->parseArguments($arg); 
  358.  
  359. return implode(' ', $parsedArgs); 
  360. }); 
  361. $this->assertEquals("a \"b\" c", $engine->render('{{{argsTest "a" "\"b\"" \'c\'}}}', array())); 
  362.  
  363. // This is just a fun thing to do :) 
  364. $that = $this; 
  365. $engine->addHelper('stopToken',  
  366. function ($template, $context, $arg) use ($that) { 
  367. /** @var $template \Handlebars\Template */ 
  368. $parsedArgs = $template->parseArguments($arg); 
  369. $first = array_shift($parsedArgs); 
  370. $last = array_shift($parsedArgs); 
  371. if ($last == 'yes') { 
  372. $template->setStopToken($first); 
  373. $that->assertEquals($first, $template->getStopToken()); 
  374. $buffer = $template->render($context); 
  375. $template->setStopToken(false); 
  376. $template->discard($context); 
  377. } else { 
  378. $template->setStopToken($first); 
  379. $that->assertEquals($first, $template->getStopToken()); 
  380. $template->discard($context); 
  381. $template->setStopToken(false); 
  382. $buffer = $template->render($context); 
  383.  
  384. return $buffer; 
  385. }); 
  386.  
  387. $this->assertEquals("Used", $engine->render('{{# stopToken fun no}}Not used{{ fun }}Used{{/stopToken }}', array())); 
  388. $this->assertEquals("Not used", $engine->render('{{# stopToken any yes}}Not used{{ any }}Used{{/stopToken }}', array())); 
  389.  
  390. $this->setExpectedException('InvalidArgumentException'); 
  391. $engine->getHelpers()->call('invalid', $engine->loadTemplate(''), new \Handlebars\Context(), '', ''); 
  392.  
  393. public function testInvalidHelperMustacheStyle() 
  394. $this->setExpectedException('RuntimeException'); 
  395. $loader = new \Handlebars\Loader\StringLoader(); 
  396. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  397. $engine->render('{{#NOTVALID}}XXX{{/NOTVALID}}', array()); 
  398.  
  399. public function testInvalidHelper() 
  400. $this->setExpectedException('RuntimeException'); 
  401. $loader = new \Handlebars\Loader\StringLoader(); 
  402. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  403. $engine->render('{{#NOTVALID argument}}XXX{{/NOTVALID}}', array()); 
  404.  
  405. /** 
  406. * Test mustache style loop and if 
  407. */ 
  408. public function testMustacheStyle() 
  409. $loader = new \Handlebars\Loader\StringLoader(); 
  410. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  411. $this->assertEquals('yes', $engine->render('{{#x}}yes{{/x}}', array('x' => true))); 
  412. $this->assertEquals('', $engine->render('{{#x}}yes{{/x}}', array('x' => false))); 
  413. $this->assertEquals('yes', $engine->render('{{^x}}yes{{/x}}', array('x' => false))); 
  414. $this->assertEquals('', $engine->render('{{^x}}yes{{/x}}', array('x' => true))); 
  415. $this->assertEquals('1234', $engine->render('{{#x}}{{this}}{{/x}}', array('x' => array(1, 2, 3, 4)))); 
  416. $this->assertEquals('012', $engine->render('{{#x}}{{@index}}{{/x}}', array('x' => array('a', 'b', 'c')))); 
  417. $this->assertEquals('abc', $engine->render('{{#x}}{{@key}}{{/x}}', array('x' => array('a' => 1, 'b' => 2, 'c' => 3)))); 
  418. $this->assertEquals('the_only_key', $engine->render('{{#x}}{{@key}}{{/x}}', array('x' => array('the_only_key' => 1)))); 
  419. $std = new stdClass(); 
  420. $std->value = 1; 
  421. $this->assertEquals('1', $engine->render('{{#x}}{{value}}{{/x}}', array('x' => $std))); 
  422. $this->assertEquals('1', $engine->render('{{{x}}}', array('x' => 1))); 
  423.  
  424. /** 
  425. * @expectedException \LogicException 
  426. */ 
  427. public function testParserException() 
  428. $loader = new \Handlebars\Loader\StringLoader(); 
  429. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  430. $engine->render('{{#test}}{{#test2}}{{/test}}{{/test2}}', array()); 
  431.  
  432. /** 
  433. * Test add/addHelpers/get/getAll/has/clear functions on helper class 
  434. */ 
  435. public function testHelpersClass() 
  436. $helpers = new \Handlebars\Helpers(); 
  437. $helpers->add('test', function () { 
  438. }); 
  439. $this->assertTrue($helpers->has('test')); 
  440. $this->assertTrue(isset($helpers->test)); 
  441. $this->assertFalse($helpers->isEmpty()); 
  442. $helpers->test2 = function () { 
  443. }; 
  444. $this->assertTrue($helpers->has('test2')); 
  445. $this->assertTrue(isset($helpers->test2)); 
  446. $this->assertFalse($helpers->isEmpty()); 
  447. unset($helpers->test2); 
  448. $this->assertFalse($helpers->has('test2')); 
  449. $this->assertFalse(isset($helpers->test2)); 
  450. $helpers->clear(); 
  451. $this->assertFalse($helpers->has('test')); 
  452. $this->assertFalse(isset($helpers->test)); 
  453. $this->assertTrue($helpers->isEmpty()); 
  454. $helpers->add('test', function () { 
  455. }); 
  456. $this->assertCount(0, array_diff(array_keys($helpers->getAll()), array('test'))); 
  457. $extraHelpers = new \Handlebars\Helpers(); 
  458. $extraHelpers->add('test', function () { 
  459. }); 
  460. $extraHelpers->add('test2', function () { 
  461. }); 
  462. $helpers->addHelpers($extraHelpers); 
  463. $this->assertTrue($helpers->has('test2')); 
  464. $this->assertEquals($helpers->test, $extraHelpers->test); 
  465.  
  466. /** 
  467. * @expectedException \InvalidArgumentException 
  468. */ 
  469. public function testHelperWrongConstructor() 
  470. $helper = new \Handlebars\Helpers("helper"); 
  471.  
  472. /** 
  473. * @expectedException \InvalidArgumentException 
  474. */ 
  475. public function testHelperWrongCallable() 
  476. $helper = new \Handlebars\Helpers(); 
  477. $helper->add('test', 1); 
  478.  
  479. /** 
  480. * @expectedException \InvalidArgumentException 
  481. */ 
  482. public function testHelperWrongGet() 
  483. $helper = new \Handlebars\Helpers(); 
  484. $x = $helper->test; 
  485.  
  486. /** 
  487. * @expectedException \InvalidArgumentException 
  488. */ 
  489. public function testHelperWrongUnset() 
  490. $helper = new \Handlebars\Helpers(); 
  491. unset($helper->test); 
  492.  
  493. /** 
  494. * test String class 
  495. */ 
  496. public function testStringClass() 
  497. $string = new \Handlebars\String('test'); 
  498. $this->assertEquals('test', $string->getString()); 
  499. $string->setString('new'); 
  500. $this->assertEquals('new', $string->getString()); 
  501.  
  502. /** 
  503. * @param $dir 
  504. * @return bool 
  505. */ 
  506. private function delTree($dir) 
  507. $files = array_diff(scandir($dir), array('.', '..')); 
  508. foreach ($files as $file) { 
  509. (is_dir("$dir/$file")) ? $this->delTree("$dir/$file") : unlink("$dir/$file"); 
  510.  
  511. return rmdir($dir); 
  512.  
  513. /** 
  514. * Its not a good test :) but ok 
  515. */ 
  516. public function testCacheSystem() 
  517. $path = sys_get_temp_dir() . '/__cache__handlebars'; 
  518.  
  519. @$this->delTree($path); 
  520.  
  521. $dummy = new \Handlebars\Cache\Disk($path); 
  522. $engine = new \Handlebars\Handlebars(array('cache' => $dummy)); 
  523. $this->assertEquals(0, count(glob($path . '/*'))); 
  524. $engine->render('test', array()); 
  525. $this->assertEquals(1, count(glob($path . '/*'))); 
  526.   
  527. public function testArrayLoader() 
  528. $loader = new \Handlebars\Loader\ArrayLoader(array('test' => 'HELLO')); 
  529. $loader->addTemplate('another', 'GOODBYE'); 
  530. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  531. $this->assertEquals($engine->render('test', array()), 'HELLO'); 
  532. $this->assertEquals($engine->render('another', array()), 'GOODBYE'); 
  533.   
  534. $this->setExpectedException('RuntimeException'); 
  535. $engine->render('invalid-template', array()); 
  536.   
  537. /** 
  538. * Test file system loader 
  539. */ 
  540. public function testFileSystemLoader() 
  541. $loader = new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/data')); 
  542. $engine = new \Handlebars\Handlebars(); 
  543. $engine->setLoader($loader); 
  544. $this->assertEquals('test', $engine->render('loader', array())); 
  545.  
  546. /** 
  547. * Test inline loader 
  548. */ 
  549. public function testInlineLoader() 
  550. $loader = new \Handlebars\Loader\InlineLoader(__FILE__, __COMPILER_HALT_OFFSET__); 
  551. $this->assertEquals('This is a inline template.', $loader->load('template1')); 
  552.  
  553. $expected = <<<EOM 
  554. EOM; 
  555. $this->assertEquals($expected, $loader->load('template2')); 
  556.  
  557. /** 
  558. * Test file system loader 
  559. */ 
  560. public function testFileSystemLoaderMultipleFolder() 
  561. $paths = array( 
  562. realpath(__DIR__ . '/../fixture/data'),  
  563. realpath(__DIR__ . '/../fixture/another') 
  564. ); 
  565.  
  566. $options = array( 
  567. 'prefix' => '__',  
  568. 'extension' => 'hb' 
  569. ); 
  570. $loader = new \Handlebars\Loader\FilesystemLoader($paths, $options); 
  571. $engine = new \Handlebars\Handlebars(); 
  572. $engine->setLoader($loader); 
  573. $this->assertEquals('test_extra', $engine->render('loader', array())); 
  574. $this->assertEquals('another_extra', $engine->render('another', array())); 
  575.  
  576. /** 
  577. * Test file system loader 
  578. * @expectedException \InvalidArgumentException 
  579. */ 
  580. public function testFileSystemLoaderNotFound() 
  581. $loader = new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/data')); 
  582. $engine = new \Handlebars\Handlebars(); 
  583. $engine->setLoader($loader); 
  584. $engine->render('invalid_file', array()); 
  585.  
  586. /** 
  587. * Test file system loader 
  588. * @expectedException \RuntimeException 
  589. */ 
  590. public function testFileSystemLoaderInvalidFolder() 
  591. new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/') . 'invalid/path'); 
  592.  
  593. /** 
  594. * Test partial loader 
  595. */ 
  596. public function testPartialLoader() 
  597. $loader = new \Handlebars\Loader\StringLoader(); 
  598. $partialLoader = new \Handlebars\Loader\FilesystemLoader(realpath(__DIR__ . '/../fixture/data')); 
  599. $engine = new \Handlebars\Handlebars(); 
  600. $engine->setLoader($loader); 
  601. $engine->setPartialsLoader($partialLoader); 
  602.  
  603. $this->assertEquals('test', $engine->render('{{>loader}}', array())); 
  604.  
  605. public function testPartial() 
  606. $loader = new \Handlebars\Loader\StringLoader(); 
  607. $partialLoader = new \Handlebars\Loader\ArrayLoader(array('test' => '{{key}}', 'bar' => 'its foo')); 
  608. $partialAliasses = array('foo' => 'bar'); 
  609. $engine = new \Handlebars\Handlebars( 
  610. array( 
  611. 'loader' => $loader,  
  612. 'partials_loader' => $partialLoader,  
  613. 'partials_alias' => $partialAliasses 
  614. ); 
  615.  
  616. $this->assertEquals('HELLO', $engine->render('{{>test parameter}}', array('parameter' => array('key' => 'HELLO')))); 
  617. $this->assertEquals('its foo', $engine->render('{{>foo}}', array())); 
  618. $engine->registerPartial('foo-again', 'bar'); 
  619. $this->assertEquals('its foo', $engine->render('{{>foo-again}}', array())); 
  620. $engine->unRegisterPartial('foo-again'); 
  621.  
  622. $this->setExpectedException('RuntimeException'); 
  623. $engine->render('{{>foo-again}}', array()); 
  624.  
  625. /** 
  626. * test variable access 
  627. */ 
  628. public function testVariableAccess() 
  629. $loader = new \Handlebars\Loader\StringLoader(); 
  630. $engine = \Handlebars\Handlebars::factory(); 
  631. $engine->setLoader($loader); 
  632.  
  633. $var = new \StdClass(); 
  634. $var->x = 'var-x'; 
  635. $var->y = array( 
  636. 'z' => 'var-y-z' 
  637. ); 
  638. $this->assertEquals('test', $engine->render('{{var}}', array('var' => 'test'))); 
  639. $this->assertEquals('var-x', $engine->render('{{var.x}}', array('var' => $var))); 
  640. $this->assertEquals('var-y-z', $engine->render('{{var.y.z}}', array('var' => $var))); 
  641. // Access parent context in with helper 
  642. $this->assertEquals('var-x', $engine->render('{{#with var.y}}{{../var.x}}{{/with}}', array('var' => $var))); 
  643. // Reference array as string 
  644. $this->assertEquals('Array', $engine->render('{{var}}', array('var' => array('test')))); 
  645.  
  646. $obj = new DateTime(); 
  647. $time = $obj->getTimestamp(); 
  648. $this->assertEquals($time, $engine->render('{{time.getTimestamp}}', array('time' => $obj))); 
  649.  
  650. public function testContext() 
  651. $test = new stdClass(); 
  652. $test->value = 'value'; 
  653. $test->array = array( 
  654. 'a' => '1',  
  655. 'b' => '2',  
  656. '!"#%&\'()*+, ./;<=>@[\\^`{|}~ ' => '3',  
  657. ); 
  658. $context = new \Handlebars\Context($test); 
  659. $this->assertEquals('value', $context->get('value')); 
  660. $this->assertEquals('value', $context->get('value', true)); 
  661. $this->assertEquals('value', $context->get('[value]', true)); 
  662. $this->assertEquals('1', $context->get('array.a', true)); 
  663. $this->assertEquals('2', $context->get('array.b', true)); 
  664. $this->assertEquals('3', $context->get('array.[!"#%&\'()*+, ./;<=>@[\\^`{|}~ ]', true)); 
  665. $new = array('value' => 'new value'); 
  666. $context->push($new); 
  667. $this->assertEquals('new value', $context->get('value')); 
  668. $this->assertEquals('new value', $context->get('value', true)); 
  669. $this->assertEquals('value', $context->get('../value')); 
  670. $this->assertEquals('value', $context->get('../value', true)); 
  671. $this->assertEquals($new, $context->last()); 
  672. $this->assertEquals($new, $context->get('.')); 
  673. $this->assertEquals($new, $context->get('this')); 
  674. $this->assertEquals($new, $context->get('this.')); 
  675. $this->assertEquals($test, $context->get('../.')); 
  676. $context->pop(); 
  677. $this->assertEquals('value', $context->get('value')); 
  678. $this->assertEquals('value', $context->get('value', true)); 
  679.  
  680. /** 
  681. * @expectedException \InvalidArgumentException 
  682. * @dataProvider getInvalidData 
  683. */ 
  684. public function testInvalidAccessContext($invalid) 
  685. $context = new \Handlebars\Context(array()); 
  686. $this->assertEmpty($context->get($invalid)); 
  687. $context->get($invalid, true); 
  688.  
  689. public function getInvalidData() 
  690. return array( 
  691. array('../../data'),  
  692. array('data'),  
  693. array(''),  
  694. array('data.key.key'),  
  695. ); 
  696.  
  697.  
  698. /** 
  699. * Test invalid custom template class 
  700. * @expectedException \InvalidArgumentException 
  701. */ 
  702. public function testInvalidCustomTemplateClass() 
  703. $loader = new \Handlebars\Loader\StringLoader(); 
  704. $engine = new \Handlebars\Handlebars(array( 
  705. 'loader' => $loader,  
  706. 'template_class' => 'stdclass' 
  707. )); 
  708.  
  709. /** 
  710. * Test custom template class 
  711. */ 
  712. public function testValidCustomTemplateClass() 
  713. Handlebars\Autoloader::register(realpath(__DIR__ . '/../fixture/')); 
  714.  
  715. $loader = new \Handlebars\Loader\StringLoader(); 
  716. $engine = new \Handlebars\Handlebars(array( 
  717. 'loader' => $loader,  
  718. 'template_class' => 'Handlebars\CustomTemplate' 
  719. )); 
  720.  
  721. $render = $engine->render('Original Template', array()); 
  722.  
  723. $this->assertEquals($render, 'Altered Template'); 
  724.  
  725. /** 
  726. * Test for proper handling of the length property 
  727. **/ 
  728. public function testArrayLengthEmulation() 
  729.  
  730. $data = array("numbers" => array(1, 2, 3, 4),  
  731. "object" => (object)array("prop1" => "val1", "prop2" => "val2"),  
  732. "object_with_length_property" => (object)array("length" => "15cm") 
  733. ); 
  734. $context = new \Handlebars\Context($data); 
  735. // make sure we are getting the array length when given an array 
  736. $this->assertEquals($context->get("numbers.length"), 4); 
  737. // make sure we are not getting a length when given an object 
  738. $this->assertEmpty($context->get("object.length")); 
  739. // make sure we can still get the length property when given an object 
  740. $this->assertEquals($context->get("object_with_length_property.length"), "15cm"); 
  741.  
  742. public function argumentParserProvider() 
  743. return array( 
  744. array('arg1 arg2', array("arg1", "arg2")),  
  745. array('"arg1 arg2"', array("arg1 arg2")),  
  746. array('arg1 arg2 "arg number 3"', array("arg1", "arg2", "arg number 3")),  
  747. array('arg1 "arg\"2" "\"arg3\""', array("arg1", 'arg"2', '"arg3"')),  
  748. array("'arg1 arg2'", array("arg1 arg2")),  
  749. array("arg1 arg2 'arg number 3'", array("arg1", "arg2", "arg number 3")),  
  750. array('arg1 "arg\"2" "\\\'arg3\\\'"', array("arg1", 'arg"2', "'arg3'")),  
  751. array('arg1 arg2.[value\'s "segment"].val', array("arg1", 'arg2.[value\'s "segment"].val')),  
  752. array('"arg1.[value 1]" arg2', array("arg1.[value 1]", 'arg2')),  
  753. array('0', array('0')),  
  754. ); 
  755.  
  756. /** 
  757. * Test Argument Parser 
  758. * @param string $arg_string argument text 
  759. * @param $expected_array 
  760. * @dataProvider argumentParserProvider 
  761. * @return void 
  762. */ 
  763. public function testArgumentParser($arg_string, $expected_array) 
  764. $engine = new \Handlebars\Handlebars(); 
  765. $template = new \Handlebars\Template($engine, null, null); 
  766. // get the string version of the arguments array 
  767. $args = $template->parseArguments($arg_string); 
  768. $args = array_map(function ($a) { 
  769. return (string)$a; 
  770. }, $args); 
  771. $this->assertEquals($args, $expected_array); 
  772.  
  773. public function namedArgumentParserProvider() 
  774. return array( 
  775. array('arg1="value" arg2="value 2"', array('arg1' => 'value', 'arg2' => 'value 2')),  
  776. array('arg1=var1', array('arg1' => 'var1')),  
  777. array('[arg "1"]="arg number 1"', array('arg "1"' => "arg number 1")),  
  778. array('arg1 = "value"', array('arg1' => "value")),  
  779. ); 
  780.  
  781. /** 
  782. * Test Named Argument Parser 
  783. * @param string $arg_string argument text 
  784. * @param $expected_array 
  785. * @dataProvider namedArgumentParserProvider 
  786. * @return void 
  787. */ 
  788. public function testNamedArgumentsParser($arg_string, $expected_array) 
  789. $engine = new \Handlebars\Handlebars(); 
  790. $template = new \Handlebars\Template($engine, null, null); 
  791. // get the string version of the arguments array 
  792. $args = $template->parseNamedArguments($arg_string); 
  793. $args = array_map(function ($a) { 
  794. return (string)$a; 
  795. }, $args); 
  796. $this->assertEquals($args, $expected_array); 
  797.  
  798. /** 
  799. * Test Combined Arguments Parser 
  800. * @param string $arg_string argument text 
  801. * @param $positional_args 
  802. * @param $named_args 
  803. * @dataProvider combinedArgumentsParserProvider 
  804. * @return void 
  805. */ 
  806. public function testCombinedArgumentsParser($arg_string, $positional_args, $named_args) 
  807. $args = new \Handlebars\Arguments($arg_string); 
  808.  
  809. // Get the string version of the arguments array 
  810. $stringify = function ($a) { 
  811. return (string)$a; 
  812. }; 
  813.  
  814. if ($positional_args !== false) { 
  815. $this->assertEquals( 
  816. array_map($stringify, $args->getPositionalArguments()),  
  817. $positional_args 
  818. ); 
  819. if ($named_args !== false) { 
  820. $this->assertEquals( 
  821. array_map($stringify, $args->getNamedArguments()),  
  822. $named_args 
  823. ); 
  824.  
  825. public function combinedArgumentsParserProvider() 
  826. $result = array(); 
  827.  
  828. // Use data provider for positional arguments parser 
  829. foreach ($this->argumentParserProvider() as $dataSet) { 
  830. $result[] = array( 
  831. $dataSet[0],  
  832. $dataSet[1],  
  833. false,  
  834. ); 
  835.  
  836. // Use data provider for named arguments parser 
  837. foreach ($this->namedArgumentParserProvider() as $dataSet) { 
  838. $result[] = array( 
  839. $dataSet[0],  
  840. false,  
  841. $dataSet[1],  
  842. ); 
  843.  
  844. // Add test cases with combined arguments 
  845. return array_merge( 
  846. $result,  
  847. array( 
  848. array( 
  849. 'arg1 arg2 arg3=value1 arg4="value2"',  
  850. array('arg1', 'arg2'),  
  851. array('arg3' => 'value1', 'arg4' => 'value2') 
  852. ),  
  853. array( 
  854. '@first arg=@last',  
  855. array('@first'),  
  856. array('arg' => '@last') 
  857. ),  
  858. array( 
  859. '[seg arg1] [seg arg2] = [seg value "1"]',  
  860. array('[seg arg1]'),  
  861. array('seg arg2' => '[seg value "1"]') 
  862. ); 
  863.  
  864. public function stringLiteralInCustomHelperProvider() 
  865. return array( 
  866. array('{{#test2 arg1 "Argument 2"}}', array("arg1" => "Argument 1"), "Argument 1:Argument 2"),  
  867. array('{{#test2 "Argument 1" "Argument 2"}}', array("arg1" => "Argument 1"), "Argument 1:Argument 2"),  
  868. array('{{#test2 "Argument 1" arg2}}', array("arg2" => "Argument 2"), "Argument 1:Argument 2") 
  869. ); 
  870.  
  871. /** 
  872. * Test String literals in the context of a helper 
  873. * @param string $template template text 
  874. * @param array $data context data 
  875. * @param string $results The Expected Results 
  876. * @dataProvider stringLiteralInCustomHelperProvider 
  877. * @return void 
  878. */ 
  879. public function testStringLiteralInCustomHelper($template, $data, $results) 
  880. $engine = new \Handlebars\Handlebars(); 
  881. $engine->addHelper('test2', function ($template, $context, $args) { 
  882. $args = $template->parseArguments($args); 
  883.  
  884. $args = array_map(function ($a) use ($context) { 
  885. return $context->get($a); 
  886. }, $args); 
  887.  
  888. return implode(':', $args); 
  889. }); 
  890. $res = $engine->render($template, $data); 
  891. $this->assertEquals($res, $results); 
  892.  
  893. public function integerLiteralInCustomHelperProvider() 
  894. return array( 
  895. array('{{test -5}}', array(), '-5'),  
  896. array('{{test 0}}', array(), '0'),  
  897. array('{{test 12}}', array(), '12'),  
  898. array('{{test 12 [12]}}', array('12' => 'foo'), '12:foo'),  
  899. ); 
  900.  
  901. /** 
  902. * Test integer literals in the context of a helper 
  903. * @param string $template template text 
  904. * @param array $data context data 
  905. * @param string $results The Expected Results 
  906. * @dataProvider integerLiteralInCustomHelperProvider 
  907. * @return void 
  908. */ 
  909. public function testIntegerLiteralInCustomHelper($template, $data, $results) 
  910. $engine = new \Handlebars\Handlebars(); 
  911. $engine->addHelper('test', function ($template, $context, $args) { 
  912. $args = $template->parseArguments($args); 
  913.  
  914. $args = array_map(function ($a) use ($context) { 
  915. return $context->get($a); 
  916. }, $args); 
  917.  
  918. return implode(':', $args); 
  919. }); 
  920. $res = $engine->render($template, $data); 
  921. $this->assertEquals($res, $results); 
  922.  
  923. public function testString() 
  924. $string = new \Handlebars\String("Hello World"); 
  925. $this->assertEquals((string)$string, "Hello World"); 
  926.  
  927. public function testInvalidNames() 
  928. $loader = new \Handlebars\Loader\StringLoader(); 
  929. $engine = new \Handlebars\Handlebars( 
  930. array( 
  931. 'loader' => $loader,  
  932. ); 
  933. $all = \Handlebars\Context::NOT_VALID_NAME_CHARS; 
  934.  
  935. for ($i = 0; $i < strlen($all); $i++) { 
  936. // Dot in string is valid, its an exception here 
  937. if ($all{$i} === '.') { 
  938. continue; 
  939. try { 
  940. $name = 'var' . $all{$i} . 'var'; 
  941. $engine->render('{{' . $name . '}}', array($name => 'VALUE')); 
  942. throw new Exception("Accept the $name :/"); 
  943. } catch (Exception $e) { 
  944. $this->assertInstanceOf("InvalidArgumentException", $e); 
  945.  
  946. /** 
  947. * Helper subexpressions test 
  948. */ 
  949. public function testHelperSubexpressions() 
  950. $loader = new \Handlebars\Loader\StringLoader(); 
  951. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  952. $engine->addHelper('test', function ($template, $context, $args) { 
  953. $parsedArgs = $template->parseArguments($args); 
  954.  
  955. return (count($parsedArgs) ? $context->get($parsedArgs[0]) : '') . 'Test.'; 
  956. }); 
  957.  
  958. // assert that nested syntax is accepted and sub-helper is run 
  959. $this->assertEquals('Test.Test.', $engine->render('{{test (test)}}', array())); 
  960.  
  961. $engine->addHelper('add', function ($template, $context, $args) { 
  962. $sum = 0; 
  963.  
  964. foreach ($template->parseArguments($args) as $value) { 
  965. $sum += intval($context->get($value)); 
  966.  
  967. return $sum; 
  968. }); 
  969.  
  970. // assert that subexpression result is inserted correctly as argument to top level helper 
  971. $this->assertEquals('42', $engine->render('{{add 21 (add 10 (add 5 6))}}', array())); 
  972.  
  973. // assert that bracketed expressions within string literals are treated correctly 
  974. $this->assertEquals("(test)Test.", $engine->render("{{test '(test)'}}", array())); 
  975. $this->assertEquals(")Test.Test.", $engine->render("{{test (test ')')}}", array())); 
  976.  
  977. $engine->addHelper('concat', function (\Handlebars\Template $template, \Handlebars\Context $context, $args) { 
  978. $result = ''; 
  979.  
  980. foreach ($template->parseArguments($args) as $arg) { 
  981. $result .= $context->get($arg); 
  982.  
  983. return $result; 
  984. }); 
  985.  
  986. $this->assertEquals('ACB', $engine->render('{{concat a (concat c b)}}', array('a' => 'A', 'b' => 'B', 'c' => 'C'))); 
  987. $this->assertEquals('ACB', $engine->render('{{concat (concat a c) b}}', array('a' => 'A', 'b' => 'B', 'c' => 'C'))); 
  988. $this->assertEquals('A-B', $engine->render('{{concat (concat a "-") b}}', array('a' => 'A', 'b' => 'B'))); 
  989. $this->assertEquals('A-B', $engine->render('{{concat (concat a "-") b}}', array('a' => 'A', 'b' => 'B', 'A-' => '!'))); 
  990.  
  991. /** 
  992. * Test if and unless adding an extra layer when accessing parent 
  993. */ 
  994. public function testIfUnlessExtraLayer() 
  995. $loader = new \Handlebars\Loader\StringLoader(); 
  996. $engine = new \Handlebars\Handlebars(array('loader' => $loader)); 
  997.  
  998. $this->assertEquals('good', $engine->render('{{#with b}}{{#if this}}{{../../a}}{{/if}}{{/with}}', array('a' => 'good', 'b' => 'stump'))); 
  999. $this->assertEquals('good', $engine->render('{{#with b}}{{#unless false}}{{../../a}}{{/unless}}{{/with}}', array('a' => 'good', 'b' => 'stump'))); 
  1000.  
  1001. /** 
  1002. * Test of Arguments to string conversion. 
  1003. */ 
  1004. public function testArgumentsString() 
  1005. $argsString = 'foo bar [foo bar] baz="value"'; 
  1006. $args = new \Handlebars\Arguments($argsString); 
  1007. $this->assertEquals($argsString, (string)$args); 
  1008.  
  1009.  
  1010. public function stringLiteralsInIfAndUnlessHelpersProvider() 
  1011. return array( 
  1012. // IfHelper 
  1013. array('{{#if "truthyString"}}true{{else}}false{{/if}}', array(), "true"),  
  1014. array("{{#if 'truthyStringSingleQuotes'}}true{{else}}false{{/if}}", array(), "true"),  
  1015. array("{{#if ''}}true{{else}}false{{/if}}", array(), "false"),  
  1016. array("{{#if '0'}}true{{else}}false{{/if}}", array(), "false"),  
  1017. array("{{#if (add 0 1)}}true{{else}}false{{/if}}", array(), "true"),  
  1018. array("{{#if (add 1 -1)}}true{{else}}false{{/if}}", array(), "false"),  
  1019. // UnlessHelper 
  1020. array('{{#unless "truthyString"}}true{{else}}false{{/unless}}', array(), "false"),  
  1021. array("{{#unless 'truthyStringSingleQuotes'}}true{{else}}false{{/unless}}", array(), "false"),  
  1022. array("{{#unless ''}}true{{else}}false{{/unless}}", array(), "true"),  
  1023. array("{{#unless '0'}}true{{else}}false{{/unless}}", array(), "true"),  
  1024. array("{{#unless (add 0 1)}}true{{else}}false{{/unless}}", array(), "false"),  
  1025. array("{{#unless (add 1 -1)}}true{{else}}false{{/unless}}", array(), "true"),  
  1026. ); 
  1027.  
  1028. /** 
  1029. * Test string literals in the context of if and unless helpers 
  1030. * @param string $template template text 
  1031. * @param array $data context data 
  1032. * @param string $results The Expected Results 
  1033. * @dataProvider stringLiteralsInIfAndUnlessHelpersProvider 
  1034. * @return void 
  1035. */ 
  1036. public function testStringLiteralsInIfAndUnlessHelpers($template, $data, $results) 
  1037. $engine = new \Handlebars\Handlebars(); 
  1038.  
  1039. $engine->addHelper('add', function ($template, $context, $args) { 
  1040. $sum = 0; 
  1041.  
  1042. foreach ($template->parseArguments($args) as $value) { 
  1043. $sum += intval($context->get($value)); 
  1044.  
  1045. return $sum; 
  1046. }); 
  1047.  
  1048. $res = $engine->render($template, $data); 
  1049. $this->assertEquals($res, $results); 
  1050.