0796c1d2d2
so tests pass in 0.11. 0.11 client seems to throw errors more often, so this is not an issue with express or node’s servers.
597 linhas
13 KiB
JavaScript
597 linhas
13 KiB
JavaScript
|
|
var express = require('../')
|
|
, request = require('./support/http')
|
|
, assert = require('assert')
|
|
, methods = require('methods');
|
|
|
|
describe('app.router', function(){
|
|
describe('methods supported', function(){
|
|
methods.forEach(function(method){
|
|
if (method === 'connect') return;
|
|
|
|
it('should include ' + method.toUpperCase(), function(done){
|
|
if (method == 'delete') method = 'del';
|
|
var app = express();
|
|
var calls = [];
|
|
|
|
app[method]('/foo', function(req, res){
|
|
if ('head' == method) {
|
|
res.end();
|
|
} else {
|
|
res.end(method);
|
|
}
|
|
});
|
|
|
|
request(app)
|
|
[method]('/foo')
|
|
.expect('head' == method ? '' : method, done);
|
|
})
|
|
});
|
|
})
|
|
|
|
describe('decode querystring', function(){
|
|
it('should decode correct params', function(done){
|
|
var app = express();
|
|
|
|
app.get('/:name', function(req, res, next){
|
|
res.send(req.params.name);
|
|
});
|
|
|
|
request(app)
|
|
.get('/foo%2Fbar')
|
|
.expect('foo/bar', done);
|
|
})
|
|
|
|
it('should not accept params in malformed paths', function(done) {
|
|
var app = express();
|
|
|
|
app.get('/:name', function(req, res, next){
|
|
res.send(req.params.name);
|
|
});
|
|
|
|
request(app)
|
|
.get('/%foobar')
|
|
.expect(400, done);
|
|
})
|
|
|
|
it('should not decode spaces', function(done) {
|
|
var app = express();
|
|
|
|
app.get('/:name', function(req, res, next){
|
|
res.send(req.params.name);
|
|
});
|
|
|
|
request(app)
|
|
.get('/foo+bar')
|
|
.expect('foo+bar', done);
|
|
})
|
|
|
|
it('should work with unicode', function(done) {
|
|
var app = express();
|
|
|
|
app.get('/:name', function(req, res, next){
|
|
res.send(req.params.name);
|
|
});
|
|
|
|
request(app)
|
|
.get('/%ce%b1')
|
|
.expect('\u03b1', done);
|
|
})
|
|
})
|
|
|
|
it('should be .use()able', function(done){
|
|
var app = express();
|
|
|
|
var calls = [];
|
|
|
|
app.use(function(req, res, next){
|
|
calls.push('before');
|
|
next();
|
|
});
|
|
|
|
app.get('/', function(req, res, next){
|
|
calls.push('GET /')
|
|
next();
|
|
});
|
|
|
|
app.use(function(req, res, next){
|
|
calls.push('after');
|
|
res.end();
|
|
});
|
|
|
|
request(app)
|
|
.get('/')
|
|
.end(function(res){
|
|
calls.should.eql(['before', 'GET /', 'after'])
|
|
done();
|
|
})
|
|
})
|
|
|
|
describe('when given a regexp', function(){
|
|
it('should match the pathname only', function(done){
|
|
var app = express();
|
|
|
|
app.get(/^\/user\/[0-9]+$/, function(req, res){
|
|
res.end('user');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/12?foo=bar')
|
|
.expect('user', done);
|
|
})
|
|
|
|
it('should populate req.params with the captures', function(done){
|
|
var app = express();
|
|
|
|
app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function(req, res){
|
|
var id = req.params[0]
|
|
, op = req.params[1];
|
|
res.end(op + 'ing user ' + id);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/10/edit')
|
|
.expect('editing user 10', done);
|
|
})
|
|
})
|
|
|
|
describe('case sensitivity', function(){
|
|
it('should be disabled by default', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/USER')
|
|
.expect('tj', done);
|
|
})
|
|
|
|
describe('when "case sensitive routing" is enabled', function(){
|
|
it('should match identical casing', function(done){
|
|
var app = express();
|
|
|
|
app.enable('case sensitive routing');
|
|
|
|
app.get('/uSer', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/uSer')
|
|
.expect('tj', done);
|
|
})
|
|
|
|
it('should not match otherwise', function(done){
|
|
var app = express();
|
|
|
|
app.enable('case sensitive routing');
|
|
|
|
app.get('/uSer', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user')
|
|
.expect(404, done);
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('trailing slashes', function(){
|
|
it('should be optional by default', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/')
|
|
.expect('tj', done);
|
|
})
|
|
|
|
describe('when "strict routing" is enabled', function(){
|
|
it('should match trailing slashes', function(done){
|
|
var app = express();
|
|
|
|
app.enable('strict routing');
|
|
|
|
app.get('/user/', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/')
|
|
.expect('tj', done);
|
|
})
|
|
|
|
it('should match no slashes', function(done){
|
|
var app = express();
|
|
|
|
app.enable('strict routing');
|
|
|
|
app.get('/user', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user')
|
|
.expect('tj', done);
|
|
})
|
|
|
|
it('should fail when omitting the trailing slash', function(done){
|
|
var app = express();
|
|
|
|
app.enable('strict routing');
|
|
|
|
app.get('/user/', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user')
|
|
.expect(404, done);
|
|
})
|
|
|
|
it('should fail when adding the trailing slash', function(done){
|
|
var app = express();
|
|
|
|
app.enable('strict routing');
|
|
|
|
app.get('/user', function(req, res){
|
|
res.end('tj');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/')
|
|
.expect(404, done);
|
|
})
|
|
})
|
|
})
|
|
|
|
it('should allow escaped regexp', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/\\d+', function(req, res){
|
|
res.end('woot');
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/10')
|
|
.end(function(err, res){
|
|
res.statusCode.should.equal(200);
|
|
request(app)
|
|
.get('/user/tj')
|
|
.expect(404, done);
|
|
});
|
|
})
|
|
|
|
it('should allow literal "."', function(done){
|
|
var app = express();
|
|
|
|
app.get('/api/users/:from..:to', function(req, res){
|
|
var from = req.params.from
|
|
, to = req.params.to;
|
|
|
|
res.end('users from ' + from + ' to ' + to);
|
|
});
|
|
|
|
request(app)
|
|
.get('/api/users/1..50')
|
|
.expect('users from 1 to 50', done);
|
|
})
|
|
|
|
describe('*', function(){
|
|
it('should denote a greedy capture group', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/*.json', function(req, res){
|
|
res.end(req.params[0]);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/tj.json')
|
|
.expect('tj', done);
|
|
})
|
|
|
|
it('should work with several', function(done){
|
|
var app = express();
|
|
|
|
app.get('/api/*.*', function(req, res){
|
|
var resource = req.params[0]
|
|
, format = req.params[1];
|
|
res.end(resource + ' as ' + format);
|
|
});
|
|
|
|
request(app)
|
|
.get('/api/users/foo.bar.json')
|
|
.expect('users/foo.bar as json', done);
|
|
})
|
|
|
|
it('should work cross-segment', function(done){
|
|
var app = express();
|
|
|
|
app.get('/api*', function(req, res){
|
|
res.send(req.params[0]);
|
|
});
|
|
|
|
request(app)
|
|
.get('/api')
|
|
.expect('', function(){
|
|
request(app)
|
|
.get('/api/hey')
|
|
.expect('/hey', done);
|
|
});
|
|
})
|
|
|
|
it('should allow naming', function(done){
|
|
var app = express();
|
|
|
|
app.get('/api/:resource(*)', function(req, res){
|
|
var resource = req.params.resource;
|
|
res.end(resource);
|
|
});
|
|
|
|
request(app)
|
|
.get('/api/users/0.json')
|
|
.expect('users/0.json', done);
|
|
})
|
|
|
|
it('should not be greedy immediately after param', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/:user*', function(req, res){
|
|
res.end(req.params.user);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/122')
|
|
.expect('122', done);
|
|
})
|
|
|
|
it('should eat everything after /', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/:user*', function(req, res){
|
|
res.end(req.params.user);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/122/aaa')
|
|
.expect('122', done);
|
|
})
|
|
|
|
it('should span multiple segments', function(done){
|
|
var app = express();
|
|
|
|
app.get('/file/*', function(req, res){
|
|
res.end(req.params[0]);
|
|
});
|
|
|
|
request(app)
|
|
.get('/file/javascripts/jquery.js')
|
|
.expect('javascripts/jquery.js', done);
|
|
})
|
|
|
|
it('should be optional', function(done){
|
|
var app = express();
|
|
|
|
app.get('/file/*', function(req, res){
|
|
res.end(req.params[0]);
|
|
});
|
|
|
|
request(app)
|
|
.get('/file/')
|
|
.expect('', done);
|
|
})
|
|
|
|
it('should require a preceeding /', function(done){
|
|
var app = express();
|
|
|
|
app.get('/file/*', function(req, res){
|
|
res.end(req.params[0]);
|
|
});
|
|
|
|
request(app)
|
|
.get('/file')
|
|
.expect(404, done);
|
|
})
|
|
})
|
|
|
|
describe(':name', function(){
|
|
it('should denote a capture group', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/:user', function(req, res){
|
|
res.end(req.params.user);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/tj')
|
|
.expect('tj', done);
|
|
})
|
|
|
|
it('should match a single segment only', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/:user', function(req, res){
|
|
res.end(req.params.user);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/tj/edit')
|
|
.expect(404, done);
|
|
})
|
|
|
|
it('should allow several capture groups', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/:user/:op', function(req, res){
|
|
res.end(req.params.op + 'ing ' + req.params.user);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/tj/edit')
|
|
.expect('editing tj', done);
|
|
})
|
|
})
|
|
|
|
describe(':name?', function(){
|
|
it('should denote an optional capture group', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/:user/:op?', function(req, res){
|
|
var op = req.params.op || 'view';
|
|
res.end(op + 'ing ' + req.params.user);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/tj')
|
|
.expect('viewing tj', done);
|
|
})
|
|
|
|
it('should populate the capture group', function(done){
|
|
var app = express();
|
|
|
|
app.get('/user/:user/:op?', function(req, res){
|
|
var op = req.params.op || 'view';
|
|
res.end(op + 'ing ' + req.params.user);
|
|
});
|
|
|
|
request(app)
|
|
.get('/user/tj/edit')
|
|
.expect('editing tj', done);
|
|
})
|
|
})
|
|
|
|
describe('.:name', function(){
|
|
it('should denote a format', function(done){
|
|
var app = express();
|
|
|
|
app.get('/:name.:format', function(req, res){
|
|
res.end(req.params.name + ' as ' + req.params.format);
|
|
});
|
|
|
|
request(app)
|
|
.get('/foo.json')
|
|
.expect('foo as json', function(){
|
|
request(app)
|
|
.get('/foo')
|
|
.expect(404, done);
|
|
});
|
|
})
|
|
})
|
|
|
|
describe('.:name?', function(){
|
|
it('should denote an optional format', function(done){
|
|
var app = express();
|
|
|
|
app.get('/:name.:format?', function(req, res){
|
|
res.end(req.params.name + ' as ' + (req.params.format || 'html'));
|
|
});
|
|
|
|
request(app)
|
|
.get('/foo')
|
|
.expect('foo as html', function(){
|
|
request(app)
|
|
.get('/foo.json')
|
|
.expect('foo as json', done);
|
|
});
|
|
})
|
|
})
|
|
|
|
describe('when next() is called', function(){
|
|
it('should continue lookup', function(done){
|
|
var app = express()
|
|
, calls = [];
|
|
|
|
app.get('/foo/:bar?', function(req, res, next){
|
|
calls.push('/foo/:bar?');
|
|
next();
|
|
});
|
|
|
|
app.get('/bar', function(req, res){
|
|
assert(0);
|
|
});
|
|
|
|
app.get('/foo', function(req, res, next){
|
|
calls.push('/foo');
|
|
next();
|
|
});
|
|
|
|
app.get('/foo', function(req, res, next){
|
|
calls.push('/foo 2');
|
|
res.end('done');
|
|
});
|
|
|
|
request(app)
|
|
.get('/foo')
|
|
.expect('done', function(){
|
|
calls.should.eql(['/foo/:bar?', '/foo', '/foo 2']);
|
|
done();
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('when next(err) is called', function(){
|
|
it('should break out of app.router', function(done){
|
|
var app = express()
|
|
, calls = [];
|
|
|
|
app.get('/foo/:bar?', function(req, res, next){
|
|
calls.push('/foo/:bar?');
|
|
next();
|
|
});
|
|
|
|
app.get('/bar', function(req, res){
|
|
assert(0);
|
|
});
|
|
|
|
app.get('/foo', function(req, res, next){
|
|
calls.push('/foo');
|
|
next(new Error('fail'));
|
|
});
|
|
|
|
app.get('/foo', function(req, res, next){
|
|
assert(0);
|
|
});
|
|
|
|
app.use(function(err, req, res, next){
|
|
res.end(err.message);
|
|
})
|
|
|
|
request(app)
|
|
.get('/foo')
|
|
.expect('fail', function(){
|
|
calls.should.eql(['/foo/:bar?', '/foo']);
|
|
done();
|
|
})
|
|
})
|
|
})
|
|
|
|
it('should allow rewriting of the url', function(done){
|
|
var app = express();
|
|
|
|
app.get('/account/edit', function(req, res, next){
|
|
req.user = { id: 12 }; // faux authenticated user
|
|
req.url = '/user/' + req.user.id + '/edit';
|
|
next();
|
|
});
|
|
|
|
app.get('/user/:id/edit', function(req, res){
|
|
res.send('editing user ' + req.params.id);
|
|
});
|
|
|
|
request(app)
|
|
.get('/account/edit')
|
|
.expect('editing user 12', done);
|
|
})
|
|
|
|
it('should be chainable', function(){
|
|
var app = express();
|
|
app.get('/', function(){}).should.equal(app);
|
|
})
|
|
})
|