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>')
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>')
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>')
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>')
61 it('should handle render error throws', function(done){
64 function View(name, options){
69 View.prototype.render = function(options, fn){
70 throw new Error('err!');
73 app.set('view', View);
75 app.render('something', function(err, str){
77 assert.strictEqual(err.message, 'err!')
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) {
89 assert.equal(err.message, 'Failed to lookup view "rawr.tmpl" in views directory "' + path.join(__dirname, 'fixtures') + '"')
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) {
103 assert.equal(err.name, 'RenderError')
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>')
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>')
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>')
152 describe('when array of paths', function(){
153 it('should lookup the file in the path', function(done){
154 var app = createApp();
156 path.join(__dirname, 'fixtures', 'local_layout'),
157 path.join(__dirname, 'fixtures', 'default_layout')
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>')
170 it('should lookup in later paths until found', function(done){
171 var app = createApp();
173 path.join(__dirname, 'fixtures', 'local_layout'),
174 path.join(__dirname, 'fixtures', 'default_layout')
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>')
187 it('should error if file does not exist', function(done){
188 var app = createApp();
190 path.join(__dirname, 'fixtures', 'local_layout'),
191 path.join(__dirname, 'fixtures', 'default_layout')
194 app.set('views', views);
195 app.locals.name = 'tobi';
197 app.render('pet.tmpl', function (err, str) {
199 assert.equal(err.message, 'Failed to lookup view "pet.tmpl" in views directories "' + views[0] + '" or "' + views[1] + '"')
206 describe('when a "view" constructor is given', function(){
207 it('should create an instance of it', function(done){
210 function View(name, options){
212 this.path = 'path is required by application.js as a signal of success even though it is not used there.';
215 View.prototype.render = function(options, fn){
216 fn(null, 'abstract engine');
219 app.set('view', View);
221 app.render('something', function(err, str){
222 if (err) return done(err);
223 assert.strictEqual(str, 'abstract engine')
229 describe('caching', function(){
230 it('should always lookup view without cache', function(done){
234 function View(name, options){
240 View.prototype.render = function(options, fn){
241 fn(null, 'abstract engine');
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')
260 it('should cache with "view cache" setting', function(done){
264 function View(name, options){
270 View.prototype.render = function(options, fn){
271 fn(null, 'abstract engine');
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')
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>')
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>')
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>')
334 describe('caching', function(){
335 it('should cache with cache option', function(done){
339 function View(name, options){
345 View.prototype.render = function(options, fn){
346 fn(null, 'abstract engine');
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')
368 function createApp() {
371 app.engine('.tmpl', tmpl);