You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

574 lines
12KB

  1. module('Interpreter');
  2. test("Parser", function() {
  3. expect(3);
  4. // matches whitespace_partial.html
  5. equals(
  6. Mustache.to_html(
  7. '<h1>{{ greeting }}</h1>\n{{> partial }}\n<h3>{{ farewell }}</h3>',
  8. {
  9. greeting: function() {
  10. return "Welcome";
  11. },
  12. farewell: function() {
  13. return "Fair enough, right?";
  14. },
  15. partial: {
  16. name: "Chris",
  17. value: 10000,
  18. taxed_value: function() {
  19. return this.value - (this.value * 0.4);
  20. },
  21. in_ca: true
  22. }
  23. },
  24. {partial:'Hello {{ name}}\nYou have just won ${{value }}!\n{{# in_ca }}\nWell, ${{ taxed_value }}, after taxes.\n{{/ in_ca }}\n'}
  25. ),
  26. '<h1>Welcome</h1>\nHello Chris\nYou have just won $10000!\n\nWell, $6000, after taxes.\n\n\n<h3>Fair enough, right?</h3>',
  27. 'Whitespace in Tag names'
  28. );
  29. equals(
  30. Mustache.to_html(
  31. '{{tag1}}\n\n\n{{tag2}}\n',
  32. { tag1: 'Hello', tag2: 'World' },
  33. {}
  34. ),
  35. 'Hello\n\n\nWorld\n',
  36. 'Preservation of white space'
  37. );
  38. try {
  39. Mustache.to_html(
  40. '{{=tag1}}',
  41. { tag1: 'Hello' },
  42. {}
  43. );
  44. ok(false);
  45. } catch (e) {
  46. equals(e.message, 'Unexpected end of document.');
  47. }
  48. });
  49. test("Basic Variables", function() {
  50. expect(3);
  51. // matches escaped.html
  52. equals(
  53. Mustache.to_html(
  54. '<h1>{{title}}</h1>\nBut not {{entities}}.\n',
  55. {
  56. title: function() {
  57. return "Bear > Shark";
  58. },
  59. entities: "&quot;"
  60. },
  61. {}
  62. ),
  63. '<h1>Bear &gt; Shark</h1>\nBut not &amp;quot;.\n',
  64. 'HTML Escaping'
  65. );
  66. // matches null_string.html
  67. equals(
  68. Mustache.to_html(
  69. 'Hello {{name}}\nglytch {{glytch}}\nbinary {{binary}}\nvalue {{value}}\nnumeric {{numeric}}',
  70. {
  71. name: "Elise",
  72. glytch: true,
  73. binary: false,
  74. value: null,
  75. numeric: function() {
  76. return NaN;
  77. }
  78. },
  79. {}
  80. ),
  81. 'Hello Elise\nglytch true\nbinary false\nvalue \nnumeric NaN',
  82. 'Different variable types'
  83. );
  84. // matches two_in_a_row.html
  85. equals(
  86. Mustache.to_html(
  87. '{{greeting}}, {{name}}!',
  88. {
  89. name: "Joe",
  90. greeting: "Welcome"
  91. },
  92. {}
  93. ),
  94. 'Welcome, Joe!'
  95. );
  96. });
  97. test("'{' or '&' (Unescaped Variable)", function() {
  98. expect(2);
  99. // matches unescaped.html
  100. equals(
  101. Mustache.to_html(
  102. '<h1>{{{title}}}</h1>',
  103. {
  104. title: function() {
  105. return "Bear > Shark";
  106. }
  107. },
  108. {}
  109. ),
  110. '<h1>Bear > Shark</h1>',
  111. '{ character'
  112. );
  113. equals(
  114. Mustache.to_html(
  115. '<h1>{{&title}}</h1>',
  116. {
  117. title: function() {
  118. return "Bear > Shark";
  119. }
  120. },
  121. {}
  122. ),
  123. '<h1>Bear > Shark</h1>',
  124. '& character'
  125. );
  126. });
  127. test("'#' (Sections)", function() {
  128. expect(7);
  129. // matches array_of_partials_implicit_partial.html
  130. equals(
  131. Mustache.to_html(
  132. 'Here is some stuff!\n{{#numbers}}\n{{>partial}}\n{{/numbers}}',
  133. { numbers: ['1', '2', '3', '4'] },
  134. { partial: '{{.}}' }
  135. ),
  136. 'Here is some stuff!\n\n1\n\n2\n\n3\n\n4\n',
  137. 'Array of Partials (Implicit)'
  138. );
  139. // matches array_of_partials_partial.html
  140. equals(
  141. Mustache.to_html(
  142. 'Here is some stuff!\n{{#numbers}}\n{{>partial}}\n{{/numbers}}',
  143. { numbers: [{i: '1'}, {i: '2'}, {i: '3'}, {i: '4'}] },
  144. { partial: '{{i}}' }
  145. ),
  146. 'Here is some stuff!\n\n1\n\n2\n\n3\n\n4\n',
  147. 'Array of Partials (Explicit)'
  148. );
  149. // matches array_of_strings.html
  150. equals(
  151. Mustache.to_html(
  152. '{{#array_of_strings}}{{.}} {{/array_of_strings}}',
  153. {array_of_strings: ['hello', 'world']},
  154. {}
  155. ),
  156. 'hello world ',
  157. 'Array of Strings'
  158. );
  159. // mathces higher_order_sections.html
  160. equals(
  161. Mustache.to_html(
  162. '{{#bolder}}Hi {{name}}.{{/bolder}}\n',
  163. {
  164. "name": "Tater",
  165. "helper": "To tinker?",
  166. "bolder": function() {
  167. return function(text, render) {
  168. return "<b>" + render(text) + '</b> ' + this.helper;
  169. }
  170. }
  171. },
  172. {}
  173. ),
  174. '<b>Hi Tater.</b> To tinker?\n'
  175. );
  176. // matches recursion_with_same_names.html
  177. equals(
  178. Mustache.to_html(
  179. '{{ name }}\n{{ description }}\n\n{{#terms}}\n {{name}}\n {{index}}\n{{/terms}}\n',
  180. {
  181. name: 'name',
  182. description: 'desc',
  183. terms: [
  184. {name: 't1', index: 0},
  185. {name: 't2', index: 1},
  186. ]
  187. },
  188. {}
  189. ),
  190. 'name\ndesc\n\n\n t1\n 0\n\n t2\n 1\n\n'
  191. );
  192. // matches reuse_of_enumerables.html
  193. equals(
  194. Mustache.to_html(
  195. '{{#terms}}\n {{name}}\n {{index}}\n{{/terms}}\n{{#terms}}\n {{name}}\n {{index}}\n{{/terms}}\n',
  196. {
  197. terms: [
  198. {name: 't1', index: 0},
  199. {name: 't2', index: 1},
  200. ]
  201. },
  202. {}
  203. ),
  204. '\n t1\n 0\n\n t2\n 1\n\n\n t1\n 0\n\n t2\n 1\n\n',
  205. 'Lazy match of Section and Inverted Section'
  206. );
  207. // matches section_as_context.html
  208. equals(
  209. Mustache.to_html(
  210. '{{#a_object}}\n <h1>{{title}}</h1>\n <p>{{description}}</p>\n <ul>\n {{#a_list}}\n <li>{{label}}</li>\n {{/a_list}}\n </ul>\n{{/a_object}}\n',
  211. {
  212. a_object: {
  213. title: 'this is an object',
  214. description: 'one of its attributes is a list',
  215. a_list: [{label: 'listitem1'}, {label: 'listitem2'}]
  216. }
  217. },
  218. {}
  219. ),
  220. '\n <h1>this is an object</h1>\n <p>one of its attributes is a list</p>\n <ul>\n \n <li>listitem1</li>\n \n <li>listitem2</li>\n \n </ul>\n\n',
  221. 'Lazy match of Section and Inverted Section'
  222. );
  223. });
  224. test("'^' (Inverted Section)", function() {
  225. expect(1);
  226. // matches inverted_section.html
  227. equals(
  228. Mustache.to_html(
  229. '{{#repo}}<b>{{name}}</b>{{/repo}}\n{{^repo}}No repos :({{/repo}}\n',
  230. {
  231. "repo": []
  232. },
  233. {}
  234. ),
  235. '\nNo repos :(\n'
  236. );
  237. });
  238. test("'>' (Partials)", function() {
  239. expect(5);
  240. // matches view_partial.html
  241. equals(
  242. Mustache.to_html(
  243. '<h1>{{greeting}}</h1>\n{{>partial}}\n<h3>{{farewell}}</h3>',
  244. {
  245. greeting: function() {
  246. return "Welcome";
  247. },
  248. farewell: function() {
  249. return "Fair enough, right?";
  250. },
  251. partial: {
  252. name: "Chris",
  253. value: 10000,
  254. taxed_value: function() {
  255. return this.value - (this.value * 0.4);
  256. },
  257. in_ca: true
  258. }
  259. },
  260. {partial: 'Hello {{name}}\nYou have just won ${{value}}!\n{{#in_ca}}\nWell, ${{ taxed_value }}, after taxes.\n{{/in_ca}}\n'}
  261. ),
  262. '<h1>Welcome</h1>\nHello Chris\nYou have just won $10000!\n\nWell, $6000, after taxes.\n\n\n<h3>Fair enough, right?</h3>'
  263. );
  264. // matches array_partial.html
  265. equals(
  266. Mustache.to_html(
  267. '{{>partial}}',
  268. {
  269. partial: {
  270. array: ['1', '2', '3', '4']
  271. }
  272. },
  273. { partial: 'Here\'s a non-sense array of values\n{{#array}}\n {{.}}\n{{/array}}' }
  274. ),
  275. 'Here\'s a non-sense array of values\n\n 1\n\n 2\n\n 3\n\n 4\n'
  276. );
  277. // matches template_partial.html
  278. equals(
  279. Mustache.to_html(
  280. '<h1>{{title}}</h1>\n{{>partial}}',
  281. {
  282. title: function() {
  283. return "Welcome";
  284. },
  285. partial: {
  286. again: "Goodbye"
  287. }
  288. },
  289. {partial:'Again, {{again}}!'}
  290. ),
  291. '<h1>Welcome</h1>\nAgain, Goodbye!'
  292. );
  293. // matches partial_recursion.html
  294. equals(
  295. Mustache.to_html(
  296. '{{name}}\n{{#kids}}\n{{>partial}}\n{{/kids}}',
  297. {
  298. name: '1',
  299. kids: [
  300. {
  301. name: '1.1',
  302. children: [
  303. {name: '1.1.1'}
  304. ]
  305. }
  306. ]
  307. },
  308. {partial:'{{name}}\n{{#children}}\n{{>partial}}\n{{/children}}'}
  309. ),
  310. '1\n\n1.1\n\n1.1.1\n\n\n'
  311. );
  312. try {
  313. Mustache.to_html(
  314. '{{>partial}}',
  315. {},
  316. {partal: ''}
  317. );
  318. ok(false);
  319. } catch(e) {
  320. equals(e.message, "Unknown partial 'partial'");
  321. }
  322. });
  323. test("'=' (Set Delimiter)", function() {
  324. expect(1);
  325. // matches delimiter.html
  326. equals(
  327. Mustache.to_html(
  328. '{{=<% %>=}}*\n<% first %>\n* <% second %>\n<%=| |=%>\n* | third |\n|={{ }}=|\n* {{ fourth }}',
  329. {
  330. first: "It worked the first time.",
  331. second: "And it worked the second time.",
  332. third: "Then, surprisingly, it worked the third time.",
  333. fourth: "Fourth time also fine!."
  334. },
  335. {}
  336. ),
  337. '*\nIt worked the first time.\n* And it worked the second time.\n\n* Then, surprisingly, it worked the third time.\n\n* Fourth time also fine!.',
  338. 'Simple Set Delimiter'
  339. );
  340. });
  341. test("'!' (Comments)", function() {
  342. expect(1);
  343. // matches comments.html
  344. equals(
  345. Mustache.to_html(
  346. '<h1>{{title}}{{! just something interesting... or not... }}</h1>\n',
  347. {
  348. title: function() {
  349. return "A Comedy of Errors";
  350. }
  351. },
  352. {}
  353. ),
  354. '<h1>A Comedy of Errors</h1>\n'
  355. );
  356. });
  357. test("'%' (Pragmas)", function() {
  358. expect(3);
  359. // matches array_of_strings_options.html
  360. equals(
  361. Mustache.to_html(
  362. '{{%IMPLICIT-ITERATOR iterator=rob}}\n{{#array_of_strings_options}}{{rob}} {{/array_of_strings_options}}',
  363. {array_of_strings_options: ['hello', 'world']},
  364. {}
  365. ),
  366. '\nhello world ',
  367. 'IMPLICIT-ITERATOR pragma'
  368. );
  369. // matches unknown_pragma.txt
  370. try {
  371. equals(
  372. Mustache.to_html(
  373. '{{%I-HAVE-THE-GREATEST-MUSTACHE}}\n',
  374. {},
  375. {}
  376. ),
  377. 'hello world ',
  378. 'IMPLICIT-ITERATOR pragma'
  379. );
  380. ok(false);
  381. } catch (e) {
  382. equals(e.message, 'This implementation of mustache doesn\'t understand the \'I-HAVE-THE-GREATEST-MUSTACHE\' pragma');
  383. }
  384. equals(
  385. Mustache.to_html(
  386. '{{%IMPLICIT-ITERATOR}}{{#dataSet}}{{.}}:{{/dataSet}}',
  387. { dataSet: [ 'Object 1', 'Object 2', 'Object 3' ] },
  388. {}
  389. ),
  390. "Object 1:Object 2:Object 3:"
  391. );
  392. });
  393. test("Empty", function() {
  394. expect(2);
  395. // matches empty_template.html
  396. equals(
  397. Mustache.to_html(
  398. '<html><head></head><body><h1>Test</h1></body></html>',
  399. {},
  400. {}
  401. ),
  402. '<html><head></head><body><h1>Test</h1></body></html>',
  403. 'Empty Template'
  404. );
  405. // matches empty_partial.html
  406. equals(
  407. Mustache.to_html(
  408. 'hey {{foo}}\n{{>partial}}\n',
  409. {
  410. foo: 1
  411. },
  412. {partial: 'yo'}
  413. ),
  414. 'hey 1\nyo\n',
  415. 'Empty Partial'
  416. );
  417. });
  418. test("Demo", function() {
  419. expect(2);
  420. // matches simple.html
  421. equals(
  422. Mustache.to_html(
  423. 'Hello {{name}}\nYou have just won ${{value}}!\n{{#in_ca}}\nWell, ${{ taxed_value }}, after taxes.\n{{/in_ca}}',
  424. {
  425. name: "Chris",
  426. value: 10000,
  427. taxed_value: function() {
  428. return this.value - (this.value * 0.4);
  429. },
  430. in_ca: true
  431. },
  432. {}
  433. ),
  434. 'Hello Chris\nYou have just won $10000!\n\nWell, $6000, after taxes.\n',
  435. 'A simple template'
  436. );
  437. // matches complex.html
  438. var template = [
  439. '<h1>{{header}}</h1>',
  440. '{{#list}}',
  441. ' <ul>',
  442. ' {{#item}}',
  443. ' {{#current}}',
  444. ' <li><strong>{{name}}</strong></li>',
  445. ' {{/current}}',
  446. ' {{#link}}',
  447. ' <li><a href="{{url}}">{{name}}</a></li>',
  448. ' {{/link}}',
  449. ' {{/item}}',
  450. ' </ul>',
  451. '{{/list}}',
  452. '{{#empty}}',
  453. ' <p>The list is empty.</p>',
  454. '{{/empty}}',
  455. ].join('\n');
  456. var view = {
  457. header: function() {
  458. return "Colors";
  459. },
  460. item: [
  461. {name: "red", current: true, url: "#Red"},
  462. {name: "green", current: false, url: "#Green"},
  463. {name: "blue", current: false, url: "#Blue"}
  464. ],
  465. link: function() {
  466. return this["current"] !== true;
  467. },
  468. list: function() {
  469. return this.item.length !== 0;
  470. },
  471. empty: function() {
  472. return this.item.length === 0;
  473. }
  474. };
  475. var expected_result = '<h1>Colors</h1>\n\n <ul>\n \n \n <li><strong>red</strong></li>\n \n \n <li><a href=\"#Red\">red</a></li>\n \n \n \n \n <li><a href=\"#Green\">green</a></li>\n \n \n \n \n <li><a href=\"#Blue\">blue</a></li>\n \n \n </ul>\n\n';
  476. equals(
  477. Mustache.to_html(
  478. template,
  479. view,
  480. {}
  481. ),
  482. expected_result,
  483. 'A complex template'
  484. );
  485. });
  486. test("Regression Suite", function() {
  487. expect(3);
  488. // matches bug_11_eating_whitespace.html
  489. equals(
  490. Mustache.to_html(
  491. '{{tag}} foo',
  492. { tag: "yo" },
  493. {}
  494. ),
  495. 'yo foo',
  496. 'Issue 11'
  497. );
  498. // matches delimiters_partial.html
  499. equals(
  500. Mustache.to_html(
  501. '{{#enumerate}}\n{{>partial}}\n{{/enumerate}}',
  502. { enumerate: [ { text: 'A' }, { text: 'B' } ] },
  503. { partial: '{{=[[ ]]=}}\n{{text}}\n[[={{ }}=]]' }
  504. ),
  505. '\n\n{{text}}\n\n\n\n{{text}}\n\n',
  506. 'Issue 44'
  507. );
  508. // matches bug_46_set_delimiter.html
  509. equals(
  510. Mustache.to_html(
  511. '{{=[[ ]]=}}[[#IsMustacheAwesome]]mustache is awesome![[/IsMustacheAwesome]]',
  512. {IsMustacheAwesome: true},
  513. {}
  514. ),
  515. 'mustache is awesome!',
  516. 'Issue 46'
  517. );
  518. });