refactor: improve readability (#6173)
[express.git] / test / app.use.js
bloba88a2f2c8e9e611b4765e9958b9d3c5aee460afa
1 'use strict'
3 var after = require('after');
4 var assert = require('assert')
5 var express = require('..');
6 var request = require('supertest');
8 describe('app', function(){
9   it('should emit "mount" when mounted', function(done){
10     var blog = express()
11       , app = express();
13     blog.on('mount', function(arg){
14       assert.strictEqual(arg, app)
15       done();
16     });
18     app.use(blog);
19   })
21   describe('.use(app)', function(){
22     it('should mount the app', function(done){
23       var blog = express()
24         , app = express();
26       blog.get('/blog', function(req, res){
27         res.end('blog');
28       });
30       app.use(blog);
32       request(app)
33       .get('/blog')
34       .expect('blog', done);
35     })
37     it('should support mount-points', function(done){
38       var blog = express()
39         , forum = express()
40         , app = express();
41       var cb = after(2, done)
43       blog.get('/', function(req, res){
44         res.end('blog');
45       });
47       forum.get('/', function(req, res){
48         res.end('forum');
49       });
51       app.use('/blog', blog);
52       app.use('/forum', forum);
54       request(app)
55         .get('/blog')
56         .expect(200, 'blog', cb)
58       request(app)
59         .get('/forum')
60         .expect(200, 'forum', cb)
61     })
63     it('should set the child\'s .parent', function(){
64       var blog = express()
65         , app = express();
67       app.use('/blog', blog);
68       assert.strictEqual(blog.parent, app)
69     })
71     it('should support dynamic routes', function(done){
72       var blog = express()
73         , app = express();
75       blog.get('/', function(req, res){
76         res.end('success');
77       });
79       app.use('/post/:article', blog);
81       request(app)
82       .get('/post/once-upon-a-time')
83       .expect('success', done);
84     })
86     it('should support mounted app anywhere', function(done){
87       var cb = after(3, done);
88       var blog = express()
89         , other = express()
90         , app = express();
92       function fn1(req, res, next) {
93         res.setHeader('x-fn-1', 'hit');
94         next();
95       }
97       function fn2(req, res, next) {
98         res.setHeader('x-fn-2', 'hit');
99         next();
100       }
102       blog.get('/', function(req, res){
103         res.end('success');
104       });
106       blog.once('mount', function (parent) {
107         assert.strictEqual(parent, app)
108         cb();
109       });
110       other.once('mount', function (parent) {
111         assert.strictEqual(parent, app)
112         cb();
113       });
115       app.use('/post/:article', fn1, other, fn2, blog);
117       request(app)
118       .get('/post/once-upon-a-time')
119       .expect('x-fn-1', 'hit')
120       .expect('x-fn-2', 'hit')
121       .expect('success', cb);
122     })
123   })
125   describe('.use(middleware)', function(){
126     it('should accept multiple arguments', function (done) {
127       var app = express();
129       function fn1(req, res, next) {
130         res.setHeader('x-fn-1', 'hit');
131         next();
132       }
134       function fn2(req, res, next) {
135         res.setHeader('x-fn-2', 'hit');
136         next();
137       }
139       app.use(fn1, fn2, function fn3(req, res) {
140         res.setHeader('x-fn-3', 'hit');
141         res.end();
142       });
144       request(app)
145       .get('/')
146       .expect('x-fn-1', 'hit')
147       .expect('x-fn-2', 'hit')
148       .expect('x-fn-3', 'hit')
149       .expect(200, done);
150     })
152     it('should invoke middleware for all requests', function (done) {
153       var app = express();
154       var cb = after(3, done);
156       app.use(function (req, res) {
157         res.send('saw ' + req.method + ' ' + req.url);
158       });
160       request(app)
161       .get('/')
162       .expect(200, 'saw GET /', cb);
164       request(app)
165       .options('/')
166       .expect(200, 'saw OPTIONS /', cb);
168       request(app)
169       .post('/foo')
170       .expect(200, 'saw POST /foo', cb);
171     })
173     it('should accept array of middleware', function (done) {
174       var app = express();
176       function fn1(req, res, next) {
177         res.setHeader('x-fn-1', 'hit');
178         next();
179       }
181       function fn2(req, res, next) {
182         res.setHeader('x-fn-2', 'hit');
183         next();
184       }
186       function fn3(req, res, next) {
187         res.setHeader('x-fn-3', 'hit');
188         res.end();
189       }
191       app.use([fn1, fn2, fn3]);
193       request(app)
194       .get('/')
195       .expect('x-fn-1', 'hit')
196       .expect('x-fn-2', 'hit')
197       .expect('x-fn-3', 'hit')
198       .expect(200, done);
199     })
201     it('should accept multiple arrays of middleware', function (done) {
202       var app = express();
204       function fn1(req, res, next) {
205         res.setHeader('x-fn-1', 'hit');
206         next();
207       }
209       function fn2(req, res, next) {
210         res.setHeader('x-fn-2', 'hit');
211         next();
212       }
214       function fn3(req, res, next) {
215         res.setHeader('x-fn-3', 'hit');
216         res.end();
217       }
219       app.use([fn1, fn2], [fn3]);
221       request(app)
222       .get('/')
223       .expect('x-fn-1', 'hit')
224       .expect('x-fn-2', 'hit')
225       .expect('x-fn-3', 'hit')
226       .expect(200, done);
227     })
229     it('should accept nested arrays of middleware', function (done) {
230       var app = express();
232       function fn1(req, res, next) {
233         res.setHeader('x-fn-1', 'hit');
234         next();
235       }
237       function fn2(req, res, next) {
238         res.setHeader('x-fn-2', 'hit');
239         next();
240       }
242       function fn3(req, res, next) {
243         res.setHeader('x-fn-3', 'hit');
244         res.end();
245       }
247       app.use([[fn1], fn2], [fn3]);
249       request(app)
250       .get('/')
251       .expect('x-fn-1', 'hit')
252       .expect('x-fn-2', 'hit')
253       .expect('x-fn-3', 'hit')
254       .expect(200, done);
255     })
256   })
258   describe('.use(path, middleware)', function(){
259     it('should require middleware', function () {
260       var app = express()
261       assert.throws(function () { app.use('/') }, 'TypeError: app.use() requires a middleware function')
262     })
264     it('should reject string as middleware', function () {
265       var app = express()
266       assert.throws(function () { app.use('/', 'foo') }, /argument handler must be a function/)
267     })
269     it('should reject number as middleware', function () {
270       var app = express()
271       assert.throws(function () { app.use('/', 42) }, /argument handler must be a function/)
272     })
274     it('should reject null as middleware', function () {
275       var app = express()
276       assert.throws(function () { app.use('/', null) }, /argument handler must be a function/)
277     })
279     it('should reject Date as middleware', function () {
280       var app = express()
281       assert.throws(function () { app.use('/', new Date()) }, /argument handler must be a function/)
282     })
284     it('should strip path from req.url', function (done) {
285       var app = express();
287       app.use('/foo', function (req, res) {
288         res.send('saw ' + req.method + ' ' + req.url);
289       });
291       request(app)
292       .get('/foo/bar')
293       .expect(200, 'saw GET /bar', done);
294     })
296     it('should accept multiple arguments', function (done) {
297       var app = express();
299       function fn1(req, res, next) {
300         res.setHeader('x-fn-1', 'hit');
301         next();
302       }
304       function fn2(req, res, next) {
305         res.setHeader('x-fn-2', 'hit');
306         next();
307       }
309       app.use('/foo', fn1, fn2, function fn3(req, res) {
310         res.setHeader('x-fn-3', 'hit');
311         res.end();
312       });
314       request(app)
315       .get('/foo')
316       .expect('x-fn-1', 'hit')
317       .expect('x-fn-2', 'hit')
318       .expect('x-fn-3', 'hit')
319       .expect(200, done);
320     })
322     it('should invoke middleware for all requests starting with path', function (done) {
323       var app = express();
324       var cb = after(3, done);
326       app.use('/foo', function (req, res) {
327         res.send('saw ' + req.method + ' ' + req.url);
328       });
330       request(app)
331       .get('/')
332       .expect(404, cb);
334       request(app)
335       .post('/foo')
336       .expect(200, 'saw POST /', cb);
338       request(app)
339       .post('/foo/bar')
340       .expect(200, 'saw POST /bar', cb);
341     })
343     it('should work if path has trailing slash', function (done) {
344       var app = express();
345       var cb = after(3, done);
347       app.use('/foo/', function (req, res) {
348         res.send('saw ' + req.method + ' ' + req.url);
349       });
351       request(app)
352       .get('/')
353       .expect(404, cb);
355       request(app)
356       .post('/foo')
357       .expect(200, 'saw POST /', cb);
359       request(app)
360       .post('/foo/bar')
361       .expect(200, 'saw POST /bar', cb);
362     })
364     it('should accept array of middleware', function (done) {
365       var app = express();
367       function fn1(req, res, next) {
368         res.setHeader('x-fn-1', 'hit');
369         next();
370       }
372       function fn2(req, res, next) {
373         res.setHeader('x-fn-2', 'hit');
374         next();
375       }
377       function fn3(req, res, next) {
378         res.setHeader('x-fn-3', 'hit');
379         res.end();
380       }
382       app.use('/foo', [fn1, fn2, fn3]);
384       request(app)
385       .get('/foo')
386       .expect('x-fn-1', 'hit')
387       .expect('x-fn-2', 'hit')
388       .expect('x-fn-3', 'hit')
389       .expect(200, done);
390     })
392     it('should accept multiple arrays of middleware', function (done) {
393       var app = express();
395       function fn1(req, res, next) {
396         res.setHeader('x-fn-1', 'hit');
397         next();
398       }
400       function fn2(req, res, next) {
401         res.setHeader('x-fn-2', 'hit');
402         next();
403       }
405       function fn3(req, res, next) {
406         res.setHeader('x-fn-3', 'hit');
407         res.end();
408       }
410       app.use('/foo', [fn1, fn2], [fn3]);
412       request(app)
413       .get('/foo')
414       .expect('x-fn-1', 'hit')
415       .expect('x-fn-2', 'hit')
416       .expect('x-fn-3', 'hit')
417       .expect(200, done);
418     })
420     it('should accept nested arrays of middleware', function (done) {
421       var app = express();
423       function fn1(req, res, next) {
424         res.setHeader('x-fn-1', 'hit');
425         next();
426       }
428       function fn2(req, res, next) {
429         res.setHeader('x-fn-2', 'hit');
430         next();
431       }
433       function fn3(req, res, next) {
434         res.setHeader('x-fn-3', 'hit');
435         res.end();
436       }
438       app.use('/foo', [fn1, [fn2]], [fn3]);
440       request(app)
441       .get('/foo')
442       .expect('x-fn-1', 'hit')
443       .expect('x-fn-2', 'hit')
444       .expect('x-fn-3', 'hit')
445       .expect(200, done);
446     })
448     it('should support array of paths', function (done) {
449       var app = express();
450       var cb = after(3, done);
452       app.use(['/foo/', '/bar'], function (req, res) {
453         res.send('saw ' + req.method + ' ' + req.url + ' through ' + req.originalUrl);
454       });
456       request(app)
457       .get('/')
458       .expect(404, cb);
460       request(app)
461       .get('/foo')
462       .expect(200, 'saw GET / through /foo', cb);
464       request(app)
465       .get('/bar')
466       .expect(200, 'saw GET / through /bar', cb);
467     })
469     it('should support array of paths with middleware array', function (done) {
470       var app = express();
471       var cb = after(2, done);
473       function fn1(req, res, next) {
474         res.setHeader('x-fn-1', 'hit');
475         next();
476       }
478       function fn2(req, res, next) {
479         res.setHeader('x-fn-2', 'hit');
480         next();
481       }
483       function fn3(req, res, next) {
484         res.setHeader('x-fn-3', 'hit');
485         res.send('saw ' + req.method + ' ' + req.url + ' through ' + req.originalUrl);
486       }
488       app.use(['/foo/', '/bar'], [[fn1], fn2], [fn3]);
490       request(app)
491       .get('/foo')
492       .expect('x-fn-1', 'hit')
493       .expect('x-fn-2', 'hit')
494       .expect('x-fn-3', 'hit')
495       .expect(200, 'saw GET / through /foo', cb);
497       request(app)
498       .get('/bar')
499       .expect('x-fn-1', 'hit')
500       .expect('x-fn-2', 'hit')
501       .expect('x-fn-3', 'hit')
502       .expect(200, 'saw GET / through /bar', cb);
503     })
505     it('should support regexp path', function (done) {
506       var app = express();
507       var cb = after(4, done);
509       app.use(/^\/[a-z]oo/, function (req, res) {
510         res.send('saw ' + req.method + ' ' + req.url + ' through ' + req.originalUrl);
511       });
513       request(app)
514       .get('/')
515       .expect(404, cb);
517       request(app)
518       .get('/foo')
519       .expect(200, 'saw GET / through /foo', cb);
521       request(app)
522       .get('/zoo/bear')
523       .expect(200, 'saw GET /bear through /zoo/bear', cb);
525       request(app)
526       .get('/get/zoo')
527       .expect(404, cb);
528     })
530     it('should support empty string path', function (done) {
531       var app = express();
533       app.use('', function (req, res) {
534         res.send('saw ' + req.method + ' ' + req.url + ' through ' + req.originalUrl);
535       });
537       request(app)
538       .get('/')
539       .expect(200, 'saw GET / through /', done);
540     })
541   })