PageRenderTime 265ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/filters.js

https://github.com/chrisdickinson/plate
JavaScript | 1230 lines | 1003 code | 226 blank | 1 comment | 58 complexity | 74d0ea64a2ba4c0c51acdd90d5fe83e3 MD5 | raw file
  1. var plate = require('../index')
  2. , utils = require('../lib/date')
  3. , test = require('tape')
  4. , mocktimeout = require('./mocktimeout')
  5. test("Test that the add filter works as expected", mocktimeout(function(assert) {
  6. var tpl = new plate.Template("{{ test|add:3 }}"),
  7. rnd = ~~(Math.random()*10);
  8. tpl.render({'test':rnd}, function(err, data) {
  9. assert.equal((rnd+3), parseInt(data, 10));
  10. });
  11. })
  12. )
  13. test("test that the split filter works as expected", mocktimeout(function(assert) {
  14. var tpl_by_char = new plate.Template('{% for i in test|split:"" %}{{ i }}\n{% endfor %}')
  15. , tpl_with_none = new plate.Template('{% for i in test|split %}{{ i }}\n{% endfor %}')
  16. , tpl_split_by_pattern = new plate.Template('{% for i in test|split:"," %}{{ i }}\n{% endfor %}')
  17. tpl_by_char.render({test: 'hey there'}, function(err, data) {
  18. assert.ok(!err)
  19. assert.equal(data, 'hey there'.split('').join('\n')+'\n')
  20. })
  21. tpl_with_none.render({test: 'anything'}, function(err, data) {
  22. assert.ok(!err)
  23. assert.equal(data, 'anything\n')
  24. })
  25. tpl_split_by_pattern.render({test: 'hey,there'}, function(err, data) {
  26. assert.ok(!err)
  27. assert.equal(data, 'hey\nthere\n')
  28. })
  29. }))
  30. test("Test that the addslashes filter works as expected", mocktimeout(function(assert) {
  31. var tpl = new plate.Template("{{ test|addslashes }}"),
  32. ctxt = {},
  33. inp = [],
  34. num = 1 + ~~(Math.random()*10);
  35. for(var i = 0; inp.push("'") < num; ++i) {};
  36. inp = inp.join("asdf");
  37. ctxt.test = inp;
  38. tpl.render(ctxt, function(err, data) {
  39. assert.equal(data.split('\\').length, num+1);
  40. });
  41. })
  42. )
  43. test("Test that the capfirst filter works as expected", mocktimeout(function(assert) {
  44. var corpus = ['a', 'fluffy bunny', '99 times', 'lol', '', 3.2, {'toString':function(){return 'lol';}}],
  45. template = new plate.Template("{{ test|capfirst }}"),
  46. emitter = function(item) {
  47. var ctxt = { 'test':item };
  48. template.render(ctxt, function(err, data) {
  49. assert.equal(data.charAt(0), item.toString().charAt(0).toUpperCase());
  50. });
  51. };
  52. for(var i = 0; i < corpus.length; ++i) {
  53. emitter(corpus[i]);
  54. }
  55. })
  56. )
  57. test("Test that the center filter works as expected.", mocktimeout(function(assert) {
  58. var corpus = ['a', 'bunny', 'rode', 'firmly', 'through', 'the', 'wood'],
  59. template = new plate.Template("{{ test|center:centernum }}"),
  60. emitter = function(item, len) {
  61. template.render({'test':item, 'centernum':len}, function(err, data) {
  62. if(item.length >= len) {
  63. assert.equal(data.length, data.length);
  64. } else {
  65. assert.equal(data.length, len);
  66. var parts = data.split(item),
  67. wlen = len - item.length,
  68. strong_side = item.length % 2 == 0 ? 0 : 1,
  69. testlen = Math.floor(wlen/2.0),
  70. uneven = (wlen/2.0) - Math.floor(wlen/2.0) > 0.0;
  71. if(uneven) {
  72. assert.equal(parts[strong_side].length, testlen+1);
  73. assert.equal(parts[0+!strong_side].length, testlen);
  74. } else {
  75. assert.equal(parts[strong_side].length, testlen);
  76. assert.equal(parts[0+strong_side].length, testlen);
  77. }
  78. }
  79. });
  80. },
  81. item = null;
  82. while(corpus.length > 0) {
  83. item = corpus.shift();
  84. emitter(item, ~~(Math.random() * 10) + 2);
  85. }
  86. }))
  87. test("Test that the cut filter works as expected", mocktimeout(function(assert) {
  88. var corpus = 'abcdefghijklmnopqrstuvwxyz',
  89. template = new plate.Template("{{ test|cut:val }}"),
  90. rand = function() {
  91. return String.fromCharCode(~~(Math.random() * ('z'.charCodeAt(0) - 'a'.charCodeAt(0))) + 'a'.charCodeAt(0));
  92. },
  93. emitter = function(item) {
  94. template.render({'test':corpus, 'val':item}, function(err, data) {
  95. assert.equal(data.indexOf(item), -1);
  96. });
  97. };
  98. var len = ~~(Math.random() * 10);
  99. while(len-- > 0) emitter(rand());
  100. })
  101. )
  102. test("Test that the date filter defaults to 'N j, Y'", mocktimeout(function(assert) {
  103. var tpl = new plate.Template("{{ test|date }}")
  104. , dt
  105. , now = utils.date(dt = new Date, "N j, Y")
  106. tpl.render({test:dt}, function(err, data) {
  107. assert.equal(data, now)
  108. })
  109. })
  110. )
  111. test("Test that the date filter accepts a format arg", mocktimeout(function(assert) {
  112. var tpl = new plate.Template("{{ test|date:'jS o\\f F' }}")
  113. , dt
  114. , now = utils.date(dt = new Date, "jS o\\f F")
  115. tpl.render({test:dt}, function(err, data) {
  116. assert.equal(data, now)
  117. })
  118. })
  119. )
  120. test("Test that the date filter accepts non-date arguments", mocktimeout(function(assert) {
  121. var tpl = new plate.Template("{{ test|date:'jS o\\f F' }}")
  122. , dt
  123. , now = utils.date(dt = new Date, "jS o\\f F")
  124. tpl.render({test:+dt}, function(err, data) {
  125. assert.equal(data, now)
  126. })
  127. tpl.render({test:''+dt}, function(err, data) {
  128. assert.equal(data, now)
  129. })
  130. })
  131. )
  132. test("Test that the default filter works as expected", mocktimeout(function(assert) {
  133. var random = ~~(Math.random() * 10),
  134. template = new plate.Template("{{ test|default:default }}"),
  135. corpus = ['truthy', 0, null, false, NaN, {'toString':function(){return'lol';}}],
  136. emitter = function(item) {
  137. template.render({'test':item, 'default':random}, function(err, data) {
  138. if(item) assert.equal(data, item.toString());
  139. else assert.equal(''+data, ''+random);
  140. });
  141. }
  142. while(corpus.length) {
  143. emitter(corpus.shift());
  144. }
  145. })
  146. )
  147. test("Test that the dictsort filter works as expected", mocktimeout(function(assert) {
  148. var F = function() {
  149. var self = this;
  150. this.value = ~~(Math.random() * 10);
  151. this.toString = function() {
  152. return ''+self.value;
  153. };
  154. },
  155. len = ~~(Math.random() * 10) + 1,
  156. arr = [],
  157. sorted = null,
  158. template = new plate.Template("{% for i in items|dictsort:\"value\" %}{{ i }}\n{% endfor %}");
  159. while(len--) {
  160. arr.push(new F());
  161. }
  162. sorted = arr.slice().sort(function(x, y) {
  163. if(x.value < y.value) return -1;
  164. if(x.value > y.value) return 1;
  165. return 0;
  166. });
  167. template.render({'items':arr}, function(err, data) {
  168. var split = data.split('\n').slice(0,-1);
  169. while(split.length > 0) {
  170. assert.equal(split.shift(), sorted.shift().toString());
  171. }
  172. });
  173. })
  174. )
  175. test("Test that the dictsortreversed filter works as expected", mocktimeout(function(assert) {
  176. var F = function() {
  177. var self = this;
  178. this.value = ~~(Math.random() * 10);
  179. this.toString = function() {
  180. return ''+self.value;
  181. };
  182. },
  183. len = ~~(Math.random() * 10) + 1,
  184. arr = [],
  185. sorted = null,
  186. template = new plate.Template("{% for i in items|dictsortreversed:\"value\" %}{{ i }}\n{% endfor %}");
  187. while(len--) {
  188. arr.push(new F());
  189. }
  190. sorted = arr.slice().sort(function(x, y) {
  191. if(x.value < y.value) return -1;
  192. if(x.value > y.value) return 1;
  193. return 0;
  194. }).reverse();
  195. template.render({'items':arr}, function(err, data) {
  196. var split = data.split('\n').slice(0,-1);
  197. while(split.length > 0) {
  198. assert.equal(split.shift(), sorted.shift().toString());
  199. }
  200. });
  201. })
  202. )
  203. test("Test that the divisibleby filter works as expected", mocktimeout(function(assert) {
  204. var pairs = (function(num) {
  205. var accum = [];
  206. for(;accum.length < num; accum.push([~~(Math.random()*10), ~~(Math.random()*10)]));
  207. return accum;
  208. })(~~(Math.random() * 10) + 2),
  209. template = new plate.Template("{% for x,y in pairs %}{% if x|divisibleby:y %}y{% else %}n{% endif %}\n{% endfor %}");
  210. template.render({pairs:pairs}, function(err, data) {
  211. var bits = data.split('\n').slice(0, -1);
  212. for(var i = 0, len = bits.length; i < len; ++i) {
  213. assert.equal(pairs[i][0] % pairs[i][1] == 0 ? 'y' : 'n', bits[i]);
  214. }
  215. });
  216. })
  217. )
  218. test("Test that the filesizeformat filter works as expected", mocktimeout(function(assert) {
  219. var items = [],
  220. template = new plate.Template("{{ i|filesizeformat }}");
  221. for(var i = 2, len = (1024*1024*1024*1024); i < len; i = Math.pow(i, 2)) {
  222. (function(item) {
  223. template.render({i:item}, function(err, data) {
  224. var words = data.split(/\s+/);
  225. if(item < 1024) {
  226. assert.equal(words.slice(-1)[0], 'bytes');
  227. } else if(item < (1024*1024)) {
  228. assert.equal(words.slice(-1)[0], 'KB');
  229. } else if(item < (1024*1024*1024)) {
  230. assert.equal(words.slice(-1)[0], 'MB');
  231. } else {
  232. assert.equal(words.slice(-1)[0], 'GB');
  233. }
  234. });
  235. })(i);
  236. }
  237. })
  238. )
  239. test("Test that the first filter works as expected", mocktimeout(function(assert) {
  240. var items = (function(len) {
  241. var accum = [];
  242. while(accum.length < len) {
  243. accum.push(~~(Math.random()*10));
  244. }
  245. return accum;
  246. })(~~(Math.random()*10)+1),
  247. template = new plate.Template("{{ items|first }}");
  248. template.render({items:items}, function(err, data) {
  249. assert.equal(data, items[0].toString());
  250. });
  251. })
  252. )
  253. test("Test that the floatformat filter works as expected", mocktimeout(function(assert) {
  254. var tpl = new plate.Template(
  255. "{% for x,y in values %}{{ forloop.counter0 }}:{{ x|floatformat:y }}\n{% endfor %}"
  256. ),
  257. context = {
  258. 'values':[]
  259. };
  260. while(context.values.length < 10) {
  261. context.values.push([
  262. (Math.random() * 10),
  263. (~~(Math.random()*10)-5)
  264. ]);
  265. }
  266. tpl.render(context, function(err, data) {
  267. var lines = data.split('\n').slice(0, -1),
  268. line_split,
  269. idx,
  270. val,
  271. val_split,
  272. decimal;
  273. while(lines.length) {
  274. line_split = lines.shift().split(':');
  275. idx = line_split[0];
  276. val = line_split[1];
  277. val_split = val.split('.');
  278. decimal = val_split.length > 1 ? val_split[1] : '';
  279. if(context.values[idx][1] < 1) {
  280. assert.ok(decimal.length <= parseInt(Math.abs(context.values[idx][1])));
  281. } else {
  282. assert.ok(decimal.length == parseInt(context.values[idx][1]));
  283. }
  284. }
  285. });
  286. })
  287. )
  288. test("Test that the get_digit filter works as expected.", mocktimeout(function(assert) {
  289. var tpl = new plate.Template(
  290. "{% for x in digit|make_list %}{{ digit|get_digit:forloop.counter }}\n{% endfor %}"
  291. ),
  292. context = {
  293. 'digit':~~(Math.random()*1000)
  294. };
  295. tpl.render(context, function(err, data) {
  296. var bits = data.split('\n').slice(0, -1),
  297. num = context.digit.toString();
  298. assert.equal(bits.reverse().join(''), num+'');
  299. });
  300. })
  301. )
  302. test("Test that get_digit returns the original input when given a bad digit", mocktimeout(function(assert) {
  303. var tpl = new plate.Template(
  304. "{{ digit|get_digit:badfood }}"
  305. ),
  306. context = {
  307. 'digit':~~(Math.random()*1000),
  308. 'badfood':'asdf'
  309. };
  310. tpl.render(context, function(err, data) {
  311. assert.equal(data, context.digit.toString());
  312. });
  313. })
  314. )
  315. test("Test that the join filter works as expected.", mocktimeout(function(assert) {
  316. var tpl = new plate.Template(
  317. "{{ a_list|join:value }}"
  318. ),
  319. context = {
  320. a_list:[1,2,3,4,5],
  321. value:~~(Math.random()*100)
  322. };
  323. tpl.render(context, function(err, data) {
  324. assert.equal(data, context.a_list.join(context.value));
  325. });
  326. })
  327. )
  328. test("Test that last grabs the last element of a list.", mocktimeout(function(assert) {
  329. var tpl = new plate.Template(
  330. "{{ a_list|last }}"
  331. ),
  332. context = {
  333. a_list:[1,2,3,3,4,556,6,76,7,5,4,6].sort(function(lhs, rhs) {
  334. return Math.random() > 0.5;
  335. })
  336. };
  337. tpl.render(context, function(err, data) {
  338. assert.equal(data, ''+context.a_list[context.a_list.length-1]);
  339. });
  340. })
  341. )
  342. test("Test that length works with simple arrays.", mocktimeout(function(assert) {
  343. var tpl = new plate.Template(
  344. "{{ a_list|length }}"
  345. ),
  346. random_array = function() {
  347. var len = 1+~~(Math.random()*100),
  348. out = [];
  349. while(out.length < len) out.push(Math.random());
  350. return out;
  351. },
  352. context = {
  353. a_list:random_array()
  354. };
  355. tpl.render(context, function(err, data) {
  356. assert.equal(context.a_list.length+'', data);
  357. });
  358. })
  359. )
  360. test("Test that length works with complex objects.", mocktimeout(function(assert) {
  361. var randLen = ~~(Math.random()*10) + 1,
  362. lenFn = function(callback) {
  363. setTimeout(function() {
  364. callback(null, randLen);
  365. }, 1);
  366. },
  367. tpl = new plate.Template(
  368. "{{ a_list|length }}"
  369. ),
  370. context = {
  371. a_list:{length:lenFn}
  372. };
  373. tpl.render(context, function(err, data) {
  374. assert.equal(data, randLen+'');
  375. });
  376. })
  377. )
  378. test("Test that length_is works with simple arrays.", mocktimeout(function(assert) {
  379. var tpl = new plate.Template(
  380. "{{ a_list|length_is:a_list.length }}\n{{ a_list|length_is:0 }}"
  381. ),
  382. random_array = function() {
  383. var len = 1+~~(Math.random()*100),
  384. out = [];
  385. while(out.length < len) out.push(Math.random());
  386. return out;
  387. },
  388. context = {
  389. a_list:random_array()
  390. };
  391. tpl.render(context, function(err, data) {
  392. assert.equal('true\nfalse', data);
  393. });
  394. })
  395. )
  396. test("Test that length_is works with complex objects.", mocktimeout(function(assert) {
  397. var randLen = ~~(Math.random()*10) + 1,
  398. lenFn = function(callback) {
  399. setTimeout(function() {
  400. callback(null, randLen);
  401. }, 1);
  402. },
  403. tpl = new plate.Template(
  404. "{% with a_list.length as len %}{{ a_list|length_is:len }}\n{{ a_list|length_is:0 }}{% endwith %}"
  405. ),
  406. context = {
  407. a_list:{length:lenFn}
  408. };
  409. tpl.render(context, function(err, data) {
  410. assert.equal(data, "true\nfalse");
  411. });
  412. })
  413. )
  414. test("Test that linebreaks wraps all double-spaced elements in <p> tags.", mocktimeout(function(assert) {
  415. var text = "Hi there\n\nI am new to world\n\nEnjoying time very much.",
  416. tpl = new plate.Template(
  417. "{{ text|linebreaks }}"
  418. ),
  419. context = { text: text };
  420. tpl.render(context, function(err, data) {
  421. assert.equal(data, "<p>Hi there</p><p>I am new to world</p><p>Enjoying time very much.</p>");
  422. });
  423. })
  424. )
  425. test("Test that linebreaks escapes.", mocktimeout(function(assert) {
  426. var text = "Hi there\n\nI am <strong>new</strong> to world\n\nEnjoying time very much.",
  427. tpl = new plate.Template(
  428. "{{ text|linebreaks }}"
  429. ),
  430. context = { text: text };
  431. tpl.render(context, function(err, data) {
  432. assert.equal(data, "<p>Hi there</p><p>I am &lt;strong&gt;new&lt;/strong&gt; to world</p><p>Enjoying time very much.</p>");
  433. });
  434. })
  435. )
  436. test("Test that linebreaks creates <br /> tags for all single newline characters.", mocktimeout(function(assert) {
  437. var text = "Hi there\nI am new to world\nEnjoying time very much.",
  438. tpl = new plate.Template(
  439. "{{ text|linebreaks }}"
  440. ),
  441. context = { text: text };
  442. tpl.render(context, function(err, data) {
  443. assert.equal(data, "<p>Hi there<br />I am new to world<br />Enjoying time very much.</p>");
  444. });
  445. })
  446. )
  447. test("Test that linebreaksbr converts all newlines to br elements", mocktimeout(function(assert) {
  448. var text = "Hi there\n\nI am new\n to world\n\nEnjoying time very much.",
  449. tpl = new plate.Template(
  450. "{{ text|linebreaksbr }}"
  451. ),
  452. context = { text: text };
  453. tpl.render(context, function(err, data) {
  454. assert.equal(data, text.replace(/\n/g, '<br />'));
  455. });
  456. })
  457. )
  458. test("Test that linebreaksbr escapes", mocktimeout(function(assert) {
  459. var text = "Hi there\n\nI am <em>new</em>\n to world\n\nEnjoying time very much.",
  460. tpl = new plate.Template(
  461. "{{ text|linebreaksbr }}"
  462. ),
  463. context = { text: text };
  464. tpl.render(context, function(err, data) {
  465. assert.equal(
  466. data
  467. , "Hi there<br /><br />I am &lt;em&gt;new&lt;/em&gt;<br /> to world<br /><br />Enjoying time very much."
  468. )
  469. });
  470. })
  471. )
  472. test("Test that linenumbers prepends line numbers to each line of input text.", mocktimeout(function(assert) {
  473. var text = "Yes\nI\nLike\nJavascript\nIs\nVery\nGood",
  474. tpl = new plate.Template(
  475. "{{ text|linenumbers }}"
  476. ),
  477. context = { text: text };
  478. tpl.render(context, function(err, data) {
  479. var expected = text.split('\n');
  480. for(var i = 0, len = expected.length; i < len; ++i) {
  481. expected[i] = (i+1)+'. '+expected[i];
  482. }
  483. expected = expected.join('\n');
  484. assert.equal(data, expected);
  485. });
  486. })
  487. )
  488. test("Test that ljust left justifies as expected.", mocktimeout(function(assert) {
  489. var tpl = new plate.Template(
  490. "{% for i in range %}{{ str|ljust:i }}\n{% endfor %}"
  491. ),
  492. makeRange = function() {
  493. var out = [], len = ~~(Math.random()*20) + 1;
  494. while(out.length < len) { out.push(out.length+1); }
  495. return out;
  496. },
  497. context = {
  498. 'str':'hi',
  499. 'range':makeRange()
  500. };
  501. tpl.render(context, function(err, data) {
  502. var bits = data.split('\n').slice(0, -1);
  503. while(bits.length) {
  504. var idx = context.range.length - bits.length
  505. bit = bits.shift();
  506. if(bit.length > context.str.length) {
  507. assert.equal(bit.length, context.range[idx]);
  508. assert.ok((/\s+$/g).test(bit));
  509. } else {
  510. assert.strictEqual(bit.length, context.str.length);
  511. }
  512. }
  513. });
  514. })
  515. )
  516. test("Test that lower works.", mocktimeout(function(assert) {
  517. var tpl = new plate.Template(
  518. "{% for word in words %}{{ word|lower }}{% endfor %}"
  519. );
  520. tpl.render({words:['Asdf', '1ST', 'YEAHHHH']}, function(err, data) {
  521. assert.ok(!(/[A-Z]+/g).test(data));
  522. });
  523. })
  524. )
  525. test("Test that make_list just passes through arrays.", mocktimeout(function(assert) {
  526. var tpl = new plate.Template(
  527. '{% for i in item|make_list %}{{ i }}{% if not forloop.last %}\n{% endif %}{% endfor %}'
  528. ),
  529. item = [1,2,3,4,5];
  530. tpl.render({'item':item}, function(err, data) {
  531. var bits = data.split('\n');
  532. assert.equal(bits.length, item.length);
  533. while(bits.length) {
  534. assert.equal(bits.pop(), ''+item.pop());
  535. };
  536. });
  537. })
  538. )
  539. test("Test that make_list works with strings.", mocktimeout(function(assert) {
  540. var tpl = new plate.Template(
  541. '{% for i in item|make_list %}{{ i }}{% if not forloop.last %}\n{% endif %}{% endfor %}'
  542. ),
  543. item = "random"+Math.random();
  544. tpl.render({'item':item}, function(err, data) {
  545. var bits = data.split('\n');
  546. item = item.toString().split('');
  547. assert.equal(bits.length, item.length);
  548. while(bits.length) {
  549. assert.equal(bits.pop(), item.pop());
  550. };
  551. });
  552. })
  553. )
  554. test("Test that make_list works with numbers.", mocktimeout(function(assert) {
  555. var tpl = new plate.Template(
  556. '{% for i in item|make_list %}{{ i }}{% if not forloop.last %}\n{% endif %}{% endfor %}'
  557. ),
  558. item = ~~(100 * Math.random());
  559. tpl.render({'item':item}, function(err, data) {
  560. var bits = data.split('\n');
  561. item = item.toString().split('');
  562. assert.equal(bits.length, item.length);
  563. while(bits.length) {
  564. assert.equal(bits.pop(), item.pop());
  565. };
  566. });
  567. })
  568. )
  569. test("Test that phone2numeric works as expected.", mocktimeout(function(assert) {
  570. var phone = '1-800-4GO-OGLE',
  571. expected = '1-800-446-6453',
  572. tpl = new plate.Template(
  573. "{{ item|phone2numeric }}"
  574. );
  575. tpl.render({'item':phone}, function(err, data) {
  576. assert.equal(data, expected);
  577. });
  578. })
  579. )
  580. test("Assert that pluralize coerces single argument to plural case.", mocktimeout(function(assert) {
  581. var values = [1,3],
  582. tpl = new plate.Template(
  583. '{% for i in items %}{{ i|pluralize:"s" }}:{% endfor %}'
  584. );
  585. tpl.render({items:values}, function(err, data) {
  586. assert.equal(data, ':s:');
  587. });
  588. })
  589. )
  590. test("Assert that pluralize coerces two arguments to singular, plural.", mocktimeout(function(assert) {
  591. var values = [1,3],
  592. tpl = new plate.Template(
  593. '{% for i in items %}{{ i|pluralize:"y,s" }}:{% endfor %}'
  594. );
  595. tpl.render({items:values}, function(err, data) {
  596. assert.equal(data, 'y:s:');
  597. });
  598. })
  599. )
  600. test("Assert that random pulls an item out of an array randomly.", mocktimeout(function(assert) {
  601. var arr = [1,2,3,4,5,6,7,8,9,10],
  602. tpl = new plate.Template(
  603. '{% for i in list %}{{ list|random }}\n{% endfor %}'
  604. );
  605. tpl.render({list:arr}, function(err, data) {
  606. var bits = data.split('\n').slice(0, -1);
  607. while(bits.length) {
  608. for(var i = 0, len = arr.length, item = bits.pop(), found = false; i < len && !found; ++i) {
  609. found = arr[i] == item;
  610. }
  611. assert.ok(found);
  612. }
  613. });
  614. })
  615. )
  616. test("Test that rjust right justifies as expected.", mocktimeout(function(assert) {
  617. var tpl = new plate.Template(
  618. "{% for i in range %}{{ str|rjust:i }}\n{% endfor %}"
  619. ),
  620. makeRange = function() {
  621. var out = [], len = ~~(Math.random()*20) + 1;
  622. while(out.length < len) { out.push(out.length+1); }
  623. return out;
  624. },
  625. context = {
  626. 'str':'hi',
  627. 'range':makeRange()
  628. };
  629. tpl.render(context, function(err, data) {
  630. var bits = data.split('\n').slice(0, -1);
  631. while(bits.length) {
  632. var idx = context.range.length - bits.length
  633. bit = bits.shift();
  634. assert.ok(bit.length === context.str.length || bit.length === context.range[idx]);
  635. if(bit.length > context.str.length) {
  636. assert.ok((/^\s+/g).test(bit));
  637. }
  638. }
  639. });
  640. })
  641. )
  642. test("Test that upper works.", mocktimeout(function(assert) {
  643. var tpl = new plate.Template(
  644. "{% for word in words %}{{ word|upper }}{% endfor %}"
  645. );
  646. tpl.render({words:['Asdf', '1ST', 'YEAHHHH']}, function(err, data) {
  647. assert.ok(!(/[a-z]+/g).test(data));
  648. });
  649. })
  650. )
  651. test("Test that HTML characters are escaped by default", mocktimeout(function(assert) {
  652. var tpl = new plate.Template('{{ value }}')
  653. tpl.render({'value':'<>"\'&'}, function(err, data) {
  654. assert.ok(!err)
  655. assert.equal(data, '&lt;&gt;&quot;&#39;&amp;')
  656. })
  657. })
  658. )
  659. test("Test that HTML characters may be marked 'safe'", mocktimeout(function(assert) {
  660. var tpl = new plate.Template('{{ value|safe }}')
  661. , x = '<>"\'&'
  662. tpl.render({'value':x}, function(err, data) {
  663. assert.ok(!err)
  664. assert.equal(data, x)
  665. })
  666. })
  667. )
  668. test("Test that escape automatically escapes the input", mocktimeout(function(assert) {
  669. var tpl = new plate.Template('{{ value|escape }}')
  670. , x = '&'
  671. tpl.render({value:x}, function(err, data) {
  672. assert.ok(!err)
  673. assert.equal(data, '&amp;')
  674. })
  675. })
  676. )
  677. test("Test that escape does not double-escape the input", mocktimeout(function(assert) {
  678. var tpl = new plate.Template('{{ value|escape|escape }}')
  679. , x = '&'
  680. tpl.render({value:x}, function(err, data) {
  681. assert.ok(!err)
  682. assert.equal(data, '&amp;')
  683. })
  684. })
  685. )
  686. test("Test that escape respects 'safe'", mocktimeout(function(assert) {
  687. var tpl = new plate.Template('{{ value|safe|escape }}')
  688. , x = '&'
  689. tpl.render({value:x}, function(err, data) {
  690. assert.ok(!err)
  691. assert.equal(data, '&')
  692. })
  693. })
  694. )
  695. test("Test that force_escape does not respect 'safe'", mocktimeout(function(assert) {
  696. var tpl = new plate.Template('{{ value|safe|force_escape }}')
  697. , x = '&'
  698. tpl.render({value:x}, function(err, data) {
  699. assert.ok(!err)
  700. assert.equal(data, '&amp;')
  701. })
  702. })
  703. )
  704. test("Test that slice works with :N", mocktimeout(function(assert) {
  705. var items = [1,2,3,4],
  706. rand = ~~(items.length * Math.random()),
  707. tpl = new plate.Template(
  708. "{% for i in items|slice:rand %}{{ i }}:{% endfor %}"
  709. );
  710. tpl.render({items:items, rand:':'+rand}, function(err, data) {
  711. var bits = data.split(':').slice(0, -1),
  712. expected = items.slice(0, rand);
  713. assert.equal(bits.length, expected.length);
  714. for(var i = 0, len = bits.length; i < len; ++i) {
  715. assert.equal(bits[i], ''+expected[i]);
  716. }
  717. });
  718. })
  719. )
  720. test("Test that slice works with N:", mocktimeout(function(assert) {
  721. var items = [1,2,3,4],
  722. rand = ~~(items.length * Math.random()),
  723. tpl = new plate.Template(
  724. "{% for i in items|slice:rand %}{{ i }}:{% endfor %}"
  725. );
  726. tpl.render({items:items, rand:rand+':'}, function(err, data) {
  727. var bits = data.split(':').slice(0, -1),
  728. expected = items.slice(rand);
  729. assert.equal(bits.length, expected.length);
  730. for(var i = 0, len = bits.length; i < len; ++i) {
  731. assert.equal(bits[i], ''+expected[i]);
  732. }
  733. });
  734. })
  735. )
  736. test("Test that slugify removes unicode, turns spaces into dashes, lowercases everything.", mocktimeout(function(assert) {
  737. var makeRandomString = function() {
  738. var len = ~~(Math.random()*1000),
  739. out = [];
  740. while(out.length < len) out.push(String.fromCharCode(~~(Math.random()*256)));
  741. return out.join('');
  742. },
  743. tpl = new plate.Template('{{ item|slugify }}'),
  744. context = {item:makeRandomString()};
  745. tpl.render(context, function(err, data) {
  746. assert.ok(!((/[^a-z\-0-9_]+/g).test(data)));
  747. });
  748. })
  749. )
  750. test("Test that timesince works as expected.", mocktimeout(function(assert) {
  751. var times = [
  752. ['3 years', (+new Date) - 31557600000 * 3]
  753. , ['1 month', (+new Date) - 2592000000 * 1]
  754. , ['2 days', (+new Date) - 86400000 * 2]
  755. , ['23 hours', (+new Date) - 3600000 * 23]
  756. , ['30 minutes', (+new Date) - 60000 * 30]
  757. ]
  758. , tpl = new plate.Template("{% for expected, time in times %}{{ time|timesince }}\n{% endfor %}")
  759. tpl.render({times:times}, function(err, data) {
  760. assert.ok(!err)
  761. data = data.split('\n').slice(0, -1)
  762. for(var i = 0; i < data.length; ++i) {
  763. assert.equal(data[i], times[i][0])
  764. }
  765. })
  766. })
  767. )
  768. test("Test that timesince may accept an input.", mocktimeout(function(assert) {
  769. var fake_now = +new Date() + ~~(Math.random() * 10000)
  770. var times = [
  771. ['3 years', fake_now - 31557600000 * 3]
  772. , ['1 month', fake_now - 2592000000 * 1]
  773. , ['2 days', fake_now - 86400000 * 2]
  774. , ['23 hours', fake_now - 3600000 * 23]
  775. , ['30 minutes', fake_now - 60000 * 30]
  776. ]
  777. , tpl = new plate.Template("{% for expected, time in times %}{{ time|timesince:n }}\n{% endfor %}")
  778. tpl.render({times:times, n:fake_now}, function(err, data) {
  779. assert.ok(!err)
  780. data = data.split('\n').slice(0, -1)
  781. for(var i = 0; i < data.length; ++i) {
  782. assert.equal(data[i], times[i][0])
  783. }
  784. })
  785. })
  786. )
  787. test("Test that timesince displays the largest and second largest bit of multiple time values.", mocktimeout(function(assert) {
  788. var times = [
  789. ['3 years, 2 days', (+new Date) - (31557600000 * 3 + 86400000 * 2 + 60000)]
  790. , ['1 month, 23 hours', (+new Date) - (2592000000 + 3600000 * 23)]
  791. , ['1 year, 10 days', (+new Date) - (31557600000 + 10 * 86400000 + 20 * 60000)]
  792. ]
  793. , tpl = new plate.Template("{% for expected, time in times %}{{ time|timesince }}\n{% endfor %}")
  794. tpl.render({times:times}, function(err, data) {
  795. assert.ok(!err)
  796. data = data.split('\n').slice(0, -1)
  797. for(var i = 0; i < data.length; ++i) {
  798. assert.equal(data[i], times[i][0])
  799. }
  800. })
  801. })
  802. )
  803. test("Test that timesince displays '0 minutes' when time is in future, or when time is < 60 seconds away", mocktimeout(function(assert) {
  804. var t = new Date()
  805. , n = t + 1000
  806. , tpl = new plate.Template("{{ t|timesince:n }}")
  807. tpl.render({t:t, n:n}, function(err, data) {
  808. assert.equal(data, '0 minutes')
  809. })
  810. tpl.render({t:t, n:t}, function(err, data) {
  811. assert.equal(data, '0 minutes')
  812. })
  813. })
  814. )
  815. test("Test that title titlecases input.", mocktimeout(function(assert) {
  816. var words = ['hey','there','how','are','you',"you're",'1st','lol'],
  817. sentence = words.sort(function() {
  818. return Math.random() > 0.5;
  819. }).join(' ');
  820. var tpl = new plate.Template("{{ sentence|title }}");
  821. tpl.render({sentence:sentence}, function(err, data) {
  822. var bits = data.split(/\s+/g);
  823. while(bits.length) {
  824. assert.ok((/^[A-Z0-9]{1}[a-z']+/g).test(bits.pop()));
  825. }
  826. });
  827. })
  828. )
  829. test("Test that striptags removes all HTML tags no matter how cool they are.", mocktimeout(function(assert) {
  830. var testData =[
  831. '<div class="versionadded">',
  832. '<span class="title">New in Django 1.1.2:</span> <a class="reference internal" href="../../../releases/1.1.2/"><em>Please, see the release notes</em></a></div>',
  833. '<p>In the Django 1.1.X series, this is a no-op tag that returns an empty string for',
  834. 'future compatibility purposes. In Django 1.2 and later, it is used for CSRF',
  835. 'protection, as described in the documentation for <a class="reference internal" href="../../contrib/csrf/"><em>Cross Site Request',
  836. 'Forgeries</em></a>.</p>',
  837. '</div>'
  838. ].join('\n');
  839. var tpl = new plate.Template('{{ text|striptags }}');
  840. tpl.render({text:testData}, function(err, data) {
  841. // fail if you see a tag.
  842. assert.ok(!((/<[^>]*?>/g).test(data)));
  843. });
  844. })
  845. )
  846. test("Test that a string of characters gets truncated properly.", mocktimeout(function(assert) {
  847. var input = 'This is a collection of words.';
  848. var tpl = new plate.Template('{{ input|truncatechars:8 }}'),
  849. context = {input:input};
  850. tpl.render(context, function(err, data) {
  851. assert.equal(data, 'This is ...');
  852. });
  853. var tpl = new plate.Template('{{ input|truncatechars:20 }}'),
  854. context = {input:input};
  855. tpl.render(context, function(err, data) {
  856. assert.equal(data, 'This is a collection...');
  857. });
  858. var tpl = new plate.Template('{{ input|truncatechars:200 }}'),
  859. context = {input:input};
  860. tpl.render(context, function(err, data) {
  861. assert.equal(data, 'This is a collection of words.');
  862. });
  863. })
  864. )
  865. test("Test that a busted number doesn't double call the callback.", mocktimeout(function(assert) {
  866. var input = 'This is a collection of words.';
  867. var tpl = new plate.Template('{{ input|truncatechars:abc }}'),
  868. context = {input:input};
  869. tpl.render(context, function(err, data) {
  870. assert.equal(data, 'This is a collection of words.');
  871. });
  872. })
  873. )
  874. test("Test that a string of words gets truncated properly.", mocktimeout(function(assert) {
  875. var input = 'This is a collection of words.';
  876. var tpl = new plate.Template('{{ input|truncatewords:3 }}'),
  877. context = {input:input};
  878. tpl.render(context, function(err, data) {
  879. assert.equal(data, 'This is a...');
  880. });
  881. var tpl = new plate.Template('{{ input|truncatewords:0 }}'),
  882. context = {input:input};
  883. tpl.render(context, function(err, data) {
  884. assert.equal(data, '...');
  885. });
  886. var tpl = new plate.Template('{{ input|truncatewords:8 }}'),
  887. context = {input:input};
  888. tpl.render(context, function(err, data) {
  889. assert.equal(data, 'This is a collection of words.');
  890. });
  891. })
  892. )
  893. test("Test that a busted number doesn't double call the callback.", mocktimeout(function(assert) {
  894. var input = 'This is a collection of words.';
  895. var tpl = new plate.Template('{{ input|truncatewords:abc }}'),
  896. context = {input:input};
  897. tpl.render(context, function(err, data) {
  898. assert.equal(data, 'This is a collection of words.');
  899. });
  900. })
  901. )
  902. test("Test that unordered list... makes unordered lists. Awesome ones.", mocktimeout(function(assert) {
  903. var input = ['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']],
  904. output = '<li>States<ul><li>Kansas<ul><li>Lawrence</li><li>Topeka</li></ul></li><li>Illinois</li></ul></li>';
  905. var tpl = new plate.Template('{{ input|unordered_list }}'),
  906. context = {input:input};
  907. tpl.render(context, function(err, data) {
  908. assert.equal(data, output);
  909. });
  910. })
  911. )
  912. test("Test that urlencode encodes all appropriate characters by using the built-in escape function.", mocktimeout(function(assert) {
  913. var stringOfEverything = (function() {
  914. var out = [];
  915. while(out.length < 256) { out.push(String.fromCharCode(out.length)); }
  916. return out.join('');
  917. })(),
  918. tpl = new plate.Template('{{ str|urlencode }}');
  919. tpl.render({str:stringOfEverything}, function(err, data) {
  920. assert.equal(data, escape(stringOfEverything));
  921. });
  922. })
  923. )
  924. test("Test that urlize will turn urls of the form http://whatever.com/whatever, https://whatever.org/whatever into links.", mocktimeout(function(assert) {
  925. var links = ['https://google.com/', 'http://neversaw.us/media/blah.png', 'http://example.com/?some=params&are=here'],
  926. para = ['hey there i love ', links[0], ' and(',links[1],')', ' and paramed ', links[2]].join(''),
  927. result = 'hey there i love <a href="'+links[0]+'">'+links[0]+'</a> and(<a href="'+links[1]+'">'+links[1]+'</a>) and paramed <a href="'+links[2]+'">'+links[2]+'</a>';
  928. var tpl = new plate.Template('{{ para|urlize }}');
  929. tpl.render({para:para}, function(err, data) {
  930. assert.equal(data, result);
  931. });
  932. })
  933. )
  934. test("Test that urlizetrunc will turn urls of the form http://whatever.com/whatever, https://whatever.org/whatever into links with truncated text.", mocktimeout(function(assert) {
  935. var links = ['https://google.com/', 'http://neversaw.us/media/blah.png', 'http://example.com/?some=params&are=here'],
  936. para = ['hey there i love ', links[0], ' and(',links[1],')', ' and paramed ', links[2]].join(''),
  937. result = 'hey there i love <a href="'+links[0]+'">https://google....</a> and(<a href="'+links[1]+'">http://neversaw...</a>) and paramed <a href="'+links[2]+'">http://example....</a>';
  938. var tpl = new plate.Template('{{ para|urlizetrunc:"15" }}');
  939. tpl.render({para:para}, function(err, data) {
  940. assert.equal(data, result);
  941. });
  942. })
  943. )
  944. test("Assert that wordcount counts the number of words.", mocktimeout(function(assert) {
  945. var lorem = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
  946. count = lorem.split(/\s+/g).length,
  947. tpl = new plate.Template("{{ lorem|wordcount }}");
  948. tpl.render({lorem:lorem}, function(err, data) {
  949. assert.equal(data, count.toString());
  950. });
  951. })
  952. )
  953. test("Assert that wordwrap wraps lines at a given number.", mocktimeout(function(assert) {
  954. var lorem = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
  955. values = [1,2,3,4,5,6,7,8,9],
  956. tpl = new plate.Template("{% for value in values %}{{ lorem|wordwrap:value }}:{% endfor %}");
  957. tpl.render({lorem:lorem, values:values}, function(err, data) {
  958. var bits = data.split(':').slice(0, -1);
  959. for(var i = 0, len = bits.length; i < len; ++i) {
  960. var lilbits = bits[i].split('\n'),
  961. max = 0,
  962. val;
  963. while(lilbits.length) {
  964. val = lilbits.pop().split(/\s+/g).length;
  965. max = max < val ? val : max;
  966. }
  967. assert.ok(max <= values[i]);
  968. }
  969. });
  970. })
  971. )
  972. test("Test that the yesno filter coerces values into truthy,falsy", mocktimeout(function(assert) {
  973. return
  974. var tpl = new plate.Template('{% for value in values %}{{ value|yesno:"truthy,falsy" }}\n{% endfor %}'),
  975. context = {
  976. values:[true, 1, {}, [], false, null]
  977. };
  978. tpl.render(context, function(err, data) {
  979. var bits = data.split('\n').slice(0, -1);
  980. for(var i = 0, len = bits.length; i < len; ++i) {
  981. var mode = context.values[i] ? 'truthy' : 'falsy';
  982. assert.equal(bits[i], mode);
  983. }
  984. });
  985. })
  986. )
  987. test("Test that the yesno filter coerces values into true,false,maybe", mocktimeout(function(assert) {
  988. var tpl = new plate.Template('{% for value in values %}{{ value|yesno:"truthy,falsy,maybe" }}\n{% endfor %}'),
  989. context = {
  990. values:[true, 1, {}, [], false, null]
  991. };
  992. tpl.render(context, function(err, data) {
  993. var bits = data.split('\n').slice(0, -1);
  994. for(var i = 0, len = bits.length; i < len; ++i) {
  995. var mode = context.values[i] ? 'truthy' : context.values[i] === false ? 'falsy' : 'maybe';
  996. assert.equal(bits[i], mode);
  997. }
  998. });
  999. })
  1000. )