deps: body-parser@1.20.0
[express.git] / test / app.render.js
blob9d202acfddac559f5381855701244f6356efd7d7
1 'use strict'
3 var assert = require('assert')
4 var express = require('..');
5 var path = require('path')
6 var tmpl = require('./support/tmpl');
8 describe('app', function(){
9   describe('.render(name, fn)', function(){
10     it('should support absolute paths', function(done){
11       var app = createApp();
13       app.locals.user = { name: 'tobi' };
15       app.render(path.join(__dirname, 'fixtures', 'user.tmpl'), function (err, str) {
16         if (err) return done(err);
17         assert.strictEqual(str, '<p>tobi</p>')
18         done();
19       })
20     })
22     it('should support absolute paths with "view engine"', function(done){
23       var app = createApp();
25       app.set('view engine', 'tmpl');
26       app.locals.user = { name: 'tobi' };
28       app.render(path.join(__dirname, 'fixtures', 'user'), function (err, str) {
29         if (err) return done(err);
30         assert.strictEqual(str, '<p>tobi</p>')
31         done();
32       })
33     })
35     it('should expose app.locals', function(done){
36       var app = createApp();
38       app.set('views', path.join(__dirname, 'fixtures'))
39       app.locals.user = { name: 'tobi' };
41       app.render('user.tmpl', function (err, str) {
42         if (err) return done(err);
43         assert.strictEqual(str, '<p>tobi</p>')
44         done();
45       })
46     })
48     it('should support index.<engine>', function(done){
49       var app = createApp();
51       app.set('views', path.join(__dirname, 'fixtures'))
52       app.set('view engine', 'tmpl');
54       app.render('blog/post', function (err, str) {
55         if (err) return done(err);
56         assert.strictEqual(str, '<h1>blog post</h1>')
57         done();
58       })
59     })
61     it('should handle render error throws', function(done){
62       var app = express();
64       function View(name, options){
65         this.name = name;
66         this.path = 'fale';
67       }
69       View.prototype.render = function(options, fn){
70         throw new Error('err!');
71       };
73       app.set('view', View);
75       app.render('something', function(err, str){
76         assert.ok(err)
77         assert.strictEqual(err.message, 'err!')
78         done();
79       })
80     })
82     describe('when the file does not exist', function(){
83       it('should provide a helpful error', function(done){
84         var app = createApp();
86         app.set('views', path.join(__dirname, 'fixtures'))
87         app.render('rawr.tmpl', function (err) {
88           assert.ok(err)
89           assert.equal(err.message, 'Failed to lookup view "rawr.tmpl" in views directory "' + path.join(__dirname, 'fixtures') + '"')
90           done();
91         });
92       })
93     })
95     describe('when an error occurs', function(){
96       it('should invoke the callback', function(done){
97         var app = createApp();
99         app.set('views', path.join(__dirname, 'fixtures'))
101         app.render('user.tmpl', function (err) {
102           assert.ok(err)
103           assert.equal(err.name, 'RenderError')
104           done()
105         })
106       })
107     })
109     describe('when an extension is given', function(){
110       it('should render the template', function(done){
111         var app = createApp();
113         app.set('views', path.join(__dirname, 'fixtures'))
115         app.render('email.tmpl', function (err, str) {
116           if (err) return done(err);
117           assert.strictEqual(str, '<p>This is an email</p>')
118           done();
119         })
120       })
121     })
123     describe('when "view engine" is given', function(){
124       it('should render the template', function(done){
125         var app = createApp();
127         app.set('view engine', 'tmpl');
128         app.set('views', path.join(__dirname, 'fixtures'))
130         app.render('email', function(err, str){
131           if (err) return done(err);
132           assert.strictEqual(str, '<p>This is an email</p>')
133           done();
134         })
135       })
136     })
138     describe('when "views" is given', function(){
139       it('should lookup the file in the path', function(done){
140         var app = createApp();
142         app.set('views',  path.join(__dirname, 'fixtures', 'default_layout'))
143         app.locals.user = { name: 'tobi' };
145         app.render('user.tmpl', function (err, str) {
146           if (err) return done(err);
147           assert.strictEqual(str, '<p>tobi</p>')
148           done();
149         })
150       })
152       describe('when array of paths', function(){
153         it('should lookup the file in the path', function(done){
154           var app = createApp();
155           var views = [
156             path.join(__dirname, 'fixtures', 'local_layout'),
157             path.join(__dirname, 'fixtures', 'default_layout')
158           ]
160           app.set('views', views);
161           app.locals.user = { name: 'tobi' };
163           app.render('user.tmpl', function (err, str) {
164             if (err) return done(err);
165             assert.strictEqual(str, '<span>tobi</span>')
166             done();
167           })
168         })
170         it('should lookup in later paths until found', function(done){
171           var app = createApp();
172           var views = [
173             path.join(__dirname, 'fixtures', 'local_layout'),
174             path.join(__dirname, 'fixtures', 'default_layout')
175           ]
177           app.set('views', views);
178           app.locals.name = 'tobi';
180           app.render('name.tmpl', function (err, str) {
181             if (err) return done(err);
182             assert.strictEqual(str, '<p>tobi</p>')
183             done();
184           })
185         })
187         it('should error if file does not exist', function(done){
188           var app = createApp();
189           var views = [
190             path.join(__dirname, 'fixtures', 'local_layout'),
191             path.join(__dirname, 'fixtures', 'default_layout')
192           ]
194           app.set('views', views);
195           app.locals.name = 'tobi';
197           app.render('pet.tmpl', function (err, str) {
198             assert.ok(err)
199             assert.equal(err.message, 'Failed to lookup view "pet.tmpl" in views directories "' + views[0] + '" or "' + views[1] + '"')
200             done();
201           })
202         })
203       })
204     })
206     describe('when a "view" constructor is given', function(){
207       it('should create an instance of it', function(done){
208         var app = express();
210         function View(name, options){
211           this.name = name;
212           this.path = 'path is required by application.js as a signal of success even though it is not used there.';
213         }
215         View.prototype.render = function(options, fn){
216           fn(null, 'abstract engine');
217         };
219         app.set('view', View);
221         app.render('something', function(err, str){
222           if (err) return done(err);
223           assert.strictEqual(str, 'abstract engine')
224           done();
225         })
226       })
227     })
229     describe('caching', function(){
230       it('should always lookup view without cache', function(done){
231         var app = express();
232         var count = 0;
234         function View(name, options){
235           this.name = name;
236           this.path = 'fake';
237           count++;
238         }
240         View.prototype.render = function(options, fn){
241           fn(null, 'abstract engine');
242         };
244         app.set('view cache', false);
245         app.set('view', View);
247         app.render('something', function(err, str){
248           if (err) return done(err);
249           assert.strictEqual(count, 1)
250           assert.strictEqual(str, 'abstract engine')
251           app.render('something', function(err, str){
252             if (err) return done(err);
253             assert.strictEqual(count, 2)
254             assert.strictEqual(str, 'abstract engine')
255             done();
256           })
257         })
258       })
260       it('should cache with "view cache" setting', function(done){
261         var app = express();
262         var count = 0;
264         function View(name, options){
265           this.name = name;
266           this.path = 'fake';
267           count++;
268         }
270         View.prototype.render = function(options, fn){
271           fn(null, 'abstract engine');
272         };
274         app.set('view cache', true);
275         app.set('view', View);
277         app.render('something', function(err, str){
278           if (err) return done(err);
279           assert.strictEqual(count, 1)
280           assert.strictEqual(str, 'abstract engine')
281           app.render('something', function(err, str){
282             if (err) return done(err);
283             assert.strictEqual(count, 1)
284             assert.strictEqual(str, 'abstract engine')
285             done();
286           })
287         })
288       })
289     })
290   })
292   describe('.render(name, options, fn)', function(){
293     it('should render the template', function(done){
294       var app = createApp();
296       app.set('views', path.join(__dirname, 'fixtures'))
298       var user = { name: 'tobi' };
300       app.render('user.tmpl', { user: user }, function (err, str) {
301         if (err) return done(err);
302         assert.strictEqual(str, '<p>tobi</p>')
303         done();
304       })
305     })
307     it('should expose app.locals', function(done){
308       var app = createApp();
310       app.set('views', path.join(__dirname, 'fixtures'))
311       app.locals.user = { name: 'tobi' };
313       app.render('user.tmpl', {}, function (err, str) {
314         if (err) return done(err);
315         assert.strictEqual(str, '<p>tobi</p>')
316         done();
317       })
318     })
320     it('should give precedence to app.render() locals', function(done){
321       var app = createApp();
323       app.set('views', path.join(__dirname, 'fixtures'))
324       app.locals.user = { name: 'tobi' };
325       var jane = { name: 'jane' };
327       app.render('user.tmpl', { user: jane }, function (err, str) {
328         if (err) return done(err);
329         assert.strictEqual(str, '<p>jane</p>')
330         done();
331       })
332     })
334     describe('caching', function(){
335       it('should cache with cache option', function(done){
336         var app = express();
337         var count = 0;
339         function View(name, options){
340           this.name = name;
341           this.path = 'fake';
342           count++;
343         }
345         View.prototype.render = function(options, fn){
346           fn(null, 'abstract engine');
347         };
349         app.set('view cache', false);
350         app.set('view', View);
352         app.render('something', {cache: true}, function(err, str){
353           if (err) return done(err);
354           assert.strictEqual(count, 1)
355           assert.strictEqual(str, 'abstract engine')
356           app.render('something', {cache: true}, function(err, str){
357             if (err) return done(err);
358             assert.strictEqual(count, 1)
359             assert.strictEqual(str, 'abstract engine')
360             done();
361           })
362         })
363       })
364     })
365   })
368 function createApp() {
369   var app = express();
371   app.engine('.tmpl', tmpl);
373   return app;