123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- /**
- * Module dependencies.
- */
- var ejs = require('..')
- , fs = require('fs')
- , read = fs.readFileSync
- , assert = require('should');
- /**
- * Load fixture `name`.
- */
- function fixture(name) {
- return read('test/fixtures/' + name, 'utf8').replace(/\r/g, '');
- }
- /**
- * User fixtures.
- */
- var users = [];
- users.push({ name: 'tobi' });
- users.push({ name: 'loki' });
- users.push({ name: 'jane' });
- describe('ejs.compile(str, options)', function(){
- it('should compile to a function', function(){
- var fn = ejs.compile('<p>yay</p>');
- fn().should.equal('<p>yay</p>');
- })
- it('should throw if there are syntax errors', function(){
- try {
- ejs.compile(fixture('fail.ejs'));
- } catch (err) {
- err.message.should.include('compiling ejs');
- try {
- ejs.compile(fixture('fail.ejs'), { filename: 'fail.ejs' });
- } catch (err) {
- err.message.should.include('fail.ejs');
- return;
- }
- }
- assert(false, 'compiling a file with invalid syntax should throw an exception');
- })
- it('should allow customizing delimiters', function(){
- var fn = ejs.compile('<p>{= name }</p>', { open: '{', close: '}' });
- fn({ name: 'tobi' }).should.equal('<p>tobi</p>');
- var fn = ejs.compile('<p>::= name ::</p>', { open: '::', close: '::' });
- fn({ name: 'tobi' }).should.equal('<p>tobi</p>');
- var fn = ejs.compile('<p>(= name )</p>', { open: '(', close: ')' });
- fn({ name: 'tobi' }).should.equal('<p>tobi</p>');
- })
- it('should default to using ejs.open and ejs.close', function(){
- ejs.open = '{';
- ejs.close = '}';
- var fn = ejs.compile('<p>{= name }</p>');
- fn({ name: 'tobi' }).should.equal('<p>tobi</p>');
- var fn = ejs.compile('<p>|= name |</p>', { open: '|', close: '|' });
- fn({ name: 'tobi' }).should.equal('<p>tobi</p>');
- delete ejs.open;
- delete ejs.close;
- })
- it('should have a working client option', function(){
- var fn = ejs.compile('<p><%= foo %></p>', { client: true });
- var str = fn.toString();
- eval('var preFn = ' + str);
- preFn({ foo: 'bar' }).should.equal('<p>bar</p>');
- })
- })
- describe('ejs.render(str, options)', function(){
- it('should render the template', function(){
- ejs.render('<p>yay</p>')
- .should.equal('<p>yay</p>');
- })
- it('should accept locals', function(){
- ejs.render('<p><%= name %></p>', { name: 'tobi' })
- .should.equal('<p>tobi</p>');
- })
- })
- describe('ejs.renderFile(path, options, fn)', function(){
- it('should render a file', function(done){
- ejs.renderFile('test/fixtures/para.ejs', function(err, html){
- if (err) return done(err);
- html.should.equal('<p>hey</p>');
- done();
- });
- })
- it('should accept locals', function(done){
- var options = { name: 'tj', open: '{', close: '}' };
- ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){
- if (err) return done(err);
- html.should.equal('<h1>tj</h1>');
- done();
- });
- })
- it('should not catch err threw by callback', function(done){
- var options = { name: 'tj', open: '{', close: '}' };
- var counter = 0;
- try {
- ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){
- counter++;
- if (err) {
- err.message.should.not.equal('Exception in callback');
- return done(err);
- }
- throw new Error('Exception in callback');
- });
- } catch (err) {
- counter.should.equal(1);
- err.message.should.equal('Exception in callback');
- done();
- }
- })
- })
- describe('<%=', function(){
- it('should escape &<script>', function(){
- ejs.render('<%= name %>', { name: ' <script>' })
- .should.equal('&nbsp;<script>');
- })
- it("should escape '", function(){
- ejs.render('<%= name %>', { name: "The Jones's" })
- .should.equal('The Jones's');
- })
-
- it("should escape &foo_bar;", function(){
- ejs.render('<%= name %>', { name: "&foo_bar;" })
- .should.equal('&foo_bar;');
- })
- })
- describe('<%-', function(){
- it('should not escape', function(){
- ejs.render('<%- name %>', { name: '<script>' })
- .should.equal('<script>');
- })
- it('should terminate gracefully if no close tag is found', function(){
- try {
- ejs.compile('<h1>oops</h1><%- name ->')
- throw new Error('Expected parse failure');
- } catch (err) {
- err.message.should.equal('Could not find matching close tag "%>".');
- }
- })
- })
- describe('%>', function(){
- it('should produce newlines', function(){
- ejs.render(fixture('newlines.ejs'), { users: users })
- .should.equal(fixture('newlines.html'));
- })
- })
- describe('-%>', function(){
- it('should not produce newlines', function(){
- ejs.render(fixture('no.newlines.ejs'), { users: users })
- .should.equal(fixture('no.newlines.html'));
- })
- })
- describe('single quotes', function(){
- it('should not mess up the constructed function', function(){
- ejs.render(fixture('single-quote.ejs'))
- .should.equal(fixture('single-quote.html'));
- })
- })
- describe('double quotes', function(){
- it('should not mess up the constructed function', function(){
- ejs.render(fixture('double-quote.ejs'))
- .should.equal(fixture('double-quote.html'));
- })
- })
- describe('backslashes', function(){
- it('should escape', function(){
- ejs.render(fixture('backslash.ejs'))
- .should.equal(fixture('backslash.html'));
- })
- })
- describe('messed up whitespace', function(){
- it('should work', function(){
- ejs.render(fixture('messed.ejs'), { users: users })
- .should.equal(fixture('messed.html'));
- })
- })
- describe('filters', function(){
- it('should work', function(){
- var items = ['foo', 'bar', 'baz'];
- ejs.render('<%=: items | reverse | first | reverse | capitalize %>', { items: items })
- .should.equal('Zab');
- })
- it('should accept arguments', function(){
- ejs.render('<%=: users | map:"name" | join:", " %>', { users: users })
- .should.equal('tobi, loki, jane');
- })
- it('should truncate string', function(){
- ejs.render('<%=: word | truncate: 3 %>', { word: 'World' })
- .should.equal('Wor');
- })
- it('should append string if string is longer', function(){
- ejs.render('<%=: word | truncate: 2,"..." %>', { word: 'Testing' })
- .should.equal('Te...');
- })
- it('should not append string if string is shorter', function(){
- ejs.render('<%=: word | truncate: 10,"..." %>', { word: 'Testing' })
- .should.equal('Testing');
- })
- it('should accept arguments containing :', function(){
- ejs.render('<%=: users | map:"name" | join:"::" %>', { users: users })
- .should.equal('tobi::loki::jane');
- })
- })
- describe('exceptions', function(){
- it('should produce useful stack traces', function(done){
- try {
- ejs.render(fixture('error.ejs'), { filename: 'error.ejs' });
- } catch (err) {
- err.path.should.equal('error.ejs');
- err.stack.split('\n').slice(0, 8).join('\n').should.equal(fixture('error.out'));
- done();
- }
- })
- it('should not include __stack if compileDebug is false', function() {
- try {
- ejs.render(fixture('error.ejs'), {
- filename: 'error.ejs',
- compileDebug: false
- });
- } catch (err) {
- err.should.not.have.property('path');
- err.stack.split('\n').slice(0, 8).join('\n').should.not.equal(fixture('error.out'));
- }
- });
- })
- describe('includes', function(){
- it('should include ejs', function(){
- var file = 'test/fixtures/include.ejs';
- ejs.render(fixture('include.ejs'), { filename: file, pets: users, open: '[[', close: ']]' })
- .should.equal(fixture('include.html'));
- })
- it('should work when nested', function(){
- var file = 'test/fixtures/menu.ejs';
- ejs.render(fixture('menu.ejs'), { filename: file, pets: users })
- .should.equal(fixture('menu.html'));
- })
- it('should include arbitrary files as-is', function(){
- var file = 'test/fixtures/include.css.ejs';
- ejs.render(fixture('include.css.ejs'), { filename: file, pets: users })
- .should.equal(fixture('include.css.html'));
- })
- it('should pass compileDebug to include', function(){
- var file = 'test/fixtures/include.ejs';
- var fn = ejs.compile(fixture('include.ejs'), { filename: file, open: '[[', close: ']]', compileDebug: false, client: true })
- var str = fn.toString();
- eval('var preFn = ' + str);
- str.should.not.match(/__stack/);
- (function() {
- preFn({ pets: users });
- }).should.not.throw();
- })
- })
- describe('comments', function() {
- it('should fully render with comments removed', function() {
- ejs.render(fixture('comments.ejs'))
- .should.equal(fixture('comments.html'));
- })
- })
- describe('require', function() {
- it('should allow ejs templates to be required as node modules', function() {
- var file = 'test/fixtures/include.ejs'
- , template = require(__dirname + '/fixtures/menu.ejs');
- template({ filename: file, pets: users })
- .should.equal(fixture('menu.html'));
- })
- })
|