Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

644 wiersze
14KB

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