Merge "LOG SQL dump files getting installed"
[sdnc/oam.git] / dgbuilder / dgeflows / node_modules / ejs / test / ejs.js
1 /* jshint mocha: true */
2
3 /**
4  * Module dependencies.
5  */
6
7 var ejs = require('..')
8   , fs = require('fs')
9   , read = fs.readFileSync
10   , assert = require('assert')
11   , path = require('path');
12
13 try {
14   fs.mkdirSync(__dirname + '/tmp');
15 } catch (ex) {
16   if (ex.code !== 'EEXIST') {
17     throw ex;
18   }
19 }
20
21 // From https://gist.github.com/pguillory/729616
22 function hook_stdio(stream, callback) {
23   var old_write = stream.write;
24
25   stream.write = (function() {
26     return function(string, encoding, fd) {
27       callback(string, encoding, fd);
28     };
29   })(stream.write);
30
31   return function() {
32     stream.write = old_write;
33   };
34 }
35
36 /**
37  * Load fixture `name`.
38  */
39
40 function fixture(name) {
41   return read('test/fixtures/' + name, 'utf8').replace(/\r/g, '').trim();
42 }
43
44 /**
45  * User fixtures.
46  */
47
48 var users = [];
49 users.push({name: 'geddy'});
50 users.push({name: 'neil'});
51 users.push({name: 'alex'});
52
53 suite('ejs.compile(str, options)', function () {
54   test('compile to a function', function () {
55     var fn = ejs.compile('<p>yay</p>');
56     assert.equal(fn(), '<p>yay</p>');
57   });
58
59   test('empty input works', function () {
60     var fn = ejs.compile('');
61     assert.equal(fn(), '');
62   });
63
64   test('throw if there are syntax errors', function () {
65     try {
66       ejs.compile(fixture('fail.ejs'));
67     }
68     catch (err) {
69       assert.ok(err.message.indexOf('compiling ejs') > -1);
70
71       try {
72         ejs.compile(fixture('fail.ejs'), {filename: 'fail.ejs'});
73       }
74       catch (err) {
75         assert.ok(err.message.indexOf('fail.ejs') > -1);
76         return;
77       }
78     }
79     throw new Error('no error reported when there should be');
80   });
81
82   test('allow customizing delimiter local var', function () {
83     var fn;
84     fn = ejs.compile('<p><?= name ?></p>', {delimiter: '?'});
85     assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
86
87     fn = ejs.compile('<p><:= name :></p>', {delimiter: ':'});
88     assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
89
90     fn = ejs.compile('<p><$= name $></p>', {delimiter: '$'});
91     assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
92   });
93
94   test('default to using ejs.delimiter', function () {
95     var fn;
96     ejs.delimiter = '&';
97     fn = ejs.compile('<p><&= name &></p>');
98     assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
99
100     fn = ejs.compile('<p><|= name |></p>', {delimiter: '|'});
101     assert.equal(fn({name: 'geddy'}), '<p>geddy</p>');
102     delete ejs.delimiter;
103   });
104
105   test('have a working client option', function () {
106     var fn
107       , str
108       , preFn;
109     fn = ejs.compile('<p><%= foo %></p>', {client: true});
110     str = fn.toString();
111     if (!process.env.running_under_istanbul) {
112       eval('var preFn = ' + str);
113       assert.equal(preFn({foo: 'bar'}), '<p>bar</p>');
114     }
115   });
116
117   test('support client mode without locals', function () {
118     var fn
119       , str
120       , preFn;
121     fn = ejs.compile('<p><%= "foo" %></p>', {client: true});
122     str = fn.toString();
123     if (!process.env.running_under_istanbul) {
124       eval('var preFn = ' + str);
125       assert.equal(preFn(), '<p>foo</p>');
126     }
127   });
128 });
129
130 suite('ejs.render(str, data)', function () {
131   test('render the template', function () {
132     assert.equal(ejs.render('<p>yay</p>'), '<p>yay</p>');
133   });
134
135   test('empty input works', function () {
136     assert.equal(ejs.render(''), '');
137   });
138
139   test('undefined renders nothing escaped', function () {
140     assert.equal(ejs.render('<%= undefined %>'), '');
141   });
142
143   test('undefined renders nothing raw', function () {
144     assert.equal(ejs.render('<%- undefined %>'), '');
145   });
146
147   test('null renders nothing escaped', function () {
148     assert.equal(ejs.render('<%= null %>'), '');
149   });
150
151   test('null renders nothing raw', function () {
152     assert.equal(ejs.render('<%- null %>'), '');
153   });
154
155   test('zero-value data item renders something escaped', function () {
156     assert.equal(ejs.render('<%= 0 %>'), '0');
157   });
158
159   test('zero-value data object renders something raw', function () {
160     assert.equal(ejs.render('<%- 0 %>'), '0');
161   });
162
163   test('accept locals', function () {
164     assert.equal(ejs.render('<p><%= name %></p>', {name: 'geddy'}),
165         '<p>geddy</p>');
166   });
167
168   test('accept locals without using with() {}', function () {
169     assert.equal(ejs.render('<p><%= locals.name %></p>', {name: 'geddy'},
170                             {_with: false}),
171         '<p>geddy</p>');
172     assert.throws(function() {
173       ejs.render('<p><%= name %></p>', {name: 'geddy'},
174                  {_with: false});
175     }, /name is not defined/);
176   });
177
178   test('accept custom name for locals', function () {
179     ejs.localsName = 'it';
180     assert.equal(ejs.render('<p><%= it.name %></p>', {name: 'geddy'},
181                             {_with: false}),
182         '<p>geddy</p>');
183     assert.throws(function() {
184       ejs.render('<p><%= name %></p>', {name: 'geddy'},
185                  {_with: false});
186     }, /name is not defined/);
187     ejs.localsName = 'locals';
188   });
189
190   test('support caching (pass 1)', function () {
191     var file = __dirname + '/tmp/render.ejs'
192       , options = {cache: true, filename: file}
193       , out = ejs.render('<p>Old</p>', {}, options)
194       , expected = '<p>Old</p>';
195     assert.equal(out, expected);
196   });
197
198   test('support caching (pass 2)', function () {
199     var file = __dirname + '/tmp/render.ejs'
200       , options = {cache: true, filename: file}
201       , out = ejs.render('<p>New</p>', {}, options)
202       , expected = '<p>Old</p>';
203     assert.equal(out, expected);
204   });
205 });
206
207 suite('ejs.renderFile(path, [data], [options], fn)', function () {
208   test('render a file', function(done) {
209     ejs.renderFile('test/fixtures/para.ejs', function(err, html) {
210       if (err) {
211         return done(err);
212       }
213       assert.equal(html, '<p>hey</p>');
214       done();
215     });
216   });
217
218   test('callback is async', function(done) {
219     var async = false;
220     ejs.renderFile('test/fixtures/para.ejs', function(err, html) {
221       if (async) {
222         return done();
223       }
224       throw new Error('not async');
225     });
226     async = true;
227   });
228
229   test('accept locals', function(done) {
230     var data =  {name: 'fonebone'}
231       , options = {delimiter: '$'};
232     ejs.renderFile('test/fixtures/user.ejs', data, options, function(err, html) {
233       if (err) {
234         return done(err);
235       }
236       assert.equal(html, '<h1>fonebone</h1>');
237       done();
238     });
239   });
240
241   test('accept locals without using with() {}', function(done) {
242     var data =  {name: 'fonebone'}
243       , options = {delimiter: '$', _with: false}
244       , doneCount = 0;
245     ejs.renderFile('test/fixtures/user-no-with.ejs', data, options,
246                    function(err, html) {
247       if (err) {
248         if (doneCount === 2) {
249           return;
250         }
251         doneCount = 2;
252         return done(err);
253       }
254       assert.equal(html, '<h1>fonebone</h1>');
255       doneCount++;
256       if (doneCount === 2) {
257         done();
258       }
259     });
260     ejs.renderFile('test/fixtures/user.ejs', data, options, function(err) {
261       if (!err) {
262         if (doneCount === 2) {
263           return;
264         }
265         doneCount = 2;
266         return done(new Error('error not thrown'));
267       }
268       doneCount++;
269       if (doneCount === 2) {
270         done();
271       }
272     });
273   });
274
275   test('not catch err thrown by callback', function(done) {
276     var data =  {name: 'fonebone'}
277       , options = {delimiter: '$'}
278       , counter = 0;
279
280     var d = require('domain').create();
281     d.on('error', function (err) {
282       assert.equal(counter, 1);
283       assert.equal(err.message, 'Exception in callback');
284       done();
285     });
286     d.run(function () {
287       // process.nextTick() needed to work around mochajs/mocha#513
288       //
289       // tl;dr: mocha doesn't support synchronous exception throwing in
290       // domains. Have to make it async. Ticket closed because: "domains are
291       // deprecated :D"
292       process.nextTick(function () {
293         ejs.renderFile('test/fixtures/user.ejs', data, options,
294                        function(err) {
295           counter++;
296           if (err) {
297             assert.notEqual(err.message, 'Exception in callback');
298             return done(err);
299           }
300           throw new Error('Exception in callback');
301         });
302       });
303     });
304   });
305
306   test('support caching (pass 1)', function (done) {
307     var expected = '<p>Old</p>'
308       , file = __dirname + '/tmp/renderFile.ejs'
309       , options = {cache: true};
310     fs.writeFileSync(file, '<p>Old</p>');
311
312     ejs.renderFile(file, {}, options, function (err, out) {
313       if (err) {
314         done(err);
315       }
316       assert.equal(out, expected);
317       done();
318     });
319   });
320
321   test('support caching (pass 2)', function (done) {
322     var expected = '<p>Old</p>'
323       , file = __dirname + '/tmp/renderFile.ejs'
324       , options = {cache: true};
325     fs.writeFileSync(file, '<p>New</p>');
326
327     ejs.renderFile(file, {}, options, function (err, out) {
328       if (err) {
329         done(err);
330       }
331       assert.equal(out, expected);
332       done();
333     });
334   });
335 });
336
337 suite('ejs.clearCache()', function () {
338   test('work properly', function () {
339     var expected = '<p>Old</p>'
340       , file = __dirname + '/tmp/clearCache.ejs'
341       , options = {cache: true, filename: file}
342       , out = ejs.render('<p>Old</p>', {}, options);
343     assert.equal(out, expected);
344
345     ejs.clearCache();
346
347     expected = '<p>New</p>';
348     out = ejs.render('<p>New</p>', {}, options);
349     assert.equal(out, expected);
350   });
351 });
352
353 suite('<%', function () {
354   test('without semicolons', function () {
355     assert.equal(ejs.render(fixture('no.semicolons.ejs')),
356         fixture('no.semicolons.html'));
357   });
358 });
359
360 suite('<%=', function () {
361   test('escape &amp;<script>', function () {
362     assert.equal(ejs.render('<%= name %>', {name: '&nbsp;<script>'}),
363         '&amp;nbsp;&lt;script&gt;');
364   });
365
366   test('should escape \'', function () {
367     assert.equal(ejs.render('<%= name %>', {name: 'The Jones\'s'}),
368       'The Jones&#39;s');
369   });
370
371   test('should escape &foo_bar;', function () {
372     assert.equal(ejs.render('<%= name %>', {name: '&foo_bar;'}),
373       '&amp;foo_bar;');
374   });
375 });
376
377 suite('<%-', function () {
378   test('not escape', function () {
379     assert.equal(ejs.render('<%- name %>', {name: '<script>'}),
380         '<script>');
381   });
382
383   test('terminate gracefully if no close tag is found', function () {
384     try {
385       ejs.compile('<h1>oops</h1><%- name ->');
386       throw new Error('Expected parse failure');
387     }
388     catch (err) {
389       assert.ok(err.message.indexOf('Could not find matching close tag for') > -1);
390     }
391   });
392 });
393
394 suite('%>', function () {
395   test('produce newlines', function () {
396     assert.equal(ejs.render(fixture('newlines.ejs'), {users: users}),
397       fixture('newlines.html'));
398   });
399   test('works with `-%>` interspersed', function () {
400     assert.equal(ejs.render(fixture('newlines.mixed.ejs'), {users: users}),
401       fixture('newlines.mixed.html'));
402   });
403   test('consecutive tags work', function () {
404     assert.equal(ejs.render(fixture('consecutive-tags.ejs')),
405       fixture('consecutive-tags.html'));
406   });
407 });
408
409 suite('-%>', function () {
410   test('not produce newlines', function () {
411     assert.equal(ejs.render(fixture('no.newlines.ejs'), {users: users}),
412       fixture('no.newlines.html'));
413   });
414   test('stack traces work', function () {
415     try {
416       ejs.render(fixture('no.newlines.error.ejs'));
417     }
418     catch (e) {
419       if (e.message.indexOf('>> 4| <%= qdata %>') > -1) {
420         return;
421       }
422       throw e;
423     }
424     throw new Error('Expected ReferenceError');
425   });
426 });
427
428 suite('<%%', function () {
429   test('produce literals', function () {
430     assert.equal(ejs.render('<%%- "foo" %>'),
431       '<%- "foo" %>');
432   });
433   test('work without an end tag', function () {
434     assert.equal(ejs.render('<%%'), '<%');
435     assert.equal(ejs.render(fixture('literal.ejs'), {}, {delimiter: ' '}),
436       fixture('literal.html'));
437   });
438 });
439
440 suite('single quotes', function () {
441   test('not mess up the constructed function', function () {
442     assert.equal(ejs.render(fixture('single-quote.ejs')),
443       fixture('single-quote.html'));
444   });
445 });
446
447 suite('double quotes', function () {
448   test('not mess up the constructed function', function () {
449     assert.equal(ejs.render(fixture('double-quote.ejs')),
450       fixture('double-quote.html'));
451   });
452 });
453
454 suite('backslashes', function () {
455   test('escape', function () {
456     assert.equal(ejs.render(fixture('backslash.ejs')),
457       fixture('backslash.html'));
458   });
459 });
460
461 suite('messed up whitespace', function () {
462   test('work', function () {
463     assert.equal(ejs.render(fixture('messed.ejs'), {users: users}),
464       fixture('messed.html'));
465   });
466 });
467
468 suite('exceptions', function () {
469   test('produce useful stack traces', function () {
470     try {
471       ejs.render(fixture('error.ejs'), {}, {filename: 'error.ejs'});
472     }
473     catch (err) {
474       assert.equal(err.path, 'error.ejs');
475       assert.equal(err.stack.split('\n').slice(0, 8).join('\n'), fixture('error.out'));
476       return;
477     }
478     throw new Error('no error reported when there should be');
479   });
480
481   test('not include fancy stack info if compileDebug is false', function () {
482     try {
483       ejs.render(fixture('error.ejs'), {}, {
484         filename: 'error.ejs',
485         compileDebug: false
486       });
487     }
488     catch (err) {
489       assert.ok(!err.path);
490       assert.notEqual(err.stack.split('\n').slice(0, 8).join('\n'), fixture('error.out'));
491       return;
492     }
493     throw new Error('no error reported when there should be');
494   });
495
496   var unhook = null;
497   test('log JS source when debug is set', function (done) {
498     var out = ''
499       , needToExit = false;
500     unhook = hook_stdio(process.stdout, function (str) {
501       out += str;
502       if (needToExit) {
503         return;
504       }
505       if (out.indexOf('__output')) {
506         needToExit = true;
507         unhook();
508         unhook = null;
509         return done();
510       }
511     });
512     ejs.render(fixture('hello-world.ejs'), {}, {debug: true});
513   });
514   teardown(function() {
515     if (!unhook) {
516       return;
517     }
518     unhook();
519     unhook = null;
520   });
521 });
522
523 suite('include()', function () {
524   test('include ejs', function () {
525     var file = 'test/fixtures/include-simple.ejs';
526     assert.equal(ejs.render(fixture('include-simple.ejs'), {}, {filename: file}),
527         fixture('include-simple.html'));
528   });
529
530   test('include ejs fails without `filename`', function () {
531     try {
532       ejs.render(fixture('include-simple.ejs'));
533     }
534     catch (err) {
535       assert.ok(err.message.indexOf('requires the \'filename\' option') > -1);
536       return;
537     }
538     throw new Error('expected inclusion error');
539   });
540
541   test('strips BOM', function () {
542     assert.equal(
543       ejs.render('<%- include("fixtures/includes/bom.ejs") %>',
544         {}, {filename: path.join(__dirname, 'f.ejs')}),
545       '<p>This is a file with BOM.</p>');
546   });
547
548   test('include ejs with locals', function () {
549     var file = 'test/fixtures/include.ejs';
550     assert.equal(ejs.render(fixture('include.ejs'), {pets: users}, {filename: file, delimiter: '@'}),
551         fixture('include.html'));
552   });
553
554   test('include ejs with absolute path and locals', function () {
555     var file = 'test/fixtures/include-abspath.ejs';
556     assert.equal(ejs.render(fixture('include-abspath.ejs'),
557       {dir: path.join(__dirname, 'fixtures'), pets: users, path: path},
558       {filename: file, delimiter: '@'}),
559         fixture('include.html'));
560   });
561
562   test('work when nested', function () {
563     var file = 'test/fixtures/menu.ejs';
564     assert.equal(ejs.render(fixture('menu.ejs'), {pets: users}, {filename: file}),
565         fixture('menu.html'));
566   });
567
568   test('work with a variable path', function () {
569     var file = 'test/fixtures/menu_var.ejs',
570         includePath = 'includes/menu-item';
571     assert.equal(ejs.render(fixture('menu.ejs'), {pets: users, varPath:  includePath}, {filename: file}),
572       fixture('menu.html'));
573   });
574
575   test('include arbitrary files as-is', function () {
576     var file = 'test/fixtures/include.css.ejs';
577     assert.equal(ejs.render(fixture('include.css.ejs'), {pets: users}, {filename: file}),
578         fixture('include.css.html'));
579   });
580
581   test('pass compileDebug to include', function () {
582     var file = 'test/fixtures/include.ejs'
583       , fn;
584     fn = ejs.compile(fixture('include.ejs'), {
585       filename: file
586     , delimiter: '@'
587     , compileDebug: false
588     });
589     try {
590       // Render without a required variable reference
591       fn({foo: 'asdf'});
592     }
593     catch(e) {
594       assert.equal(e.message, 'pets is not defined');
595       assert.ok(!e.path);
596       return;
597     }
598     throw new Error('no error reported when there should be');
599   });
600
601   test('is dynamic', function () {
602     fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>Old</p>');
603     var file = 'test/fixtures/include_cache.ejs'
604       , options = {filename: file}
605       , out = ejs.compile(fixture('include_cache.ejs'), options);
606     assert.equal(out(), '<p>Old</p>');
607
608     fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>New</p>');
609     assert.equal(out(), '<p>New</p>');
610   });
611
612   test('support caching (pass 1)', function () {
613     fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>Old</p>');
614     var file = 'test/fixtures/include_cache.ejs'
615       , options = {cache: true, filename: file}
616       , out = ejs.render(fixture('include_cache.ejs'), {}, options)
617       , expected = fixture('include_cache.html');
618     assert.equal(out, expected);
619   });
620
621   test('support caching (pass 2)', function () {
622     fs.writeFileSync(__dirname + '/tmp/include.ejs', '<p>New</p>');
623     var file = 'test/fixtures/include_cache.ejs'
624       , options = {cache: true, filename: file}
625       , out = ejs.render(fixture('include_cache.ejs'), {}, options)
626       , expected = fixture('include_cache.html');
627     assert.equal(out, expected);
628   });
629 });
630
631 suite('preprocessor include', function () {
632   test('work', function () {
633     var file = 'test/fixtures/include_preprocessor.ejs';
634     assert.equal(ejs.render(fixture('include_preprocessor.ejs'), {pets: users}, {filename: file, delimiter: '@'}),
635         fixture('include_preprocessor.html'));
636   });
637
638   test('fails without `filename`', function () {
639     try {
640       ejs.render(fixture('include_preprocessor.ejs'), {pets: users}, {delimiter: '@'});
641     }
642     catch (err) {
643       assert.ok(err.message.indexOf('requires the \'filename\' option') > -1);
644       return;
645     }
646     throw new Error('expected inclusion error');
647   });
648
649   test('strips BOM', function () {
650     assert.equal(
651       ejs.render('<% include fixtures/includes/bom.ejs %>',
652         {}, {filename: path.join(__dirname, 'f.ejs')}),
653       '<p>This is a file with BOM.</p>');
654   });
655
656   test('work when nested', function () {
657     var file = 'test/fixtures/menu_preprocessor.ejs';
658     assert.equal(ejs.render(fixture('menu_preprocessor.ejs'), {pets: users}, {filename: file}),
659         fixture('menu_preprocessor.html'));
660   });
661
662   test('include arbitrary files as-is', function () {
663     var file = 'test/fixtures/include_preprocessor.css.ejs';
664     assert.equal(ejs.render(fixture('include_preprocessor.css.ejs'), {pets: users}, {filename: file}),
665         fixture('include_preprocessor.css.html'));
666   });
667
668   test('pass compileDebug to include', function () {
669     var file = 'test/fixtures/include_preprocessor.ejs'
670       , fn;
671     fn = ejs.compile(fixture('include_preprocessor.ejs'), {
672       filename: file
673     , delimiter: '@'
674     , compileDebug: false
675     });
676     try {
677       // Render without a required variable reference
678       fn({foo: 'asdf'});
679     }
680     catch(e) {
681       assert.equal(e.message, 'pets is not defined');
682       assert.ok(!e.path);
683       return;
684     }
685     throw new Error('no error reported when there should be');
686   });
687
688   test('is static', function () {
689     fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>Old</p>');
690     var file = 'test/fixtures/include_preprocessor_cache.ejs'
691       , options = {filename: file}
692       , out = ejs.compile(fixture('include_preprocessor_cache.ejs'), options);
693     assert.equal(out(), '<p>Old</p>');
694
695     fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>New</p>');
696     assert.equal(out(), '<p>Old</p>');
697   });
698
699   test('support caching (pass 1)', function () {
700     fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>Old</p>');
701     var file = 'test/fixtures/include_preprocessor_cache.ejs'
702       , options = {cache: true, filename: file}
703       , out = ejs.render(fixture('include_preprocessor_cache.ejs'), {}, options)
704       , expected = fixture('include_preprocessor_cache.html');
705     assert.equal(out, expected);
706   });
707
708   test('support caching (pass 2)', function () {
709     fs.writeFileSync(__dirname + '/tmp/include_preprocessor.ejs', '<p>New</p>');
710     var file = 'test/fixtures/include_preprocessor_cache.ejs'
711       , options = {cache: true, filename: file}
712       , out = ejs.render(fixture('include_preprocessor_cache.ejs'), {}, options)
713       , expected = fixture('include_preprocessor_cache.html');
714     assert.equal(out, expected);
715   });
716 });
717
718 suite('comments', function () {
719   test('fully render with comments removed', function () {
720     assert.equal(ejs.render(fixture('comments.ejs')),
721         fixture('comments.html'));
722   });
723 });
724
725 suite('require', function () {
726
727   // Only works with inline/preprocessor includes
728   test('allow ejs templates to be required as node modules', function () {
729       var file = 'test/fixtures/include_preprocessor.ejs'
730         , template = require(__dirname + '/fixtures/menu_preprocessor.ejs');
731       if (!process.env.running_under_istanbul) {
732         assert.equal(template({filename: file, pets: users}),
733           fixture('menu_preprocessor.html'));
734       }
735   });
736 });
737
738 suite('examples', function () {
739   function noop () {}
740   fs.readdirSync('examples').forEach(function (f) {
741     if (!/\.js$/.test(f)) {
742       return;
743     }
744     suite(f, function () {
745       test('doesn\'t throw any errors', function () {
746         var stderr = hook_stdio(process.stderr, noop)
747           , stdout = hook_stdio(process.stdout, noop);
748         try {
749           require('../examples/' + f);
750         }
751         catch (ex) {
752           stdout();
753           stderr();
754           throw ex;
755         }
756         stdout();
757         stderr();
758       });
759     });
760   });
761 });